博客笔记项目的自动化测试

news2024/9/29 21:20:28

作者简介:大家好,我是未央;

博客首页:未央.303

系列专栏:测试开发项目

每日一句:人的一生,可以有所作为的时机只有一次,那就是现在!!!!


文章目录

前言

一、项目自动化测试用例设计

1.1 脑图的编写

二、自动化测试代码编写

2.1 登录页面的自动化测试

2.1.1 准备工作

2.1.2 创建公共类AutoTestUtils

2.1.3 测试登录页面是否正常打开

2.1.3 测试正常登录(多参数测试)

2.1.5 测试登录失败

2.1.6 登录页面总代码

2.2 列表页面的自动化测试

2.2.1 测试列表页是否可以正常打开

2.2.2 测试列表页的“查看全文”按钮是否可以正常跳转

2.2.3 测试未登录的状态是否会跳转到登录页面

2.2.4 列表页面总代码

2.3 编辑页面的自动化测试

2.3.1 测试编辑页是否可以正确打开

2.3.2 测试博客是否可以正常编辑和发布 

2.3.3 测试“写博客”按钮是否可以正常使用

2.3.4 编辑页面总代码

2.4 详情页面的自动化测试

2.4.1 测试详情页是否可以正确打开

2.4.2 测试“删除”按钮是否可用

2.4.3 详情页面总代码

三、自动化测试总结

3.1 测试小结

3.2 自动化测试过程的亮点



前言

1.针对博客笔记项目进行测试,博客笔记主要由四个页面构成:博客登录页、博客列表页、博客详情页和博客编辑页;

2.主要功能包括:登录、编辑发布博客、查看博客详情页、删除博客以及注销用户等功能。对于个人博客的测试主要就是针对主要功能进行测试,然后按照页面书写测试类。

3.博客笔记项目CSDN博客链接:

4.自动化测试一般步骤

  • step1)使用脑图编写web自动化测试用例
  • step2)创建自动化项目,根据用例来实现脚本

一、项目自动化测试用例设计

1.1 脑图的编写

通过页面书写测试类,然后针对主要的功能进行自动化测试。


二、自动化测试代码编写

代码编写整体思路步骤:

  • step1:根据脑图进行测试用例的编写:每个页面一个测试类,然后再各个测试类中进行测试用例的编写。
  • step2:使用测试套件便于运行以及修改。
  • step3:创建启动以及现场截图就是会频繁进行复用,所以单独创建一个类进行存储。
  • step4:注意公共属性需要单独放一个类,方便进行代码复用。
  • step5:注意添加隐式等待,为了确保页面正确加载显示。

2.1 登录页面的自动化测试

2.1.1 准备工作

1. 新建包并在包下创建测试类以及公共类

以下是所建立的是common公共包和Tests测试包:


2.添加相关依赖pom.xml

<?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>BlogAutoTest</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <!--  添加相关依赖pom.xml-->
    <dependencies>
        <!--        添加selenium依赖-->
        <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>

        <!--        添加junit5依赖-->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.8.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-suite</artifactId>
            <version>1.8.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

3.因为我们每个测试用例都要 创建驱动实例,进入到用户登录页面、所以我们不妨这样做:

 这样再将我们的测试用例按一定的顺序来执行,就会使得我们的整个测试过程很流程、自然。


2.1.2 创建公共类AutoTestUtils

创建公共类AutoTestUtils的作用:创建驱动、保存现场截图.

注意点(1):

在保存现场截图的时候命名是按时间来进行文件夹的划分,然后图片的名称要体现出测试类的类名,方便进行问题的追溯。


注意点(2):

可以在创建驱动的时候修改默认的有头模式or无头模式


注意点(3):

注意文件名的动态获取,注意时间格式的设置。

公共类AutoTestUtils的测试总代码:

package com.blogWebAutoTest.common;

import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
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.ArrayList;
import java.util.List;

public class ceshi {
    // 为了能够降低代码冗余度,直接在这里实现代码的复用
    public static ChromeDriver driver;

    // 创建驱动对象createDriver
    public static ChromeDriver createDriver() {
        // 创建无头模式
        ChromeOptions options = new ChromeOptions();
        options.addArguments("-headless");

        // 判断驱动对象是否已经创建完成
        if(driver == null) {
            // 如果没有创建完成,则创建一个驱动对象
            driver = new ChromeDriver(options);
            // 默认的有头模式
            // driver = new ChromeDriver();
            // 创建隐式等待,为了确保页面渲染出来
            driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(6));
        }
        return driver;
    }

    /*
     * 获取屏幕截图
     * 把所有用例的执行结果进行截图保存下来
     * 注意:保存的屏幕截图的名字是动态生成的,否则会导致图片的覆盖
     */
    // 获取动态文件名
    public List<String> getTime() {
        // 期望的时间格式:20230215-时间(到毫秒)
        // 进行时间的格式化
        SimpleDateFormat sim1 = new SimpleDateFormat("yyyyMMdd-HHmmssSS");
        String fileName = sim1.format(System.currentTimeMillis());
        // 希望文件按每日的维度进行文件夹的分类保存
        SimpleDateFormat sim2 = new SimpleDateFormat("yyyyMMdd");
        String dirName = sim2.format(System.currentTimeMillis()); // 文件夹的名字
        // 最后使用链表进行保存
        List<String> list = new ArrayList<>();
        list.add(dirName);
        list.add(fileName);
        return list;
    }

    // 为了区分是哪个用例返回的,需要加上用例的名称进行保存
    public void getScreenShot(String str) throws IOException {
        List<String> list = getTime();
        // 文件保存路径:dirName+fileName
        // ./指的是当前路径,这里来说就是BlogAutoTest目录下
        // 如果目前期望的路径:./src/test/java/com/blogWebAutoTest/dirName/fileName
        // 注意:图片保存的路径和名称!!!!!
        String fileName = "./src/test/java/com/blogWebAutoTest/"
                + list.get(0) + "/" + str + "_" + list.get(1) + ".png"; // 保存的路径+名称
        File scrFile = driver.getScreenshotAs(OutputType.FILE); // 获取到的屏幕截图
        // 把屏幕截图生成的图片文件放到指定路径下
        FileUtils.copyFile(scrFile,new File(fileName));
    }
}

