《基于Selenium的网页聊天室自动化测试实战报告》

一、项目背景与技术选型

项目简介

  • 目标系统:基于WebSocket的实时聊天室

  • 核心功能:用户注册/登录、会话框发送信息、好友列表、信息发送

  • 技术栈:html + Springboot + MySQL数据库

为什么选择Selenium

  • 支持多浏览器兼容性测试(Chrome/Firefox/Edge)

  • 完善的元素定位体系(XPath/CSS Selector)

  • 动态内容处理能力(WebDriverWait机制)

  • 跨平台执行能力(Windows/Linux/macOS)

测试环境

在开始测试之前,我们需要准备好测试环境。以下是测试所需的硬件和软件环境:
4. 硬件:普通个人电脑

  1. 操作系统:Windows 10 或 Windows 11

  2. 浏览器:Chrome(版本 128.0.6613.84 或以上)

  3. 项目运行环境:maven、JDK1.8

  4. 自动化测试工具:Selenium + JUnit5

二、测试用例设计+手动测试

1. 用户注册

用户注册是聊天室的第一步,我们需要确保用户能够成功注册账号。以下是注册功能的测试用例:

  • 测试场景1:输入正确的用户名和密码,点击注册按钮。

    • 预期结果:注册成功,弹出提示框"注册成功!"。
  • 测试场景2:输入已存在的用户名和密码,点击注册按钮。

    • 预期结果:注册失败,弹出提示框"注册失败!"。
  • 测试场景3:用户名或密码为空,点击注册按钮。

    • 预期结果:注册失败,弹出提示框"您输入的用户名或密码为空!"。
2. 用户登录

用户登录是进入聊天室的关键步骤,以下是登录功能的测试用例:

  • 测试场景1:输入正确的用户名和密码,点击登录按钮。

    • 预期结果:弹出提示框"登录成功",登录成功,跳转到会话页面。
  • 测试场景2:输入正确的用户名,错误的密码,点击登录按钮。

    • 预期结果:登录失败,弹出提示框"登录失败!"。
  • 测试场景3:输入未注册的用户名和密码,点击登录按钮。

    • 预期结果:登录失败,弹出提示框"登录失败!"。
  • 测试场景4:用户名或密码为空,点击登录按钮。

    • 预期结果:登录失败,弹出提示框"您输入的用户名或密码为空!"。
3. 会话功能

会话功能是聊天室的核心,以下是会话功能的测试用例:

  • 测试场景1:未登录状态下,打开会话页面。

    • 预期结果:弹出提示框"当前用户未登录!"。
  • 测试场景2:登录状态下,点击会话按钮。

    • 预期结果:会话按钮变绿,跳转会话列表页面。
  • 测试场景3:点击具体会话,查看消息。

    • 预期结果:消息页面显示当前会话的用户名和消息内容。
4. 消息发送和接收

消息发送和接收是聊天室的核心功能,以下是相关测试用例:

  • 测试场景1:在输入框中输入消息,点击发送按钮。

    • 预期结果:消息发送成功,输入框清空,消息页面显示发送的内容。
  • 测试场景2:发送消息后,接收方查看消息。

    • 预期结果:接收方能够看到发送方的消息。

等等场景

三、自动化测试实现

1.pom.xml文件引入依赖

java 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>ChatroomAutoTest</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>io.github.bonigarcia</groupId>
            <artifactId>webdrivermanager</artifactId>
            <version>5.8.0</version>
        </dependency>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>4.0.0</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>RELEASE</version>
            <scope>test</scope>
        </dependency><!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.9.1</version>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-params</artifactId>
            <version>5.9.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-params -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-params</artifactId>
            <version>5.9.1</version>
        </dependency>
        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-suite</artifactId>
            <version>1.9.1</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.junit.platform/junit-platform-suite -->
        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-suite</artifactId>
            <version>1.9.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-engine -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>5.9.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

</project>
  1. 引入自动化测试工具

    • selenium-java 用于编写和执行自动化测试脚本。

    • webdrivermanager 用于自动管理 WebDriver 驱动程序,避免手动下载和配置。

  2. 引入文件操作工具

    • commons-io 提供文件和 IO 操作的工具类,简化文件处理逻辑。
  3. 单元测试框架:通过 JUnit 5,可以编写和运行单元测试,验证网页聊天室的各项功能是否正常工作。

  4. 参数化测试:通过 JUnit Jupiter Params,可以为测试方法提供不同的参数,减少重复代码。

  5. 测试套件管理:通过 JUnit Platform Suite,可以将多个测试类或测试模块组合在一起,一次性运行。

