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

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

博客首页:未央.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;// 创建驱动对象createDriverpublic 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();// 如果要测试登录页面,则所有的用来都会用到 创建驱动+打开浏览器@BeforeAllstatic 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();@BeforeAllstatic 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();@BeforeAllstatic 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();@BeforeAllstatic 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.hqwc.cn/news/506234.html

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

相关文章

#WEB前端(HTML属性)

1.实验&#xff1a;a,img 2.IDE&#xff1a;VSCODE 3.记录&#xff1a; a: href插入超链接 默认情况下在本窗口打开链接, target可以设置打开的窗口,parent在父窗口打开&#xff0c;blank新开串口打开,top在顶层串口打开,self为默认在本窗口打开 img: 插入图片 可以插…

Java中线程安全的集合类

在先前的文章中我们已经讲过了原子类(线程安全的基本类型&#xff0c;基于CAS实现)&#xff0c;详见常见锁策略&#xff0c;synchronized内部原理以及CAS-CSDN博客 &#xff0c;我们在来讲一下集合类&#xff0c;在原来的集合类&#xff0c;大多数是线程不安全的&#xff0c;虽…

Java练习(第5天)【总结】在字符串中寻找特定的字符(5种方法)

问题描述&#xff1a;在字符串中寻找特定字符 1、第1次出现位置 实现函数原型&#xff1a; int indexOf(char c) Java代码&#xff1a; import java.io.*; public class Way_1 {public static void main(String args[]){String str "Geeks for Geeks is a computer s…

深入Kafka client

分区分配策略 客户端可以自定义分区分配策略, 当然也需要考虑分区消费之后的offset提交, 是否有冲突。 消费者协调器和组协调器 a. 消费者的不同分区策略, 消费者之间的负载均衡(新消费者加入或者存量消费者退出), 需要broker做必要的协调。 b. Kafka按照消费组管理消费者, …

每日一题——LeetCode1566.重复至少K次且长度为M的模式

方法一 暴力枚举 var containsPattern function(arr, m, k) {const n arr.length;for (let l 0; l < n - m * k; l) {let offset;for (offset 0; offset < m * k; offset) {if (arr[l offset] ! arr[l offset % m]) {break;}}if (offset m * k) {return true;}}r…

【数据结构与算法】整数二分

问题描述 对一个排好序的数组&#xff0c;要求找到大于等于7的最小位置和小于等于7的最大位置 大于等于7的最小位置 易知从某个点开始到最右边的边界都满足条件&#xff0c;我们要找到这个区域的最左边的点。 开始二分&#xff01; left指针指向最左边界&#xff0c;right…

【JGit 】一个完整的使用案例

需求 生成一系列结构相同的项目代码&#xff0c;将这些项目的代码推送至一个指定的 Git 仓库&#xff0c;每个项目独占一个分支。 推送时若仓库不存在&#xff0c;则自动创建仓库。 分析 生成代码使用 Java 程序模拟&#xff0c;每个项目中模拟三个文件。Project.cpp 、Pro…

C习题002:澡堂洗澡

问题 输入样例 在这里给出一组输入。例如&#xff1a; 2 5 1 3 3 2 3 3 输出样例 在这里给出相应的输出。例如&#xff1a; No代码长度限制 16 KB 时间限制 400 ms 内存限制 64 MB 栈限制 8192 KB 代码 #include<stdio.h> int main() {int N,W,s,t,p;int arr_s[…

将任何网页变成桌面应用,全平台支持 | 开源日报 No.184

tw93/Pake Stars: 20.9k License: MIT Pake 是利用 Rust 轻松构建轻量级多端桌面应用的工具。 与 Electron 包大小相比几乎小了 20 倍&#xff08;约 5M&#xff01;&#xff09;使用 Rust Tauri&#xff0c;Pake 比基于 JS 的框架更轻量和更快内置功能包括快捷方式传递、沉浸…

测试需求平台9-Table 组件应用产品列表优化

✍此系列为整理分享已完结入门搭建《TPM提测平台》系列的迭代版&#xff0c;拥抱Vue3.0将前端框架替换成字节最新开源的arco.design&#xff0c;其中约60%重构和20%新增内容&#xff0c;定位为从 0-1手把手实现简单的测试平台开发教程&#xff0c;内容将囊括基础、扩展和实战&a…

(每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理 第13章 项目资源管理(一)

项目建议与立项申请、初步可行性研究、详细可行性研究、评估与决策是项目投资前使其的四个阶段。在实际工作中&#xff0c;初步可行性研究和详细可行性研究可以依据项目的规模和繁简程度合二为一&#xff0c;但详细可行性研究是不可缺少的。升级改造项目制作初步和详细研究&…

2024年十大前景职业揭晓!提前布局,抢占未来职场制高点!

随着科技的飞速发展和社会的不断进步&#xff0c;各行各业都在经历着翻天覆地的变化。2024年即将到来&#xff0c;哪些职业将会成为未来的热门选择呢&#xff1f;本文将为您揭晓2024年十大前景职业&#xff0c;助您提前布局&#xff0c;抢占未来职场制高点&#xff01; 一、人…