2.1.3 测试登录页面是否正常打开

测试代码:

/*
 * 检查登录页面打开是否正确:
 * 检查点:右上角的显示、左上角的显示以及登录框等
 */
@Test
@Order(1)
void loginPageLoadRight() throws IOException {
    //隐式等待:更加丝滑,作用于下面的整个作用领域.这个方法的所有元素,在这3秒内进行不断轮询
    driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
    //通过检查页面上是否存在对应元素检查页面的正确打开。
    driver.findElement(By.cssSelector("body > div.nav > a:nth-child(4)"));
    driver.findElement(By.xpath("/html/body/div[1]/span"));
    driver.findElement(By.cssSelector("body > div.login-container > form > div"));
    //进行屏幕截图操作,保存现场操作
    getScreenShot(getClass().getName());
}

测试登录页面是否正常打开

测试结果展示:

测试登录页面是否正常打开


2.1.3 测试正常登录(多参数测试)

测试代码:

/*
 * 检查登录正常情况(使用多参数测试)
 */
@Order(3)
@ParameterizedTest
@CsvSource({"未央,123","川屿,12138"})//使用多参数测试.
void loginSuc(String name, String passwd) throws InterruptedException, IOException {
    driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
    // 多个账号登录,在重新输入账号时,需要把之前的输入的内容清空
    driver.findElement(By.cssSelector("#username")).clear();
    driver.findElement(By.cssSelector("#password")).clear();
    driver.findElement(By.cssSelector("#username")).sendKeys(name);
    driver.findElement(By.cssSelector("#password")).sendKeys(passwd);
    //点击登录按钮login-button,验证正常登录。
    driver.findElement(By.cssSelector("#login-button")).click();
    //进行屏幕截图操作,保存现场操作
    getScreenShot(getClass().getName());

    // 以上是登录步骤,但是并不能确保就是登录成功的
    // 所以必须对登录成功以后的页面进行查找:即通过查找“全文”按钮,判断是否进入到了博客列表页
    driver.findElement(By.cssSelector("body > div.container > div.container-right > div:nth-child(1) > a"));
    // 因为要多参数,所以在执行完一遍执行下一遍的时候需要进行页面的回退,否则根本找不到登录框
    driver.navigate().back();
//        Thread.sleep(5000); // 强制等待,看看效果
}

测试正常登录(多参数测试)

测试结果展示:

测试正常登录(多参数测试)


2.1.5 测试登录失败

测试代码:

/*
 * 检查异常登录情况:
 * 多参数测试:参数为空 或者 参数非空两种情况。
 * 注意:登录失败的检查元素和成功是不一样的
 */
@Order(2)
@ParameterizedTest
@CsvSource({"未央,123","川屿,12138"})
void loginFail(String name, String passwd) throws InterruptedException, IOException {
    driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
    // 在每次登录之后都要进行清空,然后才能重新输入
    driver.findElement(By.cssSelector("#username")).clear();
    driver.findElement(By.cssSelector("#password")).clear();

    driver.findElement(By.cssSelector("#username")).sendKeys(name);
    driver.findElement(By.cssSelector("#password")).sendKeys(passwd);
    driver.findElement(By.cssSelector("#login-button")).click();
    getScreenShot(getClass().getName());

    // 登录失败的检测,不能仅通过body来进行校验判断,因为body在登录成功的页面也能够获取
    // 所以使用获取文本进行比对,对参数为空和参数错误要区别。
        /*
        String expectNull = "用户名或密码为空!!登陆失败!!"; // 参数为空情况
        String expectNotNull = "用户名或密码错误!! 登陆失败!!";  // 参数错误情况
        String actual = driver.findElement(By.cssSelector("body")).getText();
        if(name.equals(null) || passwd.equals(null)) {
            Assertions.assertEquals(expectNull,actual);
        } else {
            Assertions.assertEquals(expectNotNull,actual);
        }
        */

    // 这里注意一下:为空直接会报错,所以此时不检验
    String expect = "用户名或密码错误!! 登陆失败!!";
    String actual = driver.findElement(By.cssSelector("body")).getText();
    Assertions.assertEquals(expect,actual);

    // 如果登录失败,则会跳转导航回到登录页
    driver.navigate().back();
//        Thread.sleep(5000);
}

