零基础到项目实战:Node.js版Selenium WebDriver教程

在当今数字化时代,Web应用程序的质量和性能至关重要。为了确保这些应用的可靠性,自动化测试成为一种不可或缺的工具。Selenium,作为自动化测试领域的瑰宝,为我们提供了无限可能。本教程将深入介绍Selenium,以及如何结合Node.js发挥其最大潜力。


Selenium基础

Selenium不仅是一个强大的自动化测试框架,更是开源的,允许我们以多种方式实现自动化。其中,Selenium WebDriver是其核心组件之一,为浏览器自动化提供了出色的支持。在本部分,我们将全面解析Selenium的基础概念,重点聚焦于Node.js版本的WebDriver。

环境设置

安装和配置
使用npm安装selenium-webdriver模块

在这一步,我们将通过Node.js的包管理工具npm安装Selenium WebDriver模块。打开你的终端或命令提示符,并执行以下命令:

npm install selenium-webdriver 

这将下载并安装最新版本的selenium-webdriver模块,为我们提供Selenium WebDriver的Node.js接口。

配置和管理浏览器驱动器

安装完selenium-webdriver后,我们需要配置浏览器驱动器,以便Selenium可以与浏览器进行交互。具体的配置取决于你使用的浏览器和操作系统。以下是配置ChromeDriver的简要示例:


const { Builder } = require('selenium-webdriver');const chrome = require('selenium-webdriver/chrome');const driver = new Builder().forBrowser('chrome').setChromeOptions(new chrome.Options().headless()) // 可选,用于无头模式.build();// 现在你可以使用driver与浏览器进行交互了

确保你已经下载了相应浏览器驱动器,并将其路径加入系统的PATH环境变量中。


第一个WebDriver脚本

在这一步,我们将通过编写一个简单的Node.js脚本来启动浏览器,并进行一些基本的操作。创建一个新的文件,例如firstScript.js,并输入以下代码:

 

