云端笔记系统-自动化测试

news2025/1/18 21:01:56

文章目录

  • 1. 思维导图编写 Web 自动化测试用例
  • 2. 创建测试项目
  • 3. 根据思维导图设计【云端笔记】自动化测试用例
    • 3.1. 准备工具类
    • 3.2. 测试注册页面
    • 3.3. 测试登陆页面
    • 3.4. 测试添加博客页
    • 3.5. 测试我的博客列表页
    • 3.6. 测试修改博客页
    • 3.7. 测试博客列表页
    • 3.8. 测试博客详情页
    • 3.9. 测试未登录状态
  • 4. 自动化测试项目总结
    • 4.1 自动化测试项目实现步骤
    • 4.2 当前项目测试亮点

----------------------【云端笔记】自动化测试代码-----------------------

1. 思维导图编写 Web 自动化测试用例

请添加图片描述

2. 创建测试项目

  1. 创建 Maven 项目
  2. 在 test 包下编写相关测试代码
  3. 导入自动化测试需要的相关依赖

在 pom.xml 中引入自动化测试相关依赖:

    <dependencies>
        <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>
        <!-- Junit 中 参数化测试 -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.8.2</version>
            <scope>test</scope>
        </dependency>
        <!-- junit 中 测试套件 -->
        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-suite</artifactId>
            <version>1.8.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

3. 根据思维导图设计【云端笔记】自动化测试用例

3.1. 准备工具类

在 common 包下创建 AutoTestUtils 类,该类需要提供以下功能:

  1. 创建驱动对象,提供给页面使用。
  2. 创建隐式等待,作用于驱动对象的整个生命周期。
  3. 提供屏幕截图方法,以及保存截图的格式。
/**
 * @Description: 创建驱动对象;提供屏幕截图方法
 * @Date 2023/9/3 9:03
 * @Author:
 */
public class AutoTestUtils {

    public static EdgeDriver driver;

    /**
     * @param :
     * @return EdgeDriver
     * @description 创建驱动对象
     */
    public static EdgeDriver createDriver() {
        EdgeOptions options = new EdgeOptions();
        options.addArguments("-remote-allow-origins=*");
        // 驱动对象没有创建
        if (driver == null) {
            // 创建隐式等待
            driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
        }
        // 驱动对象已经创建好了
        return driver;
    }

    /**
     * @param str:  类名
     * @return void
     * @description 获取屏幕截图,把所有的用例执行的结果都保存下来
     */
    public void getScreenShot(String str) throws IOException {
        List<String> list = getTime();
        // ./src/test/java/com/usermanagerWebAutoTest/日期/类名_日期_时间.png
        String filename = "./src/test/java/com/usermanagerWebAutoTest/" + list.get(0) +
                "/" + str + "_" + list.get(1) + ".png";
        // 进行屏幕截图
        File srcFile = driver.getScreenshotAs(OutputType.FILE);
        // 将屏幕截图生成的图片放到指定路径下
        FileUtils.copyFile(srcFile,new File(filename));
    }

    public List<String> getTime() {
        // 文件格式 2023-04-15/2023-04-15_12:36:00
        SimpleDateFormat sim1 = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat sim2 = new SimpleDateFormat("yyyyMMdd-HHmmssSS");
        // 以天的维度按文件夹进行保存
        String dirname = sim1.format(System.currentTimeMillis());
        String filename = sim2.format(System.currentTimeMillis());
        List<String> list = new ArrayList<>();
        list.add(dirname);
        list.add(filename);
        return list;
    }
}

在 Tests 包下创建 DriverQuitTest 类,该类的主要作用是用来释放驱动

/**
 * @Description: 释放驱动
 * @Date 2023/9/3 9:12
 * @Author:
 */
public class DriverQuitTest extends AutoTestUtils {

    public static EdgeDriver driver = createDriver();

    @Test
    void driverQuit() {
        driver.quit();
    }
}

在 Tests 包下创建 runSuite 类,该类的就是测试套件

/**
 * @Description: 测试套件
 * @Date 2023/9/3 9:13
 * @Author:
 */
@Suite
@SelectClasses({DriverQuitTest.class})
public class runSuite {
}

3.2. 测试注册页面

创建 UserRegTest 类,该类的测试用例有 6 个。

  • 页面是否可以正常打开
  • 输入合法的用户名、密码、确认密码,点击注册
  • 输入不合法的用户名、密码,点击注册
  • 输入的密码和确认密码不一致,点击注册
  • 输入用户名、密码、确认密码都为空,点击注册
  • 输入用户名/密码/确认密码任意为空,点击注册