2.写下AutoTestUtils类

方便在每个测试用例中来

  • 获取浏览器驱动
  • 获取屏幕截图,将用例执行结果保存下来
  • 获取当前时间(记录每个屏幕截图是什么时候拍摄的)
java 复制代码
package common;

import io.github.bonigarcia.wdm.WebDriverManager;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.Date;

public class Utils {
    public static WebDriver driver;

    public static WebDriver createDriver(){
        if (driver == null){
            WebDriverManager.chromedriver().setup();
            ChromeOptions options = new ChromeOptions();
            //允许访问所有链接
            options.addArguments("--remote-allow-origins=*");

            driver = new ChromeDriver(options);

            //等待
            driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(2));

        }
        return driver;
    }
    public Utils(String url){
        //调用driver对象
        driver = createDriver();
        //访问url
        driver.get(url);
    }
    public void getScreenShot(String str) throws IOException {
        //      ./src/test/image/
        //                      /2025-02-15/
        //                                  /test01-174530.png
        //                                  /test02-174530.png
        //                      /2025-02-16/
        //                                  /test01-174530.png
        //                                  /test02-174530.png
        //屏幕截图
        SimpleDateFormat sim1 = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat sim2 = new SimpleDateFormat("HHmmssSS");

        String dirTime = sim1.format(System.currentTimeMillis());
        String fileTime = sim2.format(System.currentTimeMillis());

        //.src/test/image/2025-02-15/test-174530.png
        String filename = "./src/test/image" + dirTime + "/" + str + "-" + fileTime + ".png";
        System.out.println("filename:" + filename);
        File srcFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
        //srcFile放到指定位置
        FileUtils.copyFile(srcFile, new File(filename));
    }
}

3.针对各种功能做自动化测试

3.1注册页面功能测试

RegisterPageTest.java

java 复制代码
package Test;

import common.Utils;
import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.openqa.selenium.*;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.io.IOException;
import java.time.Duration;

import static java.lang.Thread.sleep;

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class RegisterPageTest extends Utils {
    //获取到驱动
    private static WebDriver driver = Utils.getDriver();

    /**
     * 打开网页
     * 注册网页一般是从登录页面进入
     */
    @BeforeAll
    public static void openWeb() {
        //打开登录页面
        driver.get("http://127.0.0.1:8080/register.html");
        //再点击登录页面的注册链接按钮
/*
        driver.findElement(By.cssSelector("body > div.login-container > div > div:nth-child(4) > a")).click();
*/
        driver.manage().window().maximize();
    }

    /**
     * 验证网页正常打开
     */
    @Test
    @Order(1)
    public void elementsAppear() throws IOException {
        //用户名输入框
        driver.findElement(By.cssSelector("#username"));
        //密码输入框
        driver.findElement(By.cssSelector("#password"));
        //注册按钮
        driver.findElement(By.cssSelector("#submit"));
        //登录账号链接
/*
        driver.findElement(By.cssSelector("body > div.register-container > div > div:nth-child(4) > a"));
*/
        getScreenShot(getClass().getName());
    }

    /**
     * 注册失败测试用例
     * 参数: 尝试注册已注册用户
     */

    @ParameterizedTest
    @CsvSource({"zhangsan,123"})
    @Order(2)
    public void regFunTest(String username, String password) throws IOException {
        // 输入测试数据
        driver.findElement(By.cssSelector("#username")).sendKeys(username);
        driver.findElement(By.cssSelector("#password")).sendKeys(password);
        driver.findElement(By.cssSelector("#submit")).click();

        // 显式等待弹窗出现(最多等待10秒)
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
        try {
            Alert alert = wait.until(ExpectedConditions.alertIsPresent());
            String actual = alert.getText();
            alert.accept(); // 关闭弹窗

            Assertions.assertEquals("注册失败!", actual);
        } catch (TimeoutException e) {
            // 如果弹窗未出现,直接断言失败
            Assertions.fail("未出现预期弹窗");
        }

        getScreenShot(getClass().getName());
    }

    @ParameterizedTest
    @CsvSource({"zmjjk,123,注册成功!"})
    @Order(3)
    public void regTest(String username, String password, String expect) throws IOException {
        // 输入测试数据
        driver.findElement(By.cssSelector("#username")).clear();
        driver.findElement(By.cssSelector("#password")).clear();
        driver.findElement(By.cssSelector("#username")).sendKeys(username);
        driver.findElement(By.cssSelector("#password")).sendKeys(password);
        driver.findElement(By.cssSelector("#submit")).click();

        // 显式等待弹窗
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
        try {
            Alert alert = wait.until(ExpectedConditions.alertIsPresent());
            String actual = alert.getText();
            alert.accept(); // 关闭弹窗

            Assertions.assertEquals(expect, actual);
        } catch (TimeoutException e) {
            Assertions.fail("未出现预期弹窗");
        }

        getScreenShot(getClass().getName());
    }}