const { Builder, By, Key, until } = require('selenium-webdriver')async function runFirstScript() {// 创建一个WebDriver实例const driver = new Builder().forBrowser('chrome').build()try {// 导航到网页await driver.get('https://www.baidu.com')// 查找一个元素并输入文本const searchBox = await driver.findElement(By.id('kw'))await searchBox.sendKeys('Selenium WebDriver', Key.RETURN)// 等待搜索结果加载完成await driver.wait(until.elementLocated(By.css('#content_left .result')),5000)console.log('第一个WebDriver脚本执行成功!')} finally {// 延迟2秒await new Promise((resolve) => setTimeout(resolve, 2000))// 关闭浏览器await driver.quit()}}runFirstScript()

执行该脚本:

node firstScript.js 

你将看到浏览器启动,导航到https://www.baidu.com,在搜索框中输入关键字并回车,最后等待搜索结果页面加载完毕。这是你的第一个Selenium WebDriver脚本!

基本操作

定位元素
使用selenium-webdriver模块定位元素

在Selenium中,定位元素是自动化测试的关键步骤之一。通过selenium-webdriver模块,我们可以使用多种方法来定位网页上的元素。以下是一些基本的定位方法示例:

 

const { Builder, By } = require('selenium-webdriver');async function locateElements() {const driver = new Builder().forBrowser('chrome').build();try {await driver.get('https://www.example.com');// 通过ID定位元素const elementById = await driver.findElement(By.id('elementId'));// 通过类名定位元素const elementByClassName = await driver.findElement(By.className('className'));// 通过标签名定位元素const elementByTagName = await driver.findElement(By.tagName('tagName'));// 通过名称定位元素const elementByName = await driver.findElement(By.name('elementName'));// 通过XPath定位元素const elementByXPath = await driver.findElement(By.xpath('//xpathExpression'));// 通过CSS选择器定位元素const elementByCss = await driver.findElement(By.css('cssSelector'));console.log('元素定位成功!');} finally {await driver.quit();}}locateElements();

通过上述方法,你可以根据元素的ID、类名、标签名、名称、XPath或CSS选择器来定位元素。根据实际需要选择最合适的方法。


交互操作
通过WebDriver进行交互操作

一旦我们成功地定位了元素,下一步就是与这些元素进行交互。这可能包括在输入框中输入文本、点击按钮、选择下拉框等。以下是一些基本的交互操作示例:

 

const { Builder, By, Key } = require('selenium-webdriver');async function interactWithElements() {const driver = new Builder().forBrowser('chrome').build();try {await driver.get('https://www.example.com');// 在输入框中输入文本const searchBox = await driver.findElement(By.name('q'));await searchBox.sendKeys('Selenium WebDriver', Key.RETURN);// 点击按钮const submitButton = await driver.findElement(By.id('submitBtn'));await submitButton.click();// 选择下拉框中的选项const dropdown = await driver.findElement(By.tagName('select'));await dropdown.findElement(By.css('option[value="optionValue"]')).click();console.log('交互操作成功!');} finally {await driver.quit();}}interactWithElements();

在这个示例中,我们演示了如何在输入框中输入文本、点击按钮以及选择下拉框中的选项。根据页面上的元素类型和操作需求,你可以进一步扩展这些基本的交互操作。

高级操作

等待机制
使用selenium-webdriver提供的等待机制

等待机制是Selenium中用于处理页面加载和元素可见性的关键特性。在进行自动化测试时,经常需要等待某个条件的发生,以确保测试步骤按预期执行。以下是等待机制的基本使用示例:

 

const { Builder, By, until } = require('selenium-webdriver');async function waitForElement() {const driver = new Builder().forBrowser('chrome').build();try {await driver.get('https://www.example.com');// 等待元素出现在页面上const element = await driver.wait(until.elementLocated(By.id('elementId')), 5000);// 等待元素可见await driver.wait(until.elementIsVisible(element), 5000);console.log('等待成功!');} finally {await driver.quit();}}waitForElement();

在这个例子中,我们使用driver.wait来等待页面上的元素,确保它在指定的时间内出现,并且可见。等待机制可以帮助我们更好地处理异步加载和页面变化的情况。


多窗口和弹窗处理
处理多个浏览器窗口之间的切换

当一个应用程序涉及到多个浏览器窗口时,我们需要能够在这些窗口之间进行切换。以下是一个简单的多窗口切换示例:

 

const { Builder, By } = require('selenium-webdriver');async function switchToWindow() {const driver = new Builder().forBrowser('chrome').build();try {await driver.get('https://www.example.com');// 打开新窗口await driver.executeScript("window.open('https://www.example2.com', '_blank');");// 获取所有窗口的句柄const windowHandles = await driver.getAllWindowHandles();// 切换到新窗口await driver.switchTo().window(windowHandles[1]);console.log('已切换到新窗口!');} finally {await driver.quit();}}switchToWindow();
处理弹窗(Alert、Confirm、Prompt)

在自动化测试中,我们可能会遇到各种弹窗,例如Alert、Confirm和Prompt。以下是处理这些弹窗的基本示例:

 

const { Builder, By } = require('selenium-webdriver');async function handleAlert() {const driver = new Builder().forBrowser('chrome').build();try {await driver.get('https://www.example.com');// 触发一个带有文本的Alertawait driver.executeScript("alert('Hello, WebDriver!');");// 切换到Alertconst alert = await driver.switchTo().alert();// 获取Alert的文本const alertText = await alert.getText();console.log('Alert文本:', alertText);// 关闭Alertawait alert.accept();console.log('已处理Alert!');} finally {await driver.quit();}}handleAlert();

在这两个示例中,我们演示了如何切换到新窗口以及如何处理弹窗。在实际测试中,这些技术对于处理多窗口和各种弹窗非常有用。

进阶主题

数据驱动测试
从外部数据源读取测试数据

数据驱动测试是一种强大的测试方法,可以通过外部数据源提供测试数据,使测试用例更灵活和可维护。以下是一个简单的数据驱动测试的示例:

 

const { Builder, By } = require('selenium-webdriver');const testData = require('./testdata.json'); // 假设有一个JSON文件包含测试数据async function dataDrivenTest() {const driver = new Builder().forBrowser('chrome').build();try {await driver.get('https://www.example.com');// 循环遍历测试数据for (const data of testData) {// 从测试数据中获取用户名和密码const username = data.username;const password = data.password;// 找到用户名和密码输入框,并输入值const usernameInput = await driver.findElement(By.id('username'));await usernameInput.sendKeys(username);const passwordInput = await driver.findElement(By.id('password'));await passwordInput.sendKeys(password);// 其他测试步骤...// 清空输入框,准备下一组数据await usernameInput.clear();await passwordInput.clear();}console.log('数据驱动测试完成!');} finally {await driver.quit();}}dataDrivenTest();

在这个例子中,我们假设有一个名为testdata.json的JSON文件,包含多组测试数据。通过循环遍历测试数据,我们可以动态地输入不同的用户名和密码,从而进行数据驱动测试。


页面对象模型(POM)
POM的概念和优势

页面对象模型(POM)是一种设计模式,旨在提高测试代码的可维护性和可读性。在POM中,页面的每个元素和每个操作都被封装在一个单独的类中。以下是一个简单的POM示例:

 

// LoginPage.jsconst { By } = require('selenium-webdriver');class LoginPage {constructor(driver) {this.driver = driver;this.usernameInput = By.id('username');this.passwordInput = By.id('password');this.loginButton = By.id('loginButton');}async login(username, password) {await this.driver.findElement(this.usernameInput).sendKeys(username);await this.driver.findElement(this.passwordInput).sendKeys(password);await this.driver.findElement(this.loginButton).click();}}module.exports = LoginPage;

在测试脚本中使用:

 

const { Builder } = require('selenium-webdriver');const LoginPage = require('./LoginPage');async function testWithPOM() {const driver = new Builder().forBrowser('chrome').build();const loginPage = new LoginPage(driver);try {await driver.get('https://www.example.com');// 使用POM执行登录操作await loginPage.login('testuser', 'password123');console.log('POM测试完成!');} finally {await driver.quit();}}testWithPOM();

POM通过将每个页面的元素和操作封装在单独的类中,提高了代码的可维护性。当页面结构发生变化时,只需要更新页面对应的类,而不必修改测试脚本。

这两个进阶主题可以在测试代码中提供更高层次的抽象,使测试更易于维护和扩展。

测试框架集成

测试框架介绍
在Node.js中使用测试框架

测试框架是用于组织和执行测试的工具,可以提供更丰富的功能,例如测试用例的组织、断言库、测试报告等。在Node.js中,常见的测试框架有Mocha、Jest等。以下是一个简单的示例,演示如何使用Mocha进行测试:

首先,安装Mocha:

npm install mocha --save-dev 

然后,创建一个测试文件,例如test.js


// test.jsconst assert = require('assert');describe('Example Test Suite', () => {it('should pass a simple test', () => {assert.strictEqual(1 + 1, 2);});it('should handle asynchronous code', (done) => {setTimeout(() => {assert.strictEqual(3 * 3, 9);done();}, 1000);});});

运行测试:

npx mocha test.js 

这是一个简单的Mocha测试文件,包含两个测试用例。你可以根据需要组织测试套件和编写更多测试用例。


测试报告生成
使用测试框架生成详细的测试报告

生成详细的测试报告是测试流程中的关键步骤,可以更好地理解测试结果和问题。在Node.js中,有一些工具可以生成漂亮的测试报告,例如mochawesomejest-html-reporters

以下是一个使用mochawesome生成测试报告的简单示例:

首先,安装mochawesome

npm install mochawesome --save-dev 

修改Mocha的执行命令:


// package.json"scripts": {"test": "mocha test.js --reporter mochawesome"}

然后,运行测试并生成报告:

npm test 

你将在项目目录中生成一个mochawesome-report文件夹,里面包含详细的HTML测试报告。

以上是一个简单的测试框架集成和测试报告生成的例子。根据实际项目的需要,可以选择适合你的测试框架和报告生成工具,以提高测试的可读性和易管理性。

性能优化和最佳实践

提高效率的并行测试
利用Node.js的并行执行特性

通过Node.js的并行执行特性,实现在多个浏览器和平台上同时运行测试,提高整体测试效率。使用concurrently等工具,将测试任务分发到多个进程,充分利用计算资源,缩短测试执行时间。


编写可维护、稳定和可扩展的测试代码的最佳实践
关键建议和最佳实践
  • 良好的命名和组织: 使用清晰、描述性的命名,合理组织测试用例和代码结构。

  • 版本控制: 使用Git等版本控制工具管理测试代码,确保代码的版本追踪和团队协作。

  • 错误处理和日志: 实现健壮的错误处理,记录详细日志以便排查问题。

  • 隔离测试数据: 使用隔离的测试数据,确保测试用例的独立性和可重复性。

  • 定期维护和更新: 定期检查和更新测试代码,保持与应用程序的同步。

  • 并行测试执行: 利用并行测试来提高测试效率,加速整体测试过程。

  • 代码审查: 进行团队内部的代码审查,确保编码标准和最佳实践的一致性。

  • 文档和注释: 提供清晰的文档和注释,帮助团队理解代码的设计和目的。

  • 测试环境一致性: 在测试环境中保持一致性,包括浏览器版本、驱动程序版本等。

  • 定期审查和改进: 定期审查测试策略和代码,寻找改进的机会,持续提高测试质量。

通过遵循这些最佳实践,你可以建立一个高效、稳定且易于维护的自动化测试框架,提高团队的测试效率和整体软件质量。

实战项目

构建一个简单的自动化测试项目

在这一部分,我们将通过一个简单的自动化测试项目来帮助读者应用前面学到的知识。我们的项目将基于以下几个步骤:

项目概述

我们将创建一个自动化测试项目,测试一个简单的登录页面。项目将包括以下关键组件:

  • 项目结构设计: 我们会设计一个清晰的项目结构,包括 tests(存放测试脚本)、pages(存放页面对象)、config(存放配置文件)等。

  • 测试脚本编写: 我们会编写测试脚本,覆盖登录页面的主要功能和交互。

  • 数据驱动测试: 我们将使用外部的JSON文件,通过数据驱动的方式执行多组测试。

  • 测试框架集成: 我们会集成Mocha测试框架,以组织和执行测试。

  • 报告生成: 我们将使用Mocha生成详细的测试报告,以更好地理解测试结果。

项目实现步骤

步骤 1: 创建项目文件夹结构

首先,让我们创建项目文件夹结构:


- automation-project- tests- loginTest.js- pages- loginPage.js- config- config.json

步骤 2: 编写测试用例

在 tests 文件夹中,创建 loginTest.js

 

const { Builder, By, Key } = require('selenium-webdriver');const assert = require('assert');const LoginPage = require('../pages/loginPage');const config = require('../config/config.json');describe('Login Test Suite', function () {let driver;let loginPage;before(async function () {driver = new Builder().forBrowser(config.browser).build();loginPage = new LoginPage(driver);});after(async function () {await driver.quit();});it('should navigate to the login page', async function () {await loginPage.navigateToLoginPage();const title = await driver.getTitle();assert.strictEqual(title, 'Login Page');});it('should login with valid credentials', async function () {await loginPage.login('username', 'password');const welcomeMessage = await loginPage.getWelcomeMessage();assert.strictEqual(welcomeMessage, 'Welcome, User!');});it('should handle invalid login', async function () {await loginPage.login('invalidUser', 'invalidPassword');const errorMessage = await loginPage.getErrorMessage();assert.strictEqual(errorMessage, 'Invalid username or password.');});});

步骤 3: 设计页面对象

在 pages 文件夹中,创建 loginPage.js

 

const { By, Key, until } = require('selenium-webdriver');class LoginPage {constructor(driver) {this.driver = driver;this.usernameInput = By.id('username');this.passwordInput = By.id('password');this.loginButton = By.id('loginButton');this.welcomeMessage = By.id('welcomeMessage');this.errorMessage = By.id('errorMessage');}async navigateToLoginPage() {await this.driver.get('https://example.com/login');}async login(username, password) {const usernameInput = await this.driver.findElement(this.usernameInput);await usernameInput.sendKeys(username);const passwordInput = await this.driver.findElement(this.passwordInput);await passwordInput.sendKeys(password);const loginButton = await this.driver.findElement(this.loginButton);await loginButton.click();}async getWelcomeMessage() {const welcomeMessageElement = await this.driver.findElement(this.welcomeMessage);return await welcomeMessageElement.getText();}async getErrorMessage() {const errorMessageElement = await this.driver.findElement(this.errorMessage);return await errorMessageElement.getText();}}module.exports = LoginPage;

步骤 4: 配置文件设置

在 config 文件夹中,创建 config.json


{"browser": "chrome"}

步骤 5: 数据驱动测试

通过创建测试数据文件 testData.json


[{"username": "validUser","password": "validPassword"},{"username": "invalidUser","password": "invalidPassword"}]

在 loginTest.js 中使用数据驱动测试:

 

const testData = require('../config/testData.json');// ...it('should login with valid and invalid credentials', async function () {for (const data of testData) {await loginPage.login(data.username, data.password);if (data.username === 'validUser') {const welcomeMessage = await loginPage.getWelcomeMessage();assert.strictEqual(welcomeMessage, 'Welcome, User!');} else {const errorMessage = await loginPage.getErrorMessage();assert.strictEqual(errorMessage, 'Invalid username or password.');}}});

步骤 6: 测试框架集成

在 package.json 中添加测试脚本:


"scripts": {"test": "mocha tests/loginTest.js --reporter mochawesome"}

步骤 7: 报告生成集成

安装 mochawesome

npm install mochawesome --save-dev 

执行测试并生成报告:

npm test 

这样,我们就成功构建了一个简单的自动化测试项目,覆盖了测试脚本编写、数据驱动测试、测试框架集成和报告生成等方面。读者可以根据这个示例项目的结构和实现来扩展和应用到实际项目中。

结尾

这次教程带你玩转Node.js版的Selenium WebDriver,是不是觉得自动化测试有点神奇?我们学了点基础知识,搞定了环境设置,还把操作搞得很高级。最后,我们通过一个项目,让你亲自动手,感受一下自动化测试的魅力。有兴趣的话,可以深入了解Node.js,瞄一眼其他测试框架,别忘了多动手实践,加深印象哦!

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:【文末自行领取】

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/427681.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

硬盘数据恢复必备:4 款强大硬盘数据恢复软件推荐!

在数字化的时代,我们的生活和工作越来越离不开电脑,而硬盘作为重要的数据存储设备,一旦出现数据丢失的情况,往往会给我们带来极大的困扰。别担心,今天就为大家推荐四款强大的硬盘数据恢复软件,帮助你轻松找…

优化算法(三)—模拟退火算法(附MATLAB程序)

模拟退火算法(Simulated Annealing, SA)是一种基于概率的优化算法,旨在寻找全局最优解。该算法模拟金属退火过程中的物质冷却过程,逐渐降低系统的“温度”以达到全局优化的效果。它特别适用于解决复杂的组合优化问题。 一、模拟退…

[羊城杯 2020]Blackcat1

知识点:数组加密绕过 进入页面熟悉的web三部曲(url地址,web源代码,web目录扫描) url地址没有什么东西去看看源代码. 这有一个mp3文件点一下看看. 在最后面发现了 PHP源码. if(empty($_POST[Black-Cat-Sheriff]) || em…

Android Studio报错: Could not find pub.devrel:easypermissions:0.3.0, 改用linux编译

在Android studio中去编译开源的仓库,大概率就是各种编译不过,一堆错误,一顿改错,基本上会耗费非常多时间,比如: 这个就是改gradle版本,改成7.2 ,修改完成之后,还有其他报…

翻页时钟 2.0-自动置顶显示,点击小时切换显示标题栏不显示标题栏-供大家学习研究参考

更新内容 自动置顶显示点击小时切换显示标题栏,(显示标题栏后可移动时钟位置,鼠标拖动边框调整时钟大小)不显示标题栏时,透明部分光标可穿透修正一个显示bu 下载地址: https://download.csdn.net/download…

iPhone 16系列:熟悉的味道,全新的体验

来看看iPhone 16和Plus这两个新成员,实话说,它们和之前曝光的样子几乎完全一致。下面我们就一起来细数一下这次的几大变化吧。 外观设计:焕然一新 首先,最显眼的变化就是后置镜头模组的布局调整为了垂直排列。这一改变使得整个背…

小程序开发设计-第一个小程序:安装开发者工具③

上篇文章导航: 小程序开发设计-第一个小程序:注册小程序开发账号②-CSDN博客https://blog.csdn.net/qq_60872637/article/details/142219035?spm1001.2014.3001.5501 须知:不同版本选项有所不同,并无大碍。 第一个小程序&#…

《黑神话悟空》开发框架与战斗系统解析

本文主要围绕《黑神话悟空》的开发框架与战斗系统解析展开 主要内容 《黑神话悟空》采用的技术栈 《黑神话悟空》战斗系统的实现方式 四种攻击模式 连招系统的创建 如何实现高扩展性的战斗系统 包括角色属性系统、技能配置文件和逻辑节点的抽象等关键技术点 版权声明 本…

中国书法—孙溟㠭浅析碑帖《爨宝子碑》

中国书法——孙溟㠭浅析碑帖《爨宝子碑》 《爨宝子碑》 全称是《晋故振威将军建宁太守爨宝子之墓》,此碑刻于东晋大亨四年(公元405年)属楷书体。 《爨宝子碑》 《爨宝子碑》 至清朝乾隆四十三年(1778年)在云南南宁&…

【开源免费】基于SpringBoot+Vue.JS网上购物商城(JAVA毕业设计)

本文项目编号 T 041 ,文末自助获取源码 \color{red}{T041,文末自助获取源码} T041,文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析5.4 用例设计 六、核…

PHP邮箱系统:从入门到实战搭建教程指南!

PHP邮箱系统配置教程?如何选用合适的PHP邮箱系统库? 为了满足个性化和定制化的需求,许多开发者选择使用PHP来搭建自己的邮箱系统。AokSend将带你从入门到实战,详细介绍如何搭建一个功能完善的PHP邮箱系统。 PHP邮箱系统&#xf…

C#软键盘设计字母数字按键处理相关事件函数

应用场景:便携式设备和检测设备等小型设备经常使用触摸屏来代替键盘鼠标的使用,因此在查询和输入界面的文本或者数字输入控件中使用软件盘来代替真正键盘的输入。 软键盘界面:软键盘界面实质上就是一个普通的窗体上面摆放了很多图片按钮&…

Golang | Leetcode Golang题解之第416题分割等和子集

题目&#xff1a; 题解&#xff1a; func canPartition(nums []int) bool {n : len(nums)if n < 2 {return false}sum, max : 0, 0for _, v : range nums {sum vif v > max {max v}}if sum%2 ! 0 {return false}target : sum / 2if max > target {return false}dp …

对象检测边界框损失 – 从IOU到ProbIOU

1.概述 目标检测损失函数的选择在目标检测问题建模中至关重要。通常&#xff0c;目标检测需要两个损失函数&#xff0c;一个用于对象分类&#xff0c;另一个用于边界框回归&#xff08;BBR&#xff09;。本文将重点介绍 IoU 损失函数&#xff08;GIoU 损失、DIoU 损失和 CIoU 损…

一、Numpy使用

1、numpy的简单使用 import numpy as np #利用as给numpy起一个别名np# 使用array来承接这个数组 array np.array([[1,2,3],[2,3,4]])print(array) print("number of dim:", array.ndim) # ndim 数组维度 print("shape:", array.shape) # 数组的形…

Spring Boot从0到1 -day02

目录 学习目标Spring Boot 的基本配置启动类与核心注解SpringBootApplicationSpring Boot 的全局配置文件1. application.properties2. application.ymlSpring 中Spring Boot Application注解的作用 自动配置原理1. 自动配置类2. 自动配置的发现示例3. 自定义自动配置 条件注解…

Prompt最佳实践|指定输出的长度

在OpenAI的官方文档中已经提供了[Prompt Enginerring]的最佳实践&#xff0c;目的就是帮助用户更好的使用ChatGPT 编写优秀的提示词我一共总结了9个分类&#xff0c;本文讲解第6个分类&#xff1a;指定输出长度 提供更多的细节要求模型扮演角色使用分隔符指定任务步骤提供样例…

Swagger 概念和使用以及遇到的问题

前言 接口文档对于前后端开发人员都十分重要。尤其近几年流行前后端分离后接口文档又变 成重中之重。接口文档固然重要,但是由于项目周期等原因后端人员经常出现无法及时更新&#xff0c; 导致前端人员抱怨接口文档和实际情况不一致。 很多人员会抱怨别人写的接口文档不…

从黎巴嫩电子通信设备爆炸看如何防范网络电子袭击

引言&#xff1a; 在当今数字化时代&#xff0c;电子通信设备已成为我们日常生活中不可或缺的一部分。然而&#xff0c;近期黎巴嫩发生的电子设备爆炸事件提醒我们&#xff0c;这些设备也可能成为危险的武器。本文将深入探讨电子袭击的原理、防范措施&#xff0c;以及网络智能…

【论文阅读】Face2Diffusion for Fast and Editable Face Personalization

code&#xff1a;mapooon/Face2Diffusion: [CVPR 2024] Face2Diffusion for Fast and Editable Face Personalization https://arxiv.org/abs/2403.05094 (github.com) 论文 介绍 目标&#xff1a;向 T2I 模型不知道的图像中插入特定概念&#xff08;例如某人的脸&#xff…