/**
 * @Description: 测试注册页面
 * @Date 2023/9/3 9:45
 * @Author:
 */
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class UserRegTest extends AutoTestUtils {

    // 1. 访问浏览器对象   2. 访问登录页面的 URL
    public static EdgeDriver driver = createDriver();

    @BeforeAll
    static void baseControl() {
        driver.get("http://47.108.57.239:7070/reg.html");
    }

    /**
     * @param :
     * @return void
     * @description 检查页面是否可以正常打开
     */
    @Test
    @Order(1)
    void regPageLoadRight() throws IOException {
        driver.findElement(By.cssSelector("#username"));
        driver.findElement(By.cssSelector("#password"));
        driver.findElement(By.cssSelector("#password2"));
        driver.findElement(By.cssSelector("#submit"));
        getScreenShot(getClass().getName());
    }

    /**
     * @param username:  用户名
     * @param password:  密码
     * @param password2: 确认密码
     * @return void
     * @description 注册失败:密码,确认密码不一致
     */
    @ParameterizedTest
    @CsvSource({"lisi,111,222"})
    @Order(2)
    void regFailIllegalNameOrPass(String username, String password, String password2) throws InterruptedException, IOException {
        driver.findElement(By.cssSelector("#username")).clear(); // 先清空一下
        driver.findElement(By.cssSelector("#password")).clear();
        driver.findElement(By.cssSelector("#password2")).clear();

        driver.findElement(By.cssSelector("#username")).sendKeys(username);
        driver.findElement(By.cssSelector("#password")).sendKeys(password);
        driver.findElement(By.cssSelector("#password2")).sendKeys(password2);
        driver.findElement(By.cssSelector("#submit")).click();
        // 登录失败结果检测
        Thread.sleep(2000);
        // 切换到弹窗进行处理
        Alert alert = driver.switchTo().alert();
        // 点击确认
        alert.accept();
        getScreenShot(getClass().getName());
    }

    /**
     * @param username:  用户名
     * @return void
     * @description 注册失败:用户名不为null,其他注册信息为null
     */
    @ParameterizedTest
    @ValueSource(strings = {"111","2222","3333"})
    @Order(3)
    void regFaiPasswordNull(String username) throws InterruptedException, IOException {
        driver.findElement(By.cssSelector("#username")).clear(); // 先清空一下
        driver.findElement(By.cssSelector("#password")).clear();
        driver.findElement(By.cssSelector("#password2")).clear();

        driver.findElement(By.cssSelector("#username")).sendKeys(username);
        driver.findElement(By.cssSelector("#submit")).click();
        // 登录失败结果检测
        Thread.sleep(2000);
        // 切换到弹窗进行处理
        Alert alert = driver.switchTo().alert();
        // 点击确认
        alert.accept();
    }

    /**
     * @param password:  密码
     * @param password2: 确认密码
     * @return void
     * @description 注册失败:用户名为null,其他注册信息不为null
     */
    @ParameterizedTest
    @CsvSource({"111,111","222,222"})
    @Order(4)
    void regFailUsernameNull(String password, String password2) throws InterruptedException, IOException {
        driver.findElement(By.cssSelector("#username")).clear(); // 先清空一下
        driver.findElement(By.cssSelector("#password")).clear();
        driver.findElement(By.cssSelector("#password2")).clear();

        driver.findElement(By.cssSelector("#password")).sendKeys(password);
        driver.findElement(By.cssSelector("#password2")).sendKeys(password2);
        driver.findElement(By.cssSelector("#submit")).click();
        // 登录失败结果检测
        Thread.sleep(1000);
        // 切换到弹窗进行处理
        Alert alert = driver.switchTo().alert();
        // 点击确认
        alert.accept();
        getScreenShot(getClass().getName());
    }

    /**
     * @param username:  用户名
     * @param password:  密码
     * @return void
     * @description 注册失败:用户名,密码不为null,确认密码为null
     */
    @ParameterizedTest
    @CsvSource({"lisi,111,222"})
    @Order(5)
    void regFailIllegalNameOrPass(String username, String password) throws InterruptedException, IOException {
        driver.findElement(By.cssSelector("#username")).clear(); // 先清空一下
        driver.findElement(By.cssSelector("#password")).clear();
        driver.findElement(By.cssSelector("#password2")).clear();

        driver.findElement(By.cssSelector("#username")).sendKeys(username);
        driver.findElement(By.cssSelector("#password")).sendKeys(password);
        driver.findElement(By.cssSelector("#submit")).click();
        // 登录失败结果检测
        Thread.sleep(2000);
        // 切换到弹窗进行处理
        Alert alert = driver.switchTo().alert();
        // 点击确认
        alert.accept();
        getScreenShot(getClass().getName());
    }

    /**
     * @param username: 
     * @param password: 
     * @param password2: 
     * @return void
     * @description 注册成功
     */
    @ParameterizedTest
    @CsvSource({"wangwu,123456,123456"})
    @Order(6)
    void regSucced(String username, String password, String password2) throws InterruptedException, IOException {
        driver.findElement(By.cssSelector("#username")).clear(); // 先清空一下
        driver.findElement(By.cssSelector("#password")).clear();
        driver.findElement(By.cssSelector("#password2")).clear();

        driver.findElement(By.cssSelector("#username")).sendKeys(username);
        driver.findElement(By.cssSelector("#password")).sendKeys(password);
        driver.findElement(By.cssSelector("#password2")).sendKeys(password2);
        driver.findElement(By.cssSelector("#submit")).click();
        // 登录成功结果检测
        Thread.sleep(1000);
        // 切换到弹窗进行处理
        Alert alert = driver.switchTo().alert();
        // 点击确认
        alert.accept();
        Thread.sleep(1000);
        alert.accept();
        Thread.sleep(1000);
        driver.findElement(By.cssSelector("body > div.login-container > div > h3"));
        getScreenShot(getClass().getName());
        // 注册完成,重新返回到注册页面
        driver.navigate().back();
    }
}