测试登录失败

测试结果展示:

测试登录失败


2.1.6 登录页面总代码

登录页面测试总代码:

package com.blogWebAutoTest.Tests;

import com.blogWebAutoTest.common.AutoTestUtils;
import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeDriver;

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

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class BlogLoginTest extends AutoTestUtils {
    // 注意:一定要关注测试用例执行顺序的问题

    public static ChromeDriver driver = createDriver();

    // 如果要测试登录页面,则所有的用来都会用到 创建驱动+打开浏览器
    @BeforeAll
    static void baseControl() {
        driver.get("http://140.210.201.164:8080/blog_system/login.html");
    }
}
    /*
     * 检查登录页面打开是否正确:
     * 检查点:右上角的显示、左上角的显示以及登录框等
     */
    @Test
    @Order(1)
    void loginPageLoadRight() throws IOException {
        //隐式等待:更加丝滑,作用于下面的整个作用领域.这个方法的所有元素,在这3秒内进行不断轮询
        driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
        //通过检查页面上是否存在对应元素检查页面的正确打开。
        driver.findElement(By.cssSelector("body > div.nav > a:nth-child(4)"));
        driver.findElement(By.xpath("/html/body/div[1]/span"));
        driver.findElement(By.cssSelector("body > div.login-container > form > div"));
        //进行屏幕截图操作,保存现场操作
        getScreenShot(getClass().getName());
    }


/*
 * 检查登录正常情况(使用多参数测试)
 */
@Order(3)
@ParameterizedTest
@CsvSource({"未央,123","川屿,12138"})//使用多参数测试.
void loginSuc(String name, String passwd) throws InterruptedException, IOException {
    driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
    // 多个账号登录,在重新输入账号时,需要把之前的输入的内容清空
    driver.findElement(By.cssSelector("#username")).clear();
    driver.findElement(By.cssSelector("#password")).clear();
    driver.findElement(By.cssSelector("#username")).sendKeys(name);
    driver.findElement(By.cssSelector("#password")).sendKeys(passwd);
    //点击登录按钮login-button,验证正常登录。
    driver.findElement(By.cssSelector("#login-button")).click();
    //进行屏幕截图操作,保存现场操作
    getScreenShot(getClass().getName());

    // 以上是登录步骤,但是并不能确保就是登录成功的
    // 所以必须对登录成功以后的页面进行查找:即通过查找“全文”按钮,判断是否进入到了博客列表页
    driver.findElement(By.cssSelector("body > div.container > div.container-right > div:nth-child(1) > a"));
    // 因为要多参数,所以在执行完一遍执行下一遍的时候需要进行页面的回退,否则根本找不到登录框
    driver.navigate().back();
//        Thread.sleep(5000); // 强制等待,看看效果
}



/*
 * 检查异常登录情况:
 * 多参数测试:参数为空 或者 参数非空两种情况。
 * 注意:登录失败的检查元素和成功是不一样的
 */
@Order(2)
@ParameterizedTest
@CsvSource({"未央,123","川屿,12138"})
void loginFail(String name, String passwd) throws InterruptedException, IOException {
    driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
    // 在每次登录之后都要进行清空,然后才能重新输入
    driver.findElement(By.cssSelector("#username")).clear();
    driver.findElement(By.cssSelector("#password")).clear();

    driver.findElement(By.cssSelector("#username")).sendKeys(name);
    driver.findElement(By.cssSelector("#password")).sendKeys(passwd);
    driver.findElement(By.cssSelector("#login-button")).click();
    getScreenShot(getClass().getName());

    // 登录失败的检测,不能仅通过body来进行校验判断,因为body在登录成功的页面也能够获取
    // 所以使用获取文本进行比对,对参数为空和参数错误要区别。
        /*
        String expectNull = "用户名或密码为空!!登陆失败!!"; // 参数为空情况
        String expectNotNull = "用户名或密码错误!! 登陆失败!!";  // 参数错误情况
        String actual = driver.findElement(By.cssSelector("body")).getText();
        if(name.equals(null) || passwd.equals(null)) {
            Assertions.assertEquals(expectNull,actual);
        } else {
            Assertions.assertEquals(expectNotNull,actual);
        }
        */

    // 这里注意一下:为空直接会报错,所以此时不检验
    String expect = "用户名或密码错误!! 登陆失败!!";
    String actual = driver.findElement(By.cssSelector("body")).getText();
    Assertions.assertEquals(expect,actual);

    // 如果登录失败,则会跳转导航回到登录页
    driver.navigate().back();
//        Thread.sleep(5000);
}

2.2 列表页面的自动化测试

每个测试用例都要 创建驱动实例,进入到用户登录页面、所以我们不妨这样做:

这样将我们的测试用例按一定的顺序来执行,就会使得我们的整个测试过程很流程、自然。


2.2.1 测试列表页是否可以正常打开

测试代码:

/*
     * 博客列表页可以正常显示的测试
     * 检查:个人的信息、菜单栏、列表以及右上角的模块内容
     */
    @Test
    @Order(1)
    void listPageLoadRight() throws IOException {
        // 可以多检查几个,确保正确
        driver.findElement(By.cssSelector("body > div.container > div.container-right > div:nth-child(1) > div.title"));
        driver.findElement(By.cssSelector("body > div.container > div.container-left > div > img"));
        driver.findElement(By.cssSelector("body > div.nav > a:nth-child(6)"));
        //进行屏幕截图操作,保存现场操作
        getScreenShot(getClass().getName());


    }