3.2登录页面功能测试

LoginPageTest.java

java 复制代码
package Test;



import common.Utils;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.openqa.selenium.Alert;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

import java.io.IOException;

import static java.lang.Thread.sleep;

public class LoginPageTest extends Utils {

    //获取到驱动
    private static WebDriver driver = Utils.getDriver();

    /**
     * 打开页面
     * 注册页面一般是从登录页面进入
     */
    @BeforeAll
    public static void openWeb() {
        //先打开登录页面
        driver.get("http://127.0.0.1:8080/login.html");
        driver.manage().window().maximize();
    }

    /**
     * 检测登录页面是否能正常打开
     */
    @Test
    @Order(1)
    public void elementsAppear() throws IOException {
        //用户名输入框
        driver.findElement(By.cssSelector("#username"));
        //密码输入框
        driver.findElement(By.cssSelector("#password"));
        //注册账号链接
/*
        driver.findElement(By.cssSelector("body > div.login-container > div > div:nth-child(4) > a"));
*/
        //登录按钮
        driver.findElement(By.cssSelector("#submit"));
        //屏幕截图
        getScreenShot(getClass().getName());
    }

    /**
     * 异常测试登录功能
     * 参数一:尝试登录未注册用户
     * 参数二:密码输入错误,登录账号
     */
    @ParameterizedTest
    @CsvSource({"zhang,123","zhangsan,123456"})
    @Order(2)
    public void loginAbnormalTest(String username,String password) throws InterruptedException, IOException {
        //拿到元素
        WebElement inputUserName = driver.findElement(By.cssSelector("#username"));
        WebElement inputPassword = driver.findElement(By.cssSelector("#password"));
        WebElement button = driver.findElement(By.cssSelector("#submit"));
        //清除用户名,密码
        inputUserName.clear();
        inputPassword.clear();
        //输入账号,密码
        inputUserName.sendKeys(username);
        inputPassword.sendKeys(password);
        //点击登录
        button.click();
        //等待弹窗
        sleep(3000);
        //期望结果
        String expect = "登录失败!";
        String actual = "登录失败!";
        Alert alert = driver.switchTo().alert();
        if(alert != null) {
            alert.accept();
        } else {
            actual = "当前用例执行失败!";
        }
        Assertions.assertEquals(expect,actual);
        //屏幕截图
        getScreenShot(getClass().getName());
    }

    /**
     * 正常登录测试
     */
    @ParameterizedTest
    @CsvSource({"'zhangsan','123','登录成功!'"})
    @Order(3)
    public void loginNormalTest(String userName,String password,String expect) throws InterruptedException, IOException {
        //发现元素
        WebElement inputUserName = driver.findElement(By.cssSelector("#username"));
        WebElement inputPassword = driver.findElement(By.cssSelector("#password"));
        WebElement button = driver.findElement(By.cssSelector("#submit"));
        //清除用户名密码
        inputUserName.clear();
        inputPassword.clear();
        //输入用户名,密码
        inputUserName.sendKeys(userName);
        inputPassword.sendKeys(password);
        //点击登录
        button.click();
        //等待弹窗
        sleep(3000);
        //期望结果
        String actual = driver.switchTo().alert().getText();
        //断言
        Assertions.assertEquals(expect,actual);
        //处理弹窗
        driver.switchTo().alert().accept();
        //屏幕截图
        getScreenShot(getClass().getName());

    }
}

3.3不登录页面功能测试

NoLoginTest.java

java 复制代码
package Test;


import common.Utils;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.Alert;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

import java.io.IOException;

import static java.lang.Thread.sleep;