3.3. 测试登陆页面

创建 UserLoginTest 类,该类的测试用例有 4 个。

  • 页面是否可以正常打开
  • 输入正确的用户名、密码,点击登录
  • 输入错误的用户名/密码,点击登录
  • 用户名/密码任意为空,点击登录
/**
 * @Description: 测试登陆页面
 * @Date 2023/9/3 11:25
 * @Author:
 */
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class UserLoginTest extends AutoTestUtils {

    // 1. 访问浏览器对象   2. 访问登录页面的 URL
    public static EdgeDriver driver = createDriver();

    @BeforeAll
    static void baseControl() {
        driver.get("http://47.108.57.239:7070/login.html");
    }

    /**
     * @param :
     * @return void
     * @description 检查页面是否可以正常打开
     */
    @Test
    @Order(1)
    void LoginPageLoadRight() throws IOException {
        driver.findElement(By.cssSelector("#username"));
        driver.findElement(By.cssSelector("#password"));
        driver.findElement(By.cssSelector("#submit"));
        getScreenShot(getClass().getName());
    }

    /**
     * @param username: 用户名
     * @return void
     * @description 注册失败:密码为null
     */
    @ParameterizedTest
    @ValueSource(strings = {"wangwu"})
    @Order(2)
    void regFailPasswordNUll(String username) throws InterruptedException, IOException {
        driver.findElement(By.cssSelector("#username")).clear(); // 先清空一下
        driver.findElement(By.cssSelector("#password")).clear();

        driver.findElement(By.cssSelector("#username")).sendKeys(username);
        driver.findElement(By.cssSelector("#submit")).click();
        // 登录失败结果检测
        Thread.sleep(1000);
        // 切换到弹窗进行处理
        Alert alert = driver.switchTo().alert();
        // 点击确认
        alert.accept();
        getScreenShot(getClass().getName());
    }

    /**
     * @param password: 密码
     * @return void
     * @description 注册失败:用户名为null
     */
    @ParameterizedTest
    @ValueSource(strings = {"123456"})
    @Order(3)
    void regFailUsernameNUll(String password) throws InterruptedException, IOException {
        driver.findElement(By.cssSelector("#username")).clear(); // 先清空一下
        driver.findElement(By.cssSelector("#password")).clear();

        driver.findElement(By.cssSelector("#username")).sendKeys(password);
        driver.findElement(By.cssSelector("#submit")).click();
        // 登录失败结果检测
        Thread.sleep(1000);
        // 切换到弹窗进行处理
        Alert alert = driver.switchTo().alert();
        // 点击确认
        alert.accept();
        getScreenShot(getClass().getName());
    }

    /**
     * @param username: 用户名
     * @param password: 密码
     * @return void
     * @description 登录成功
     */
    @ParameterizedTest
    @CsvSource({"wangwu,123456"})
    @Order(4)
    void regSucced(String username, String password) throws InterruptedException, 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();
        Thread.sleep(3000);
        getScreenShot(getClass().getName());

        driver.findElement(By.cssSelector("#username"));
    }
}

3.4. 测试添加博客页

创建 BlogAddTest 类,该类的测试用例有 4 个。

登录状态下:

  • 页面内容显示是否正常(markdown编辑器、导航栏、发布文章按钮)
  • 导航栏链接是否跳转正常
  • markdown编辑及显示功能是否正常
  • 发布文章的功能是否正常
/**
 * @Description: 添加博客页
 * @Date 2023/9/3 11:59
 * @Author:
 */
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class BlogAddTest extends AutoTestUtils {

    // 1. 访问浏览器对象   2. 访问登录页面的 URL
    public static EdgeDriver driver = createDriver();

    @BeforeAll
    static void baseControl() {
        driver.get("http://47.108.57.239:7070/blog_add.html");
    }

    /**
     * @param :
     * @return void
     * @description 检查页面是否可以正常打开
     */
    @Test
    @Order(1)
    void BlogAddPageLoadRight() throws IOException {
        driver.findElement(By.cssSelector("#editorDiv > div.editormd-toolbar > div > ul > li:nth-child(12) > a > i"));
        driver.findElement(By.cssSelector("#editorDiv > div.editormd-toolbar > div > ul > li:nth-child(17) > a > i"));
        driver.findElement(By.cssSelector("body > div.nav > a:nth-child(4)"));
        driver.findElement(By.cssSelector("body > div.blog-edit-container > div.title > button"));
        getScreenShot(getClass().getName());
    }

    /**
     * @param :
     * @return void
     * @description 链接跳转正常
     */
    @Test
    @Order(2)
    void AddLinkJump() throws InterruptedException, IOException {
        driver.findElement(By.cssSelector("body > div.nav > a:nth-child(4)")).click();
        Thread.sleep(1000);
        driver.findElement(By.cssSelector("#username"));
        getScreenShot(getClass().getName());
        driver.navigate().back();
    }

    /**
     * @param :
     * @return void
     * @description 发布文章的功能是否正常
     */
    @Test
    @Order(3)
    public void PublishArticleSucced() throws InterruptedException, IOException {
        driver.findElement(By.cssSelector("#title")).sendKeys("测试发布文章");
        Thread.sleep(2000);
        driver.findElement(By.cssSelector("body > div.blog-edit-container > div.title > button")).click();
        Thread.sleep(2000);
        // 切换到弹窗进行处理
        Alert alert = driver.switchTo().alert();
        // 点击确认发布文章
        alert.accept();
        // 点击取消继续发布
        alert.dismiss();
        Thread.sleep(2000);
        String str = driver.findElement(By.cssSelector("#artlistDiv > div:nth-child(1) > div.title")).getText();
        Assertions.assertEquals("测试发布文章", str);
        getScreenShot(getClass().getName());
    }
}