测试列表页是否可以正常打开

测试结果展示:

测试列表页是否可以正常打开


2.2.2 测试列表页的“查看全文”按钮是否可以正常跳转

测试代码:

 /*
     * 测试“查看全文“的按钮是否能点击
     * 在点击之后,跳转到博客详情页
     */
    @Test
    @Order(2)
    void listInspectAll() throws IOException {
        driver.findElement(By.xpath("/html/body/div[2]/div[2]/div[1]/a")).click();
        driver.findElement(By.cssSelector("body > div.container > div.container-right"));
        driver.findElement(By.cssSelector("#delete_button"));
        //进行屏幕截图操作,保存现场操作
        getScreenShot(getClass().getName());

    }

2.2.3 测试未登录的状态是否会跳转到登录页面

测试代码:

 /*
     * 未登录:则直接回到登录页面
     * 点击注销后,直接输入链接打开,然后进行元素的检查。
     * 最后要登录保持登录的状态,方便后续使用。
     */
    @Test
    @Order(3)
    void listFail() throws IOException {
        //点击注销后直接输入链接打开,然后进行元素的检查
        driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
        driver.findElement(By.cssSelector("body > div.nav > a:nth-child(6)")).click();
        driver.get("http://140.210.201.164:8080/blog_system/blog_list.html");
        driver.findElement(By.cssSelector("body > div.login-container > form > div"));
        //进行屏幕截图操作,保存现场操作
        getScreenShot(getClass().getName());

        //最后要进行登录方便后续使用
        driver.findElement(By.cssSelector("#username")).sendKeys("未央");
        driver.findElement(By.cssSelector("#password")).sendKeys("123");
        driver.findElement(By.cssSelector("#login-button")).click();
        //进行屏幕截图操作,保存现场操作
        getScreenShot(getClass().getName());

    }

2.2.4 列表页面总代码

列表页面测试总代码:

package com.blogWebAutoTest.Tests;

import com.blogWebAutoTest.common.AutotestUtils;
import org.junit.jupiter.api.*;
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeDriver;

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


// 博客列表页测试
//上一步是在登录成功
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class blogListTest extends AutotestUtils {
    public static ChromeDriver driver = createDriver();
    @BeforeAll
    static void baseControl() {
        driver.get("http://140.210.201.164:8080/blog_system/blog_list.html");
    }


    /*
     * 博客列表页可以正常显示的测试
     * 检查:个人的信息、菜单栏、列表以及右上角的模块内容
     */
    @Test
    @Order(1)
    void listPageLoadRight() throws IOException {
        // 可以多检查几个,确保正确
        driver.findElement(By.cssSelector("body > div.container > div.container-right > div:nth-child(1) > div.title"));
        driver.findElement(By.cssSelector("body > div.container > div.container-left > div > img"));
        driver.findElement(By.cssSelector("body > div.nav > a:nth-child(6)"));
        //进行屏幕截图操作,保存现场操作
        getScreenShot(getClass().getName());


    }


    /*
     * 测试“查看全文“的按钮是否能点击
     * 在点击之后,跳转到博客详情页
     */
    @Test
    @Order(2)
    void listInspectAll() throws IOException {
        driver.findElement(By.xpath("/html/body/div[2]/div[2]/div[1]/a")).click();
        driver.findElement(By.cssSelector("body > div.container > div.container-right"));
        driver.findElement(By.cssSelector("#delete_button"));
        //进行屏幕截图操作,保存现场操作
        getScreenShot(getClass().getName());

    }


    /*
     * 未登录:则直接回到登录页面
     * 点击注销后,直接输入链接打开,然后进行元素的检查。
     * 最后要登录保持登录的状态,方便后续使用。
     */
    @Test
    @Order(3)
    void listFail() throws IOException {
        //点击注销后直接输入链接打开,然后进行元素的检查
        driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
        driver.findElement(By.cssSelector("body > div.nav > a:nth-child(6)")).click();
        driver.get("http://140.210.201.164:8080/blog_system/blog_list.html");
        driver.findElement(By.cssSelector("body > div.login-container > form > div"));
        //进行屏幕截图操作,保存现场操作
        getScreenShot(getClass().getName());

        //最后要进行登录方便后续使用
        driver.findElement(By.cssSelector("#username")).sendKeys("未央");
        driver.findElement(By.cssSelector("#password")).sendKeys("123");
        driver.findElement(By.cssSelector("#login-button")).click();
        //进行屏幕截图操作,保存现场操作
        getScreenShot(getClass().getName());

    }
}

测试成功结果:


2.3 编辑页面的自动化测试

2.3.1 测试编辑页是否可以正确打开

测试代码:

/*
 * 测试编辑页可以正常打开
 */