public class NoLoginTest extends Utils {
    //获取驱动
    private static WebDriver driver = Utils.getDriver();

    @Test
    public void Intercept() throws InterruptedException, IOException {
        //在未登录的情况下,跳转会话页
        driver.get("http://127.0.0.1:8080/client.html");
        sleep(2000);
        //期望结果
        String expect = "当前用户未登录!";
        String actual = "当前用户未登录!";
        Alert alert = driver.switchTo().alert();
        if (alert != null) {
            alert.accept();
        } else {
            actual = "当前用例执行失败";
        }
        //屏幕截图
        getScreenShot(getClass().getName());
        //断言
        Assertions.assertEquals(expect,actual);
    }
}

3.4客户端页面功能测试

ClientPageTest.java

java 复制代码
package Test;


import common.Utils;
import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.openqa.selenium.*;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.io.IOException;
import java.time.Duration;

import static java.lang.Thread.sleep;

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class ClientPageTest extends Utils {
    //获得驱动
    public static WebDriver driver = Utils.getDriver();

    /**
     * 打开会话页面
     */
    @BeforeAll
    public static void openWeb() {
        //先打开会话页面
        driver.get("http://127.0.0.1:8080/client.html");
        driver.manage().window().maximize();
    }

    /**
     * 测试会话页面正常打开
     */
    @Test
    @Order(1)
    public void elementsAppear() throws IOException {
        //主页个人账号名
        driver.findElement(By.cssSelector("body > div.client-container > div > div.left > div.user"));
        //搜索输入框
        driver.findElement(By.cssSelector("body > div.client-container > div > div.left > div.search > input[type=text]"));
        //搜索按钮
        driver.findElement(By.cssSelector("body > div.client-container > div > div.left > div.search > button"));
        //会话标签图
        driver.findElement(By.cssSelector("body > div.client-container > div > div.left > div.tab > div.tab-session"));
        //好友标签图
        driver.findElement(By.cssSelector("body > div.client-container > div > div.left > div.tab > div.tab-friend"));
        //聊天输入框
        driver.findElement(By.cssSelector("body > div.client-container > div > div.right > textarea"));
        //发送按钮
        driver.findElement(By.cssSelector("body > div.client-container > div > div.right > div.ctrl > button"));
        //屏幕截图
        getScreenShot(getClass().getName());
    }


    /**
     * 点击具体会话
     * 检验:消息页面展示当前会话用户名字
     */

    @Test
    @Order(2)
    void SessionList() throws InterruptedException {
        Thread.sleep(3000);
        // 点击第一个会话项
        driver.findElement(By.xpath("//*[@id=\"session-list\"]/li[1]/h3")).click();
        Thread.sleep(3000);

        // 显式等待标题元素加载并可见
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
        WebElement titleElement = wait.until(ExpectedConditions.visibilityOfElementLocated(
                By.cssSelector("body > div.client-container > div > div.right > div.title")
        ));

        // 获取并处理文本
        String actual = titleElement.getText().trim();
        System.out.println("Actual title text: '" + actual + "'");  // 调试输出

        // 断言
        Assertions.assertEquals("lisi", actual);
    }

    /**
     * 点击好友列表 (显式等待版本)
     */
    @Order(3)
    @Test
    void FriendList() {
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));

        // 1. 点击好友标签
        WebElement friendTab = wait.until(ExpectedConditions.elementToBeClickable(
                By.cssSelector("div.tab-friend")
        ));
        friendTab.click();

        // 2. 等待好友列表加载
        wait.until(ExpectedConditions.visibilityOfElementLocated(
                By.id("friend-list")
        ));

        // 3. 点击第一个好友
        WebElement firstFriend = wait.until(ExpectedConditions.elementToBeClickable(
                By.cssSelector("#friend-list li:first-child h4")
        ));
        firstFriend.click();

        // 4. 验证会话列表置顶项
        WebElement selectedSession = wait.until(ExpectedConditions.visibilityOfElementLocated(
                By.cssSelector("#session-list li.selected h3")
        ));
        Assertions.assertEquals("lisi", selectedSession.getText());
    }

    /**
     * 测试聊天发送功能 (显式等待版本)
     */
    @ParameterizedTest
    @CsvSource({"正在自动化测试中...", "测试发送成功", "测试结束!"})
    @Order(4)
    public void TalkSendTest(String msg) throws IOException {
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));

        // 1. 点击第二个会话
        WebElement secondSession = wait.until(ExpectedConditions.elementToBeClickable(
                By.cssSelector("#session-list li:nth-child(2) h3")
        ));
        secondSession.click();

        // 2. 等待输入框就绪
        WebElement inputBox = wait.until(ExpectedConditions.elementToBeClickable(
                By.cssSelector("textarea")
        ));

        // 3. 输入并发送消息
        inputBox.sendKeys(msg);
        driver.findElement(By.cssSelector("button")).click();

        // 4. 验证消息发送成功(根据实际DOM结构调整选择器)
        wait.until(ExpectedConditions.textToBePresentInElementLocated(
                By.cssSelector(".message-show div:last-child p"),
                msg
        ));

        getScreenShot(getClass().getName());
    }

    /**
     * 测试聊天接收功能 (显式等待版本)
     */
    @Test
    @Order(5)
    public void TalkAcceptTest() {
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(15));

        // 1. 跳转登录页
        driver.get("http://127.0.0.1:8080/login.html");

        // 2. 填写登录表单
        wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("username")))
                .sendKeys("lisi");
        driver.findElement(By.id("password")).sendKeys("123");
        driver.findElement(By.id("submit")).click();

        // 3. 处理登录弹窗
        Alert alert = wait.until(ExpectedConditions.alertIsPresent());
        alert.accept();

        // 4. 等待主界面加载
        wait.until(ExpectedConditions.titleContains("Client Page"));

        // 5. 点击第一个会话
        WebElement firstSession = wait.until(ExpectedConditions.elementToBeClickable(
                By.cssSelector("#session-list li:first-child h3")
        ));
        firstSession.click();

        // 6. 验证会话对象
        WebElement chatTitle = wait.until(ExpectedConditions.visibilityOfElementLocated(
                By.cssSelector("div.title")
        ));
        Assertions.assertEquals("zhangsan", chatTitle.getText());

        // 7. 获取最新消息(动态定位最后一条)
        WebElement lastMessage = wait.until(ExpectedConditions.presenceOfElementLocated(
                By.cssSelector(".message-show div:last-child p")
        ));
        Assertions.assertEquals("测试结束!", lastMessage.getText());
    }
}