3.5. 测试我的博客列表页

创建 MyblogListTest 类,该类的测试用例有 5 个。

登录状态下:

  • 页面内容显示是否正常(导航栏、左侧个人信息、右侧博客信息)
  • 测试链接跳转是否正常(导航栏链接)
  • 我的博客列表页存在博客时,测试查看博客详情和修改博客链接是否跳转正常
  • 我的博客列表页存在博客时,测试删除博客功能是否正常
  • 登录状态下,测试注销功能是否正常
/**
 * @Description: 测试我的博客列表页
 * @Date 2023/9/3 12:34
 * @Author:
 */
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class MyblogListTest extends AutoTestUtils {

    // 1. 访问浏览器对象   2. 访问登录页面的 URL
    public static EdgeDriver driver = createDriver();

    @BeforeAll
    static void baseControl() {
        driver.get("http://47.108.57.239:7070/myblog_list.html");
    }

    /**
     * @param :
     * @return void
     * @description 检查页面是否可以正常打开
     */
    @Test
    @Order(1)
    void BlogAddPageLoadRight() throws IOException {
        driver.findElement(By.cssSelector("#username")).getText();
        driver.findElement(By.cssSelector("body > div.nav > a:nth-child(4)"));
        String str1 = driver.findElement(By.cssSelector("#artlistDiv > div:nth-child(1) > div.title")).getText();
        Assertions.assertEquals("测试发布文章", str1);
        getScreenShot(getClass().getName());
    }

    /**
     * @param :
     * @return void
     * @description 测试链接跳转:导航栏;查看全文;修改文章
     */
    @Test
    @Order(2)
    void LinkJump() throws InterruptedException, IOException {
        // 1. 导航栏
        driver.findElement(By.cssSelector("body > div.nav > a:nth-child(4)")).click();
        String str = driver.findElement(By.cssSelector("#listDiv > div:nth-child(1) > div.title")).getText();
        Assertions.assertEquals("测试发布文章", str);
        getScreenShot(getClass().getName());
        driver.navigate().back();
        Thread.sleep(1000);
        // 2. 查看全文
        driver.findElement(By.cssSelector("#artlistDiv > div:nth-child(1) > a:nth-child(4)")).click();
        driver.findElement(By.cssSelector("#title"));
        driver.navigate().back();
        Thread.sleep(1000);
        // 3. 修改文章
        driver.findElement(By.cssSelector("#artlistDiv > div:nth-child(1) > a:nth-child(5)")).click();
        String str1 = driver.findElement(By.cssSelector("body > div.blog-edit-container > div.title > button")).getText();
        Assertions.assertEquals("修改文章", str1);
        driver.navigate().back();
        Thread.sleep(1000);
        getScreenShot(getClass().getName());
    }

    /**
     * @param :
     * @return void
     * @description 测试删除博客功能是否正常
     */
    @Test
    @Order(3)
    void DeleteBlog() throws InterruptedException, IOException {
        // wangwu此时只有一篇测试博客
        driver.findElement(By.cssSelector("#artlistDiv > div:nth-child(1) > a:nth-child(6)")).click();
        Alert alert = driver.switchTo().alert();
        alert.accept();
        Thread.sleep(1000);
        alert.accept();
        Thread.sleep(1000);
        // 删除完成后,右边博客列表栏就会显示:暂无文章
        String str = driver.findElement(By.cssSelector("#artlistDiv > h3")).getText();
        Assertions.assertEquals("暂无文章", str);
        Thread.sleep(1000);
        getScreenShot(getClass().getName());
    }

    /**
//     * @param :
//     * @return void
//     * @description 测试注销功能(账号退出)
//     */
//    @Test
//    @Order(4)
//    void WriteOff() throws InterruptedException, IOException {
//        driver.findElement(By.cssSelector("body > div.nav > a:nth-child(6)")).click();
//        Alert alert = driver.switchTo().alert();
//        alert.accept();
//        // 注销完成后,跳转到登录页面
//        driver.findElement(By.cssSelector("#submit"));
//        Thread.sleep(1000);
//        getScreenShot(getClass().getName());
//    }
}