@Test
@Order(1)
void editPageLoadRight() throws IOException {
    driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
    // 可以多检查几个,确保正确
    driver.findElement(By.cssSelector("#blog-title"));
    driver.findElement(By.cssSelector("#editor > div.CodeMirror.cm-s-default.CodeMirror-wrap > div.CodeMirror-scroll"));
    driver.findElement(By.xpath("//*[@id=\"submit\"]"));
    getScreenShot(getClass().getName());
}

2.3.2 测试博客是否可以正常编辑和发布 

测试代码:

/*
 * 正确编辑并发布博客测试
 * 目前是在列表页,直接点击列表页的按钮跳转到博客编辑页
 * 然后检查元素就行,注意要验证博客编辑页的特定的元素
 */
@Test
@Order(3)
void editAndSubmitBlog() throws IOException {
    driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
    driver.findElement(By.xpath("/html/body/div[1]/a[2]")).click();
    editPageLoadRight();
    String expect = "autoTest耶耶";
    // 编辑页的md是第三方插件,所以不可以直接使用sendKeys向编辑模块写入内容
    // 但是可以通过点击上方按钮进行内容的插入
    driver.findElement(By.cssSelector("#blog-title")).sendKeys(expect);
    driver.findElement(By.cssSelector("#editor > div.editormd-toolbar > div > ul > li:nth-child(5) > a")).click();
    driver.findElement(By.xpath("//*[@id=\"editor\"]/div[5]/div/ul/li[20]/a")).click();
    driver.findElement(By.cssSelector("#editor > div.editormd-toolbar > div > ul > li:nth-child(6) > a")).click();
    driver.findElement(By.xpath("//*[@id=\"submit\"]")).click();
    getScreenShot(getClass().getName());

    // 判断是否发布成功:
    // 获取第一篇博客的title的文本,检查是否相符即可(一定要找特定元素)
    String actual = driver.findElement(By.cssSelector("body > div.container > div.container-right > div:nth-child(1) > div.title")).getText();
    Assertions.assertEquals(expect,actual);
}

2.3.3 测试“写博客”按钮是否可以正常使用

测试代码:

/*
 * 测试“写博客”的按钮是否可以点击
 * 发布测试(无标题)
 */
@Test
@Order(2)
void editWriteAndNoTitle() throws IOException {
    driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
    // 进行无标题测试
    driver.findElement(By.cssSelector("#editor > div.editormd-toolbar > div > ul > li:nth-child(5) > a")).click();
    driver.findElement(By.xpath("//*[@id=\"editor\"]/div[5]/div/ul/li[20]/a")).click();
    driver.findElement(By.cssSelector("#editor > div.editormd-toolbar > div > ul > li:nth-child(6) > a")).click();
    driver.findElement(By.cssSelector("#submit")).click();
    getScreenShot(getClass().getName());

    // 进行博客列表页的元素检查
    driver.findElement(By.cssSelector("body > div.container > div.container-right > div:nth-child(1) > a"));
}

2.3.4 编辑页面总代码

编辑页面测试总代码:

package com.blogWebAutoTest.Tests;

import com.blogWebAutoTest.common.AutotestUtils;
import org.junit.jupiter.api.*;
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeDriver;

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

import static com.blogWebAutoTest.common.AutotestUtils.driver;
// 博客编辑页测试
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
static
class blogEditTest extends AutotestUtils {
    //在这创建驱动对象,保证后面都能用到他
    public static ChromeDriver driver = createDriver();

    @BeforeAll
    static void baseControl() {
        driver.get("http://140.210.201.164:8080/blog_system/blog_edit.html");

    }
}

/*
 * 测试编辑页可以正常打开
 */
@Test
@Order(1)
void editPageLoadRight() throws IOException {
    driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
    // 可以多检查几个,确保正确
    driver.findElement(By.cssSelector("#blog-title"));
    driver.findElement(By.cssSelector("#editor > div.CodeMirror.cm-s-default.CodeMirror-wrap > div.CodeMirror-scroll"));
    driver.findElement(By.xpath("//*[@id=\"submit\"]"));
    getScreenShot(getClass().getName());
}

/*
 * 正确编辑并发布博客测试
 * 目前是在列表页,直接点击列表页的按钮跳转到博客编辑页
 * 然后检查元素就行,注意要验证博客编辑页的特定的元素
 */
@Test
@Order(3)
void editAndSubmitBlog() throws IOException {
    driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
    driver.findElement(By.xpath("/html/body/div[1]/a[2]")).click();
    editPageLoadRight();
    String expect = "autoTest耶耶";
    // 编辑页的md是第三方插件,所以不可以直接使用sendKeys向编辑模块写入内容
    // 但是可以通过点击上方按钮进行内容的插入
    driver.findElement(By.cssSelector("#blog-title")).sendKeys(expect);
    driver.findElement(By.cssSelector("#editor > div.editormd-toolbar > div > ul > li:nth-child(5) > a")).click();
    driver.findElement(By.xpath("//*[@id=\"editor\"]/div[5]/div/ul/li[20]/a")).click();
    driver.findElement(By.cssSelector("#editor > div.editormd-toolbar > div > ul > li:nth-child(6) > a")).click();
    driver.findElement(By.xpath("//*[@id=\"submit\"]")).click();
    getScreenShot(getClass().getName());

    // 判断是否发布成功:
    // 获取第一篇博客的title的文本,检查是否相符即可(一定要找特定元素)
    String actual = driver.findElement(By.cssSelector("body > div.container > div.container-right > div:nth-child(1) > div.title")).getText();
    Assertions.assertEquals(expect,actual);
}