3.5退出驱动测试

DriverQuitTest.java

java 复制代码
package common;


import org.junit.jupiter.api.Test;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

public class DriverQuitTest extends Utils {
    private static WebDriver driver = Utils.getDriver();

    /**
     * 退出驱动
     */
    @Test
    public void quitWeb() {
        driver.quit();
    }
}

3.6Junit套件使用

java 复制代码
package Test;

import Test.ClientPageTest;
import Test.LoginPageTest;
import Test.NoLoginTest;
import Test.RegisterPageTest;
import common.DriverQuitTest;
import org.junit.platform.suite.api.SelectClasses;
import org.junit.platform.suite.api.Suite;

@Suite
@SelectClasses({RegisterPageTest.class, NoLoginTest.class, LoginPageTest.class, ClientPageTest.class, DriverQuitTest.class})
public class RunSuite {
    public RunSuite() {

    }

}

整体包、类、方法设计如下

有部分问题待解决,上述会话框问题和接收消息问题代码经过修改已经解决

相关推荐
攻城狮7号2 小时前
Python爬虫第20节-使用 Selenium 爬取小米商城空调商品
开发语言·数据库·爬虫·python·selenium
慢一点会很快16 小时前
【网络分析工具】网络工具wireshark、TCPdump、iperf使用详解
测试工具·wireshark·tcpdump
代码的乐趣1 天前
支持selenium的chrome driver更新到136.0.7103.92
chrome·python·selenium
海尔辛1 天前
学习黑客抓包wireshark
学习·测试工具·wireshark
xixixiLucky2 天前
配置Java Selenium Web自动化测试环境
java·前端·selenium
黑客笔记2 天前
sql注入漏洞的对抗
数据库·sql·测试工具
悟能不能悟2 天前
如何在postman使用时间戳
测试工具·postman
jardonwang12 天前
DeepInjectSQL - 基于 AI 生成对抗网络(GAN)的下一代 SQL 注入自动化漏洞猎手
python·测试工具·生成对抗网络·安全性测试
krack716x3 天前
Wireshark基本使用
网络·测试工具·wireshark
新时代牛马3 天前
tcpdump 的用法
网络·测试工具·tcpdump