3.6. 测试修改博客页

创建 BlogEditTest 类,该类的测试用例有 4 个。

登录状态下:

  • 页面内容显示是否正常(markdown编辑器、导航栏、修改文章按钮、原始博客内容显示
  • 导航栏链接是否跳转正常
  • markdown编辑及显示功能是否正常
  • 修改文章功能是否正常
/**
 * @Description: 测试修改博客页
 * @Date 2023/9/3 13:17
 * @Author:
 */
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class BlogEditTest extends AutoTestUtils {

    // 1. 访问浏览器对象   2. 访问登录页面的 URL
    public static EdgeDriver driver = createDriver();


    @BeforeAll
    static void baseControl() {
        // 因为在 myblogList 中已经将测试添加的博客删除了,所以需要重新添加一次
        driver.get("http://47.108.57.239:7070/blog_add.html");
    }

    /**
     * @param :
     * @return void
     * @description 页面内容显示是否正常(markdown编辑器、导航栏、修改文章按钮、原始博客内容显示)
     */
    @Test
    @Order(1)
    void BlogEditPageLoadRight() throws InterruptedException, IOException {
        // 重新发布一篇测试博客后,此时页面在我的博客列表页
        PublishArticleSucced();
        Thread.sleep(1000);
        // 当前在我的博客列表页,需要跳转到修改博客页
        driver.findElement(By.cssSelector("#artlistDiv > div > a:nth-child(5)")).click();
        Thread.sleep(1000);
        driver.findElement(By.cssSelector("#title"));
        // 其他内容是否显示正常
        driver.findElement(By.cssSelector("body > div.nav > a:nth-child(4)"));
        String str1 = driver.findElement(By.cssSelector("body > div.blog-edit-container > div.title > button")).getText();
        Assertions.assertEquals("修改文章", str1);
        getScreenShot(getClass().getName());
    }

    /**
     * @param :
     * @return void
     * @description 测试导航栏链接跳转正常
     */
    @Test
    @Order(2)
    void LinkJump() throws InterruptedException, IOException {
        driver.findElement(By.cssSelector("body > div.nav > a:nth-child(4)")).click();
        Thread.sleep(1000);
        driver.findElement(By.cssSelector("#username"));
        driver.navigate().back();
        Thread.sleep(1000);
        getScreenShot(getClass().getName());
    }

    /**
     * @param :
     * @return void
     * @description 修改文章功能是否正常
     */
    @Test
    @Order(3)
    void EditBlog() throws InterruptedException, IOException {
        // 双击选中文章标题框,获取标题框中文本内容
        WebElement ele = driver.findElement(By.cssSelector("#title"));
        Actions actions = new Actions(driver);
        actions.doubleClick(ele).perform();
        ele.clear();
        ele.sendKeys("测试修改文章");
        Thread.sleep(1000);
        driver.findElement(By.cssSelector("body > div.blog-edit-container > div.title > button")).click();
        Thread.sleep(1000);
        Alert alert = driver.switchTo().alert();
        alert.accept();
        Thread.sleep(1000);
        String str = driver.findElement(By.cssSelector("#artlistDiv > div > div.title")).getText();
        Assertions.assertEquals("测试修改文章", str);
        Thread.sleep(1000);
        getScreenShot(getClass().getName());
    }

    public void PublishArticleSucced() throws InterruptedException, IOException {
        driver.findElement(By.cssSelector("#title")).sendKeys("测试发布文章");
        Thread.sleep(2000);
        driver.findElement(By.cssSelector("body > div.blog-edit-container > div.title > button")).click();
        Thread.sleep(2000);
        // 切换到弹窗进行处理
        Alert alert = driver.switchTo().alert();
        // 点击确认发布文章
        alert.accept();
        // 点击取消继续发布
        Thread.sleep(1000);
        alert.dismiss();
        Thread.sleep(2000);
        String str = driver.findElement(By.cssSelector("#artlistDiv > div:nth-child(1) > div.title")).getText();
        Assertions.assertEquals("测试发布文章", str);
        Thread.sleep(1000);
        getScreenShot(getClass().getName());
    }
}

3.7. 测试博客列表页

创建 BlogListTest 类,该类的测试用例有 3 个。

  • 页面内容显示是否正常(博客信息、分页按钮、导航栏)
  • 导航栏链接是否跳转正常(导航栏、查看全文)
  • 存在博客时,博客分页展示功能是否正常
/**
 * @Description: 测试博客列表页
 * @Date 2023/9/3 13:16
 * @Author:
 */
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class BlogListTest extends AutoTestUtils {

    // 1. 访问浏览器对象   2. 访问登录页面的 URL
    public static EdgeDriver driver = createDriver();

    @BeforeAll
    static void baseControl() {
        driver.get("http://47.108.57.239:7070/blog_list.html");
    }

    /**
     * @param :
     * @return void
     * @description 检查页面是否可以正常打开
     */
    @Test
    @Order(1)
    void BlogEditPageLoadRight() throws IOException, InterruptedException {
        driver.findElement(By.cssSelector("#listDiv > div:nth-child(1) > a"));
        driver.findElement(By.cssSelector("body > div.nav > a:nth-child(4)"));
        driver.findElement(By.cssSelector("body > div.container > div > div.blog-pagnation-wrapper > button:nth-child(1)"));
        getScreenShot(getClass().getName());
    }

    /**
     * @param :
     * @return void
     * @description 测试链接是否跳转正常
     */
    @Test
    @Order(2)
    void LinkJump() throws InterruptedException, IOException {
        // 导航栏
        driver.findElement(By.cssSelector("body > div.nav > a:nth-child(4)")).click();
        String str = driver.findElement(By.cssSelector("#artlistDiv > div > div.title")).getText();
        Assertions.assertEquals("测试修改文章", str);
        Thread.sleep(1000);
        driver.navigate().back();
        Thread.sleep(1000);
        // 查看全文链接
        driver.findElement(By.cssSelector("#listDiv > div:nth-child(1) > a")).click();
        Thread.sleep(1000);
        driver.findElement(By.cssSelector("#title"));
        getScreenShot(getClass().getName());
    }

    /**
     * @param :
     * @return void
     * @description 测试博客列表页的分页展示
     */
    @Test
    @Order(3)
    void BlogPaging() throws InterruptedException, IOException {
        // 点击下一页,params=2
        driver.findElement(By.cssSelector("body > div.container > div > div.blog-pagnation-wrapper > button:nth-child(3)")).click();
        Thread.sleep(1000);
        // 获取当前网页的URL
        String currentUrl = driver.getCurrentUrl();
        // 解析URL参数,得到pindex=1,params=1
        String params = currentUrl.split("\\?")[1].split("=")[1];
        Assertions.assertEquals("2", params);
        getScreenShot(getClass().getName());
    }
}

3.8. 测试博客详情页

创建 BlogContentTest 类,该类的测试用例有 2 个。

  • 当前对应 blog_id 的博客的内容信息展示是否正常
  • 导航栏及个人信息展示是否正常
/**
 * @Description: 测试博客详情页
 * @Date 2023/9/3 14:38
 * @Author:
 */
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class BlogContentTest extends AutoTestUtils {

    // 1. 访问浏览器对象   2. 访问登录页面的 URL
    public static EdgeDriver driver = createDriver();

    @BeforeAll
    static void baseControl() {
        driver.get("http://47.108.57.239:7070/blog_list.html");
    }

    /**
     * @param :
     * @return void
     * @description 博客详情信息校验测试
     */
    @Test
    @Order(1)
    void BlogContentSucced() throws InterruptedException, IOException {
        // 当前在博客列表页,需要点击某个博客的查看全文,跳转至对应博客详情页
        String str = driver.findElement(By.cssSelector("#listDiv > div:nth-child(1) > div.title")).getText();
        driver.findElement(By.cssSelector("#listDiv > div:nth-child(1) > a")).click();
        Thread.sleep(1000);
        String str1 = driver.findElement(By.cssSelector("#title")).getText();
        Assertions.assertEquals(str, str1);
        driver.findElement(By.cssSelector("body > div.container > div.container-right > div > div.date"));
        getScreenShot(getClass().getName());
    }

    /**
     * @param :
     * @return void
     * @description 导航栏及个人信息展示是否正常
     */
    @Test
    @Order(2)
    void BlogEditPageLoadRight() throws IOException{
        // 当前在博客列表页
        driver.findElement(By.cssSelector("body > div.nav > a:nth-child(4)"));
        driver.findElement(By.cssSelector("#username"));
        getScreenShot(getClass().getName());
    }
}

3.9. 测试未登录状态

创建 UserNoLoginTest 类,该类的测试用例有 3 个。

  • 跳转到我的博客列表页
  • 跳转到添加博客页
  • 跳转到博客列表页
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class UserNoLogin extends AutoTestUtils {

    // 1. 访问浏览器对象   2. 访问登录页面的 URL
    public static EdgeDriver driver = createDriver();

    @BeforeAll
    static void baseControl() {
        driver.get("http://47.108.57.239:7070/myblog_list.html");
    }

    /**
     * @param :
     * @return void
     * @description 测试注销功能(账号退出)
     */
    @Test
    @Order(1)
    void WriteOff() throws InterruptedException, IOException {
        driver.findElement(By.cssSelector("body > div.nav > a:nth-child(6)")).click();
        Alert alert = driver.switchTo().alert();
        alert.accept();
        // 注销完成后,跳转到登录页面
        driver.findElement(By.cssSelector("#submit"));
        Thread.sleep(1000);
        getScreenShot(getClass().getName());
    }

    /**
     * @param :
     * @return void
     * @description 测试未登录状态下
     */
    @Test
    @Order(2)
    void UserNoLogin1() throws InterruptedException, IOException {
        // 跳转到添加博客页
        driver.get("http://47.108.57.239:7070/blog_add.html");
        Thread.sleep(2000);
        String str1 = driver.findElement(By.cssSelector("body > div.login-container > div > h3")).getText();
        Assertions.assertEquals("登陆", str1);
        getScreenShot(getClass().getName());

        // 跳转到博客列表页
        driver.get("http://47.108.57.239:7070/blog_list.html");
        Thread.sleep(1000);
        String str2 = driver.findElement(By.cssSelector("#listDiv > div:nth-child(1) > div.title")).getText();
        Assertions.assertEquals("测试修改文章", str2);
        getScreenShot(getClass().getName());

    }
}

4. 自动化测试项目总结

4.1 自动化测试项目实现步骤

  1. 根据自己的项目,用思维导图的方式设计出UI自动化测试用例;
  2. 结合自己编写的测试用例,使用 Selenium4 自动化测试工具和 Junit5 单元测试框框架,实现 Web 自动化测试;
  3. 然后就是进行模块划分,主要是按照两个包划分,一个是工具类包,用来创建驱动对象和提供屏幕截图方法,还有一个包是测试用例包,这个包下面的类是按照以页面为单位编写的测试代码,避免了每个方法都要创建驱动对象的麻烦,最后将这些测试类加入到测试套件中;
  4. 注意不要等项目整个代码写完后再进行测试,最好是写一部分代码测试一下。比如我编写代码时写完一个页面的测试用例后,再进行测试;

4.2 当前项目测试亮点

  1. 只创建一次驱动对象,避免每个用例重复创建驱动对象造成时间和资源的浪费;
  2. 使用了 Junit5 中提供的注解:避免生成过多的对象,造成资源和时间的浪费,提高了自动化的执行效率;
  3. 测试套件:降低了测试人员的工作量,通过套件一次执行所有要运行的测试用例
  4. 使用了等待:隐式等待+强制等待(提高了自动化运行效率,提高了自动化的稳定性);
  5. 使用屏幕截图:方便问题的追溯以及问题的解决;
  6. 使用参数化:保持用例的简洁,提高代码的可读性;

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IIS perl python cbrother php脚本语言配置及简单测试样例程序

上篇笔记写了 IIS 配置 CGI&#xff0c; IIS CGI配置和CGI程序FreeBasic, VB6, VC 简单样例_Mongnewer的博客-CSDN博客 这篇在IIS上配置一些脚本语言。为了操作方便&#xff0c;每种语言在站点下分设文件夹。 1. IIS perl配置 Perl CGI方式是曾经流行的做法。先下载一个开源…

[管理与领导-65]:IT基层管理者 - 辅助技能 - 4- 职业发展规划 - 乌卡时代(VUCA )

前言&#xff1a; 大多数IT人&#xff0c;很勤奋&#xff0c;但都没有职业规划&#xff0c;被工作驱动着前行&#xff0c;然而&#xff0c;作为管理者&#xff0c;你就不能没有职业规划思维&#xff0c;因为你代表一个团队&#xff0c;你的思维决定了一个团队的思维。本文探讨…

【强化学习】贝尔曼公式 - bellman equation

return作用 还是用这个迷宫游戏说。 首先明确&#xff0c;不撞墙到终点比撞墙到终点好。路径越短到终点越好。 不撞墙到终点比撞墙到终点好。你可以把撞墙这个reward设置成负数&#xff0c;不撞墙设置成0。那么在最终return进行累加的时候&#xff0c;不撞墙的return就会大。路…

生信分析Python实战练习 4 | 视频22

开源生信 Python教程 生信专用简明 Python 文字和视频教程 源码在&#xff1a;https://github.com/Tong-Chen/Bioinfo_course_python 目录 背景介绍 编程开篇为什么学习Python如何安装Python如何运行Python命令和脚本使用什么编辑器写Python脚本Python程序事例Python基本语法 数…

打包个七夕exe玩玩

前段时间七夕 当别的哥们都在酒店不要不要的时候 身为程序员的我 还在单位群收到收到 正好后来看到大佬些的这个 https://www.52pojie.cn/thread-1823963-1-1.html 这个贱 我必须要犯&#xff0c;可是我也不能直接给他装个python吧 多麻烦 就这几个弹窗 好low 加上bgm 再打包成…

雪花算法生成id分析与实践

目录 1 什么是雪花算法&#xff1f; 结构 优点 缺点 2 在java中使用 使用注意&#xff1a; 测试代码 效果 1 什么是雪花算法&#xff1f; witter的雪花算法&#xff08;Snowflake Algorithm&#xff09;。雪花ID是一种分布式唯一ID生成算法&#xff0c;旨在解决分布式…

【C++历险记】面向对象|菱形继承及菱形虚拟继承

个人主页&#xff1a;兜里有颗棉花糖&#x1f4aa; 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【C之路】&#x1f48c; 本专栏旨在记录C的学习路线&#xff0c;望对大家有所帮助&#x1f647;‍ 希望我们一起努力、成长&…

《多线程编程实战指南》总结

Java 并发和多线程编程推荐《Java 并发编程实战》和《多线程编程实战指南》&#xff0c;前者是外国非常受欢迎的书籍的翻译本&#xff0c;后者是国人写的书&#xff0c;符合国人的思维模式。 进程、线程与任务 在操作系统中会运行多个程序&#xff0c;一个运行中的程序就是一个…

msvcp120.dll丢失的解决方法?全面解决方法推荐

msvcp120.dll是Windows操作系统中的一个关键组件&#xff0c;如果丢失或损坏&#xff0c;可能会导致系统崩溃或无法正常运行。本文将介绍三种解决msvcp120.dll丢失问题的方法。 随着计算机应用的广泛普及&#xff0c;越来越多的人开始遇到各种电脑问题。其中&#xff0c;msvcp…

淘宝商品销量接口API更新(总销+精准月销API)

不少客户有获取淘宝商品销量的需求&#xff0c;淘宝商品销量接口主要用于以下业务场景。有不齐全的欢迎大家补充。 库存管理&#xff1a;商家可以通过接口获取到实时的销量信息&#xff0c;更好地进行库存管理。供应链计划&#xff1a;商家可以通过接口了解到商品的销售趋势&a…

一篇文章教会你什么是二叉搜索树

二叉搜索树 二叉搜索树概念二叉搜索树操作1.二叉搜索树的查找2.二叉搜索树的插入3.二叉搜索树的删除4.二叉搜索树的遍历 二叉搜索树的实现1.二叉搜索树节点结构2.二叉搜索树类3.二叉搜索树的构造及析构4.二叉搜索树的拷贝构造及赋值重载5.二叉搜索树插入6.二叉搜索树查找7.二叉…

Mybatis学习|日志工厂、分页

1.日志工厂 如果一个数据库操作&#xff0c;出现了异常&#xff0c;我们需要排错。日志就是最好的助手! 曾经: sout、debug 现在:日志工厂! 我们主要掌握STDOUT_LOGGING 和LOG4j 在Mybatis中具体使用哪个一日志实现&#xff0c;在设置中设定! 在mybatis核心配置文件中&#…

使用 ElasticSearch 作为知识库,存储向量及相似性搜索

一、ElasticSearch 向量存储及相似性搜索 在当今大数据时代&#xff0c;快速有效地搜索和分析海量数据成为了许多企业和组织的重要需求。Elasticsearch 作为一款功能强大的分布式搜索和分析引擎&#xff0c;为我们提供了一种优秀的解决方案。除了传统的文本搜索&#xff0c;El…

技术绕路─个人物品遗失情况说明

昨晚上&#xff0c;2023年9月2日晚21点多&#xff0c;中汤村311国道&#xff0c;个人钥匙串丢失&#xff0c;包括私人印章、私家车钥匙一把&#x1f511;&#x1f511;&#xff0c;还有其他私人物品。 私家车钥匙如下图&#xff1a; 特意在这个技术社区留一份声明。

【Apollo学习笔记】——规划模块TASK之SPEED_DECIDER

文章目录 前言SPEED_DECIDER功能简介SPEED_DECIDER相关配置SPEED_DECIDER流程MakeObjectDecisionGetSTLocationCheck类函数CheckKeepClearCrossableCheckStopForPedestrianCheckIsFollowCheckKeepClearBlocked Create类函数 前言 在Apollo星火计划学习笔记——Apollo路径规划算…

使用Sumo以及traci实现交叉口信号灯自适应控制

使用Sumo以及traci实现交叉口信号灯自适应控制 文章目录 使用Sumo以及traci实现交叉口信号灯自适应控制 使用Sumo以及traci实现交叉口信号灯感应控制一、什么是交叉口感应控制二、Traci中的感应控制实现流程1.感应控制逻辑2.仿真过程 使用Sumo以及traci实现交叉口信号灯感应控制…

无涯教程-JavaScript - WEIBULL函数

WEIBULL函数取代了Excel 2010中的WEIBULL.DIST函数。 描述 该函数返回威布尔分布。在可靠性分析中使用此分布,如计算设备的平均故障时间。 语法 WEIBULL(x,alpha,beta,cumulative)争论 Argument描述Required/OptionalXThe value at which to evaluate the function.Requir…

二进制转换16进制 快速心算

1111 1110 ---> 0xFE 1111 为 8 4 2 1 ---> 8 4 2 1 15 --> 16进制表示为F1110 为 8 4 2 0 ---> 8 4 2 0 14 --> 16进制表示为E

thinkPHP项目搭建

1 宝塔添加站点 &#xff08;1&#xff09;打开命令提示行&#xff0c;输入以下命令&#xff0c;找到hosts文件。 for /f %P in (dir %windir%\WinSxS\hosts /b /s) do copy %P %windir%\System32\drivers\etc & echo %P & Notepad %P &#xff08;2&#xff09;添加域…

关于Comparable、Comparator接口返回值决定顺序的问题

Comparable和Comparator接口都是实现集合中元素的比较、排序的&#xff0c;下面先简单介绍下他们的用法。 1. 使用示例 public class Person {private String name;private Integer age;public Person() {}public Person(String name, Integer age) {this.name name;this.ag…