/*
 * 测试“写博客”的按钮是否可以点击
 * 发布测试(无标题)
 */
@Test
@Order(2)
void editWriteAndNoTitle() throws IOException {
    driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
    // 进行无标题测试
    driver.findElement(By.cssSelector("#editor > div.editormd-toolbar > div > ul > li:nth-child(5) > a")).click();
    driver.findElement(By.xpath("//*[@id=\"editor\"]/div[5]/div/ul/li[20]/a")).click();
    driver.findElement(By.cssSelector("#editor > div.editormd-toolbar > div > ul > li:nth-child(6) > a")).click();
    driver.findElement(By.cssSelector("#submit")).click();
    getScreenShot(getClass().getName());

    // 进行博客列表页的元素检查
    driver.findElement(By.cssSelector("body > div.container > div.container-right > div:nth-child(1) > a"));
}




2.4 详情页面的自动化测试

2.4.1 测试详情页是否可以正确打开

测试代码:

/*
 * 详情页是否可以正常打开
 * 第一种情况:没有blogId
 * 因为没有blogId会出现Undefined
 */
@Test
@Order(1)
void undefindedTest() throws IOException {
    driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
    String expect = "";
    String fact = driver.findElement(By.xpath("/html/body/div[2]/div[2]/div/div[1]")).getText();
    getScreenShot(getClass().getName());
    Assertions.assertEquals(expect,fact);
}


/*
 * 测试详情页正确打开
 * 第二种情况:有blogId
 * 通过验证测试标题以及时间一定有来判断是否正确打开
 */
@Test
@Order(2)
void blogDetailPageRight() throws IOException {
    driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
    driver.get("http://140.210.201.164:8080/blog_system/blog_detail.html?blogId=17");
    driver.findElement(By.cssSelector("body > div.container > div.container-right > div > h3"));
    driver.findElement(By.cssSelector("body > div.container > div.container-right > div > div.date"));
    driver.findElement(By.xpath("//*[@id=\"content\"]/p"));
    getScreenShot(getClass().getName());
    driver.findElement(By.xpath("/html/body/div[1]/a[1]")).click(); // 回到列表页
}

2.4.2 测试“删除”按钮是否可用

测试代码:

/*
 * 测试“删除”按钮是否可点击
 * 删除后会跳回到博客列表页,然后与最上面的时间进行比对即可
 * 注意:不能比较标题,因为标题可能为空,无法比较。
 * 这里是要删除第一篇博客
 */
@Test
@Order(3)
void deleteTest() throws IOException {
    driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
    getScreenShot(getClass().getName());
    driver.findElement(By.cssSelector("body > div.container > div.container-right > div:nth-child(1) > a")).click();
    String before = driver.findElement(By.xpath("/html/body/div[2]/div[2]/div/div[1]")).getText();
    driver.findElement(By.cssSelector("#delete_button")).click();
    String after = driver.findElement(By.cssSelector("body > div.container > div.container-right > div:nth-child(1) > div.date")).getText();
    getScreenShot(getClass().getName());
    Assertions.assertNotEquals(before,after);  // 比对不同
}

2.4.3 详情页面总代码

package com.blogWebAutoTest.Tests;

import org.junit.jupiter.api.*;
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeDriver;

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

import static com.blogWebAutoTest.common.AutotestUtils.createDriver;
import static com.blogWebAutoTest.common.AutotestUtils.driver;

// 博客详情页测试
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
 public class blogDetailTest {
    public static ChromeDriver driver = createDriver();
    @BeforeAll
    static void baseControl() {
        driver.get("http://140.210.201.164:8080/blog_system/blog_detail.html");
    }
}

/*
 * 详情页是否可以正常打开
 * 第一种情况:没有blogId
 * 因为没有blogId会出现Undefined
 */
@Test
@Order(1)
void undefindedTest() throws IOException {
    driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
    String expect = "";
    String fact = driver.findElement(By.xpath("/html/body/div[2]/div[2]/div/div[1]")).getText();
    getScreenShot(getClass().getName());
    Assertions.assertEquals(expect,fact);
}


/*
 * 测试详情页正确打开
 * 第二种情况:有blogId
 * 通过验证测试标题以及时间一定有来判断是否正确打开
 */
@Test
@Order(2)
void blogDetailPageRight() throws IOException {
    driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
    driver.get("http://140.210.201.164:8080/blog_system/blog_detail.html?blogId=17");
    driver.findElement(By.cssSelector("body > div.container > div.container-right > div > h3"));
    driver.findElement(By.cssSelector("body > div.container > div.container-right > div > div.date"));
    driver.findElement(By.xpath("//*[@id=\"content\"]/p"));
    getScreenShot(getClass().getName());
    driver.findElement(By.xpath("/html/body/div[1]/a[1]")).click(); // 回到列表页
}

/*
 * 测试“删除”按钮是否可点击
 * 删除后会跳回到博客列表页,然后与最上面的时间进行比对即可
 * 注意:不能比较标题,因为标题可能为空,无法比较。
 * 这里是要删除第一篇博客
 */
@Test
@Order(3)
void deleteTest() throws IOException {
    driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
    getScreenShot(getClass().getName());
    driver.findElement(By.cssSelector("body > div.container > div.container-right > div:nth-child(1) > a")).click();
    String before = driver.findElement(By.xpath("/html/body/div[2]/div[2]/div/div[1]")).getText();
    driver.findElement(By.cssSelector("#delete_button")).click();
    String after = driver.findElement(By.cssSelector("body > div.container > div.container-right > div:nth-child(1) > div.date")).getText();
    getScreenShot(getClass().getName());
    Assertions.assertNotEquals(before,after);  // 比对不同
}

//    // 注意更改驱动释放位置(在最后一个类/测试用例之后)
//    @AfterAll
//    static void driverQuite() {
//        driver.quit();
//    }

三、自动化测试总结

3.1 测试小结

测试要点总结:

要点1:页面元素的检查

对于页面的检查一定要到位,如检查元素是否存在来确保页面的正确性。


要点2:测试用例的执行顺序

一定要关注测试用例的执行顺序问题,防止出现逻辑错误导致自动化测试失败。


要点3:多参数测试
在进行登录页面多参数测试时候,注意之前账号的清空和页面的回退。


要点4:适当关注用例执行时间

如果时间过长就需要考虑是我们自己写的测试用例的问题还是程序真的有性能问题呢


要点5:获取元素的时候建议获取固定的元素

建议获取如时间、标题等;内容不建议获取,因为是动态的。

元素的路径是不可变的,所以可以使用xpath来进行元素的定位。


要点6:单独写一个类来存放驱动释放

为了避免遗漏or遗忘驱动释放的位置,然后直接放到套件测试类的最后就行。


要点7:注意屏幕截图保存的方式

动态时间戳并进行时间格式化,然后期望按照某种维度(天)以文件夹的方式进行保存。


要点8:驱动关闭的位置

驱动关闭的位置要注意,只有最后一个用例结束之后才进行关闭。


3.2 自动化测试过程的亮点

亮点1:无头模式

使用了无头模式:只注重结果,可以留出屏幕。

具体表现:


亮点2:使用JUnit5种的注解

避免生成过多的对象,造成资源和时间的浪费,提高了自动化的执行效率。


亮点3:使用了隐式等待

提高了自动化的运行效率,提高了自动化的稳定性,减小误报的可能性。

具体表现:


亮点4:使用了屏幕截图

方便对问题的追溯以及问题的解决,能够在出现问题时候快速检索问题,找到依据。

具体表现:


亮点5:使用测试套件

降低了测试人员的工作量,通过套件一次执行所有要运行的测试用例。

具体表现:

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

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

相关文章

idea中springboot项目创建后追加依赖

springboot项目创建后追加依赖 前言1、安装插件editstarters设置->插件 2、进入pom.xml 页面 前言 在项目创建的时候选择好依赖创建项目&#xff0c;之后追加依赖不是很方便&#xff0c;介绍一个简单的使用方法&#xff0c;通过editstarters进行添加 1、安装插件editstart…

Http协议综述

目录 一.B/S架构 二.Http协议 1.概述 2.特点 3.请求数据格式 &#xff08;1&#xff09;请求头 &#xff08;2&#xff09;请求行 &#xff08;3&#xff09;请求体 4.相应数据格式 &#xff08;1&#xff09;相应行 &#xff08;2&#xff09;相应头 &#xff08;…

鸡尾酒疗法 T1067

鸡尾酒疗法&#xff0c;原指 “高效抗逆转录病毒治疗”&#xff08;HAARTHAART&#xff09;&#xff0c;由美籍华裔科学家何大一于 1996 年提出&#xff0c;是通过三种或三种以上的抗病毒药物联合使用来治疗艾滋病。该疗法的应用可以减少单一用药产生的抗药性&#xff0c;最大限…

假如有n个台阶,一次只能上1个台阶或2个台阶,请问走到第n个台阶有几种走法?

说明如下:假如有 3个台阶&#xff0c;那么总计就有3种走法:第一种为每次上1个台阶&#xff0c;上3次;第二种为先上2个台阶&#xff0c;再上1个台阶;第三种为先上1个台阶&#xff0c;再上2个台阶。 解决方法&#xff1a;递归 代码展示&#xff1a; #include <stdio.h> …

chromedriver,Chrome驱动的实时更新

发现自己的selenium项目跑不起来了 效验驱动版本 下载链接(可能需要魔法) https://registry.npmmirror.com/binary.html?pathchromedriver/ https://googlechromelabs.github.io/chrome-for-testing/ 找到驱动位置 1. 默认安装路径&#xff1a;Chrome驱动通常会默认安装在系…

要求将两个链表合并成一个有序(从小到大)链表

给定两个元素有序&#xff08;从小到大&#xff09;的链表&#xff0c;要求将两个链表合并成一个有序&#xff08;从小到大&#xff09;链表&#xff0c; 输入描述: 第一行输入第一个链表的结点数S1&#xff0c;S1<100。 第二行输入S1个整数&#xff0c;两两之间用空格隔开…

Android---SmartRefreshLayout实现上拉刷新和下拉加载更多

1. 在 build.gradle 中添加依赖 // 下拉刷新&#xff0c;上拉加载更多 // https://github.com/scwang90/SmartRefreshLayout implementation io.github.scwang90:refresh-layout-kernel:2.1.0 //核心必须依赖 implementation io.github.scwang90:refresh-header-classics…

CleanMyMac X2024一款专为Mac用户设计的优化工具

亲爱的用户们&#xff0c;我们都知道电脑在长时间使用后会变得越来越慢&#xff0c;垃圾文件和无用的应用程序会占用我们的硬盘空间&#xff0c;让我们的电脑变得像蜗牛一样慢。但是&#xff0c;现在有一个解决方案可以让你的电脑重获新生&#xff0c;那就是CleanMyMac X&#…

笔记本hp6930p安装Android-x86补记

在上一篇日记中&#xff08;笔记本hp6930p安装Android-x86避坑日记-CSDN博客&#xff09;提到hp6930p安装Android-x86-9.0&#xff0c;无法正常启动&#xff0c;本文对此再做尝试&#xff0c;原因是&#xff1a;Android-x86-9.0不支持无线网卡&#xff0c;需要在BIOS中关闭WLAN…

哪里下载Mac上最全面的系统清理工具,CleanMyMac X4.15中文版永久版资源啊

哪里下载Mac上最全面的系统清理工具&#xff0c;CleanMyMac X4.15中文版永久版资源啊&#xff0c;CleanMyMac X4.15中文版是一款全面的Mac系统优化工具。它能够扫描、检测并清理不需要的文件和应用程序&#xff0c;优化内存使用和磁盘空间&#xff0c;提高Mac的性能表现。此外&…

寻址错题本

指令寻址 顺序寻址 通过程序计数器PC自动加1,形成下一条指令的指令地址。 跳跃寻址 通过转移类指令实现跳转到指定的代码段或者子程序。 数据寻址 直接寻址 形式地址A就是操作数的地址EA,执行阶段访问一次存储器。 所以当我们需要取得实际的值(操作数)的时候: 第一步:…

【CSP试题回顾】202312-1-仓库规划

CSP-202312-1-仓库规划 解题思路 定义结构体和变量&#xff1a; 结构体 MyWareHouse&#xff0c;用来存储每个仓库的索引&#xff08;编号&#xff09;和位置编码。定义了整数 n 和 m&#xff0c;分别代表仓库的数量和位置编码的维数。定义了一个 vector<MyWareHouse> 的…

springboot心灵治愈交流平台源码和论文

本论文主要论述了如何使用JAVA语言开发一个心灵治愈交流平台 &#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述心灵治愈交流平台的当前背景以及系统开发的目的&a…

ssm666社区流浪动物救助领养系统的设计与开发

** &#x1f345;点赞收藏关注 → 私信领取本源代码、数据库&#x1f345; 本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目希望你能有所收获&#xff0c;少走一些弯路。&#x1f345;关注我不迷路&#x1f345;** 一 、设计说明 1.1 课题…

Vue开发实例(一)Vue环境搭建第一个项目

Vue环境搭建&第一个项目 一、环境搭建二、安装Vue脚手架三、创建Vue项目 一、环境搭建 下载方式从官网下载&#xff1a;http://nodejs.cn/download/ 建议下载v12.16.0版本以上的&#xff0c;因为版本低无法创建Vue的脚手架 检验是否安装成功 配置环境变量 新增NODE_HOME&…

termux上安装Python

Termux是一款Android平台下的终端模拟器和Linux环境应用&#xff0c;它允许用户在移动设备上访问Linux命令行界面&#xff0c;以便使用命令行工具、脚本、开发环境等功能。 要在Termux上安装Python&#xff0c;请按照以下步骤进行操作&#xff1a; 一&#xff0c;下载termux …

Linux 开发工具vim、gcc/g++、makefile

目录 Linux编辑器-vim 1. 基本概念 2. 基本操作 3. 正常模式命令集 4. 末行模式命令集 5. 其他操作 6. 简单vim配置 Linux编译器-gcc/g 1、基本概念 2、程序翻译的过程 3. gcc如何完成程序翻译 4、动静态库 Linux项目自动化构建工具-make/Makefile 1、背景 2、…

Springboot+vue的医药管理系统(有报告)。Javaee项目,springboot vue前后端分离项目。

演示视频&#xff1a; Springbootvue的医药管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot vue前后端分离项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层…

C#,基于密度的噪声应用空间聚类算法(DBSCAN Algorithm)源代码

1 聚类算法 聚类分析或简单聚类基本上是一种无监督的学习方法&#xff0c;它将数据点划分为若干特定的批次或组&#xff0c;使得相同组中的数据点具有相似的属性&#xff0c;而不同组中的数据点在某种意义上具有不同的属性。它包括许多基于差分进化的不同方法。 E、 g.K-均值…

Vue开发实例(十)Tabs标签页打开、关闭与路由之间的关系

创建标签页 一、创建标签页二、点击菜单展示新标签页1、将标签数据作为全局使用2、菜单点击增加标签页3、处理重复标签4、关闭标签页 三、点击标签页操作问题1&#xff1a;点击标签页选中菜单进行高亮展示问题2&#xff1a;点击标签页路由也要跳转 四、解决bug 先展示最终效果 …