论坛系统项目自动化测试
- 前述
- 一、脑图
- 二、代码编写
- 1.公共类InitAndEnd
- 1.登录页面测试ForumLoginTest
- 正常登录:
- 异常登录:
- 3.注册页面测试ForumRegisterTest
- 注册成功:
- 注册失败:
- 4论坛列表页面测试ForumListTest
- 登录状态下:
- 未登录状态下:
- 5.论坛帖子编辑测试ForumEditTest
- 登录状态下
- 未登录状态下:
- 6.个人中心显示测试ForumPerson
- 登录状态下:
- 异常登录状态下:
- 7.退出操作测试ForumOut
- 8.驱动释放DriverQuiteTest
- 3.代码测试:
- 5.小结:
- 6. 难点以及亮点
- 一、难点
- 二、亮点
前述
基于前后端分离的论坛系统,进行自动化测试。个人博客主要有五个页面构成:登录页、注册页、论坛列表展示页,帖子发布和个人中心页面。测试登录页面,注册页面,论坛列表页展示页面以及论坛帖子发布页面,个人信息展示,退出操作功能。
个人博客地址:https://gitee.com/arlene-c/auto_test_forum.git
自动化测试一般步骤:
1)使用脑图编写web自动化测试用例
2)创建自动化项目,根据用例来实现脚本
一、脑图
二、代码编写
- 添加相关依赖pom.xml
<dependencies><!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java --><dependency><groupId>org.seleniumhq.selenium</groupId><artifactId>selenium-java</artifactId><version>3.141.59</version></dependency><!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api --><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><version>5.9.1</version></dependency><!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-params --><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-params</artifactId><version>5.9.1</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.11.0</version></dependency><dependency><groupId>org.junit.platform</groupId><artifactId>junit-platform-suite</artifactId><version>1.9.1</version><scope>test</scope></dependency><dependency><groupId>org.junit.platform</groupId><artifactId>junit-platform-suite</artifactId><version>1.9.1</version></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-engine</artifactId><version>5.9.1</version><scope>test</scope></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>
-
新建包并在包下创建测试类以及公共类
以下是所建立的是common公共包和Tests测试包:
-
新建包并在包下创建测试类以及公共类
1)公共类InitAndEnd
2)登录页面测试ForumLogin
3)列表页测试 ForumList
4)编辑页测试 ForumEdit
5)详情页测试ForumDetail
6)个人中心测试ForumPerson
7)退出操作测试ForumOut
8)驱动释放DriverQuite
9)测试套件runSuite -
代码参考
三、代码测试
https://gitee.com/arlene-c/auto_test_forum.git
1.公共类InitAndEnd
创建公共的驱动对象,方便代码复用。减少内存消耗;
在保存现场截图,然后图片的名称要体现出测试类的类名,方便进行问题的追溯。
public class InitAndEnd {static WebDriver webDriver;@BeforeAllstatic void SetUp(){webDriver=new ChromeDriver();}@AfterAllstatic void TearDown(){webDriver.quit();}public List<String> getTime(){//文件按照天的维度按文件夹进行保存//文件格式 20230212-123030毫秒SimpleDateFormat sim1=new SimpleDateFormat("yyyyMMdd-HHmmssSS");SimpleDateFormat sim2=new SimpleDateFormat("yyyyMMdd");String filename = sim1.format(System.currentTimeMillis());String dirname = sim2.format(System.currentTimeMillis());List<String> list =new ArrayList<>();list.add(dirname);list.add(filename);return list;}
1.登录页面测试ForumLoginTest
正常登录:
@ParameterizedTest@CsvSource(value = "linlin, 111111")void Login1(String username, String password) throws InterruptedException, IOException {// 打开登录页面webDriver.get("http://127.0.0.1:58080/sign-in.html");webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 输入用户名webDriver.findElement(By.cssSelector("#username")).sendKeys(username);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 输入密码webDriver.findElement(By.cssSelector("#password")).sendKeys(password);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 点击提交webDriver.findElement(By.cssSelector("#submit")).click();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.MINUTES);Thread.sleep(1000); // 显示等待,等待弹窗出现// 上述步骤只是说明输入了账号和密码,但还不知道点击提交后是否会跳转到博客列表页String expect = "http://127.0.0.1:58080/index.html";String actual = webDriver.getCurrentUrl();//
// // 进行截图,看当前是否跳转到了登录界面webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);Assertions.assertEquals(expect, actual); // 查看当前的url是否在博客详情页面// 进行截图,看当前是否跳转到了登录界面// 程序执行的速度和页面渲染的速度File srcFile = ((TakesScreenshot) webDriver).getScreenshotAs(OutputType.FILE);String fileName = "loginTest.png";FileUtils.copyFile(srcFile, new File(fileName));Thread.sleep(1000); // 显示等待,等待弹窗出现
异常登录:
/*** 场景2:用户名正常,密码错误*/@Order(2)@ParameterizedTest@CsvSource(value = "linlin, 123")void Login2(String username, String password) throws InterruptedException, IOException {// 打开登录页面webDriver.get("http://127.0.0.1:58080/sign-in.html");webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 输入用户名webDriver.findElement(By.cssSelector("#username")).sendKeys(username);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 输入密码webDriver.findElement(By.cssSelector("#password")).sendKeys(password);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 点击提交webDriver.findElement(By.cssSelector("#submit")).click();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.MINUTES);Thread.sleep(1000);String msg = webDriver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div")).getText();System.out.println(msg);}
3.注册页面测试ForumRegisterTest
论坛注册页面是否可以正常显示;
测试注册功能正常情况,注册成功会返回登录页面;
测试注册功能异常情况,用户名重复和两次密码不一致,报出警告,停留在注册页面;
注册成功:
public class ForumRegister extends InitAndEnd{/*** 场景1:不存在的用户名,昵称,两次密码一致*/@Order(1)@ParameterizedTest@CsvSource(value = "best,best,123,123")void Register(String username, String nickname,String password1,String password2) throws InterruptedException, IOException {// 打开注册页面webDriver.get("http://127.0.0.1:58080/sign-in.html");//点击注册按钮body > div > div > div > div:nth-child(1) > div > div.text-center.text-muted.mt-3 > awebDriver.findElement(By.cssSelector("body > div > div > div > div:nth-child(1) > div > div.text-center.text-muted.mt-3 > a")).click();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 输入用户名webDriver.findElement(By.cssSelector("#username")).sendKeys(username);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 输入昵称webDriver.findElement(By.cssSelector("#nickname")).sendKeys(nickname);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 输入密码webDriver.findElement(By.cssSelector("#password")).sendKeys(password1);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 确认密码webDriver.findElement(By.cssSelector("#passwordRepeat")).sendKeys(password2);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);//点击复选框webDriver.findElement(By.cssSelector("#policy")).click();// 点击提交webDriver.findElement(By.cssSelector("#submit")).click();Thread.sleep(1000); // 显示等待// 注册成功之后,判断是否会跳转回登录界面String expect = "http://127.0.0.1:58080/sign-in.html";String actual = webDriver.getCurrentUrl();// 进行截图,看当前是否跳转到了登录界面webDriver.manage().timeouts().implicitlyWait(300, TimeUnit.MINUTES);Assertions.assertEquals(expect, actual);System.out.println("注册成功");// 进行截图,看当前是否跳转到了登录界面
注册失败:
/*** 场景2:已存在的用户名,昵称*/@Order(2)@ParameterizedTest@CsvSource(value = "linlin,linlin,111111,11111")void RegisterFail(String username, String nickname,String password1,String password2) throws InterruptedException, IOException {// 打开注册页面webDriver.get("http://127.0.0.1:58080/sign-in.html");//点击注册按钮body > div > div > div > div:nth-child(1) > div > div.text-center.text-muted.mt-3 > awebDriver.findElement(By.cssSelector("body > div > div > div > div:nth-child(1) > div > div.text-center.text-muted.mt-3 > a")).click();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 输入用户名webDriver.findElement(By.cssSelector("#username")).sendKeys(username);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 输入昵称webDriver.findElement(By.cssSelector("#nickname")).sendKeys(nickname);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 输入密码webDriver.findElement(By.cssSelector("#password")).sendKeys(password1);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 确认密码webDriver.findElement(By.cssSelector("#passwordRepeat")).sendKeys(password2);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);//点击复选框webDriver.findElement(By.cssSelector("#policy")).click();// 点击提交webDriver.findElement(By.cssSelector("#submit")).click();Thread.sleep(1000); // 显示等待// 注册成功之后,判断是否会跳转回登录界面String expect = "http://127.0.0.1:58080/sign-in.html";String actual = webDriver.getCurrentUrl();// 进行截图,看当前是否跳转到了登录界面webDriver.manage().timeouts().implicitlyWait(300, TimeUnit.MINUTES);Assertions.assertEquals(expect, actual);System.out.println("注册成功");
4论坛列表页面测试ForumListTest
登录状态下,列表页面是否可以正常显示;
未登录状态,列表页面是否可以正常显示;
在单独进行该案例测试的时候,可以检测是否弹出了警告或者回到了登陆页面,用来判断未登录状态下的,列表页面功能是否正常
登录状态下:
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class FormList extends InitAndEnd {/*** 论坛列表页帖子数量不为0*/@Testvoid ListSuc() throws IOException {webDriver.get("http://127.0.0.1:58080/sign-in.html");webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);int title_num = webDriver.findElements(By.cssSelector(".title")).size();Assertions.assertEquals(0, title_num);}@ParameterizedTest@CsvSource(value = "linlin, 111111")void ListDetail(String username, String password) throws InterruptedException, IOException {//1-登录// 打开登录页面webDriver.get("http://127.0.0.1:58080/sign-in.html");webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 输入用户名webDriver.findElement(By.cssSelector("#username")).sendKeys(username);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 输入密码webDriver.findElement(By.cssSelector("#password")).sendKeys(password);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 点击提交webDriver.findElement(By.cssSelector("#submit")).click();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.MINUTES);//2-查看页面的文本内容显示是否正确String expect1 = "首页";System.out.println();//#article_list_board_title #article_list_board_title #bit-forum-content > div.page-header.d-print-none > div > div > div.col-auto.ms-auto.d-print-none > divString actual1 = webDriver.findElement(By.cssSelector("#article_list_board_title")).getText();Assertions.assertEquals(expect1, actual1); // 断言//截图File srcFile = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE);String fileName = "BlogListSuccess.png";FileUtils.copyFile(srcFile, new File(fileName));//3-查看是否有发布帖子按钮,并点击webDriver.findElement(By.cssSelector("#bit-forum-content > div.page-header.d-print-none > div > div > div.col-auto.ms-auto.d-print-none > div > a.btn.btn-primary.d-none.d-sm-inline-block.article_post")).click();Thread.sleep(1000);//查看是否跳转到博客编辑页面String expectUrl = "http://127.0.0.1:58080/index.html";String actualUrl = webDriver.getCurrentUrl();Assertions.assertEquals(expectUrl, actualUrl); // 断言System.out.println("跳转到边界帖子页面");
未登录状态下:
/*** 未登录状态下,进入博客列表页,是否跳转回登录页面*/@Testvoid ForumList1() throws InterruptedException, IOException {//1-不登录,直接打开博客显示列表页webDriver.get("http://127.0.0.1:58080/index.html");//获取当前的url地址String expect = "http://127.0.0.1:58080/sign-in.html";String actual = webDriver.getCurrentUrl();//判断是否跳转到登录界面webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);Assertions.assertEquals(expect, actual);//截图File srcFile = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE);String fileName = "ForumListFailed.png";FileUtils.copyFile(srcFile, new File(fileName));}
}
5.论坛帖子编辑测试ForumEditTest
未登录状态,编辑页面是否可以正常显示,是否弹出警告或者多次进入而回到了登陆页面;
登录状态下,编辑页面是否可以正常显示,是否可以显示出编辑页面独有的元素;
登陆状态下,论坛帖子编辑功能是否正常
测试帖子分类模块,输入标题和内容,进行正常编辑功能测试;
只输入标题不输入内容,只输入内容不输入标题,以及标题和内容全都不输入的这三种情况,来进行异常编辑功能测试;
登录状态下
/*** 场景2:登录状态下*/@Order(2)@ParameterizedTest@CsvSource(value = "linlin, 111111")void WriteBlog2(String username, String password) throws InterruptedException, IOException {//1-登录// 打开登录页面webDriver.get("http://127.0.0.1:58080/sign-in.html");webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 输入用户名webDriver.findElement(By.cssSelector("#username")).sendKeys(username);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 输入密码webDriver.findElement(By.cssSelector("#password")).sendKeys(password);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 点击提交webDriver.findElement(By.cssSelector("#submit")).click();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.MINUTES);//场景2:输入标题,内容为空,点击发布帖子按钮,获取警告信息//2-点击 发布帖子按钮#article_post_submitwebDriver.findElement(By.cssSelector("#bit-forum-content > div.page-header.d-print-none > div > div > div.col-auto.ms-auto.d-print-none > div > a.btn.btn-primary.d-none.d-sm-inline-block.article_post")).click();//场景1:输入标题webDriver.findElement(By.cssSelector("#article_post_title")).sendKeys("标题");Thread.sleep(3000);//输入内容#edit-article > div.editormd-toolbar > div > ul > li:nth-child(20)webDriver.findElement(By.cssSelector("#edit-article > div.CodeMirror.cm-s-default.CodeMirror-wrap.CodeMirror-empty > div.CodeMirror-scroll > div.CodeMirror-sizer > div > div > div > div.CodeMirror-code > div > pre")).sendKeys("内容");Thread.sleep(3000);//点击提交按钮webDriver.findElement(By.cssSelector("#article_post_submit")).click();//获取警告框信息System.out.println(webDriver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div")).getText());// 截图File srcFile = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE);String fileName = "WriteBlogFailed.png";FileUtils.copyFile(srcFile, new File(fileName));}
}
未登录状态下:
/*** 场景1:未登录状态下,是否跳转回登录页面*/@Order(1)@Testvoid WriteBlog1() throws InterruptedException, IOException {//1-不登录,直接打开博客编辑页webDriver.get("http://127.0.0.1:58080/index.html");//获取当前的url地址String expect = "http://127.0.0.1:58080/sign-in.html";String actual = webDriver.getCurrentUrl();//判断是否跳转到登录界面webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);Assertions.assertEquals(expect, actual);//截图File srcFile = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE);String fileName = "WriteBlogFailed.png";FileUtils.copyFile(srcFile, new File(fileName));}
6.个人中心显示测试ForumPerson
登录状态下,进入博客列表页,点击我的帖子,跳转到个人中心页面,查看是否有用户昵称电话等信息。
登录状态下:
void BlogList2(String username, String password) throws InterruptedException, IOException {//1-登录// 打开登录页面webDriver.get("http://127.0.0.1:58080/sign-in.html");webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 输入用户名webDriver.findElement(By.cssSelector("#username")).sendKeys(username);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 输入密码webDriver.findElement(By.cssSelector("#password")).sendKeys(password);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 点击提交webDriver.findElement(By.cssSelector("#submit")).click();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.MINUTES);//2-点击我的帖子webDriver.findElement(By.cssSelector("#index_nav_avatar")).click();Thread.sleep(1000);webDriver.findElement(By.cssSelector("#index_user_settings")).click();Thread.sleep(1000);//是否有用户昵称webDriver.findElement(By.cssSelector("#settings_nickname"));//是否有“昵称”这两个字webDriver.findElement(By.cssSelector(" #bit-forum-content > div.page-body > div > div > div > div.col.d-flex.flex-column > div > h3:nth-child(4)"));//是否有“邮箱地址”这几个字webDriver.findElement(By.cssSelector(" #bit-forum-content > div.page-body > div > div > div > div.col.d-flex.flex-column > div > h3:nth-child(7)"));//是否有“电话号码”这几个字webDriver.findElement(By.cssSelector(" #bit-forum-content > div.page-body > div > div > div > div.col.d-flex.flex-column > div > h3:nth-child(10)"));//是否有“修改密码”这几个字webDriver.findElement(By.cssSelector(" #bit-forum-content > div.page-body > div > div > div > div.col.d-flex.flex-column > div > h3:nth-child(13)"));//是否有“提交修改”按钮#settings_input_passwordRepeatwebDriver.findElement(By.cssSelector("#settings_submit_password"));Thread.sleep(1000);//
异常登录状态下:
页面跳转到登录页面
7.退出操作测试ForumOut
点击右上角的头像点击退出,看是否到达登录页面
@ParameterizedTest@CsvSource(value = "linlin, 111111")void LoginOut1(String username, String password) throws InterruptedException, IOException {//1-登录// 打开登录页面webDriver.get("http://127.0.0.1:58080/sign-in.html");webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 输入用户名webDriver.findElement(By.cssSelector("#username")).sendKeys(username);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 输入密码webDriver.findElement(By.cssSelector("#password")).sendKeys(password);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 点击提交webDriver.findElement(By.cssSelector("#submit")).click();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.MINUTES);//2-点击我的帖子webDriver.findElement(By.cssSelector("#index_nav_avatar")).click();Thread.sleep(1000);//点击退出按钮webDriver.findElement(By.cssSelector("#index_user_logout")).click();Thread.sleep(1000);//获取当前的url地址String expect = "http://127.0.0.1:58080/sign-in.html";String actual = webDriver.getCurrentUrl();//判断是否跳转到登录界面webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);Assertions.assertEquals(expect, actual);
8.驱动释放DriverQuiteTest
为了方便一整套测试流程的进行,也是为了节省资源,避免在每个类之后都进行驱动释放,这里我们新建了一个驱动释放类。,执行驱动释放操作可以释放驱动程序所占用的资源,包括内存、I/O资源、中断资源等,避免资源泄露和系统性能下降。
public class DriverQuit extends InitAndEnd {public static ChromeDriver webDriver = createDriver();@Testvoid DriverQuit(){webDriver.quit();}
3.代码测试:
全部测试通过
5.小结:
1.首先应该选择那些需要频繁执行的、重复性高的测试用例进行自动化。
2.维护良好的测试数据:确保测试数据的一致性和准确性,避免测试中出现因数据问题导致的误判。
3.等待页面加载:在自动化测试中,需要合理设置等待时间,以确保页面元素加载完成。可以使用隐式或显式等待方法来处理页面加载等待。
4.避免硬编码:在编写测试脚本时,避免硬编码,使用变量和参数化来提高脚本的可维护性和灵活性。
5.处理异常情况:在测试过程中,遇到异常情况时需要有相应的处理机制,添加断言、截图或日志记录.
6.平台和环境兼容性:考虑不同平台和环境的兼容性,确保自动化测试在各种场景下都能正常执行。
7.持续集成和持续部署:将自动化测试集成到持续集成和持续部署流程中,实现快速反馈和自动化输出。
9.出现编码问题时,可以仔细检查idea的编码设置,更改后要进行刷新。
10.要仔细对比前端每个测试的按钮的形式,跳转等
11.测试用例不是越多越好
6. 难点以及亮点
一、难点
很容易出现报错,对前端页面的不熟悉导致按钮使用的形式不正确,需要合理设置等待时间,以确保页面元素加载完成。可以使用隐式或显式等待方法来处理页面加载等待。避免硬编码,使用变量和参数化来提高脚本的可维护性和灵活性。
二、亮点
1.可重复执行:自动化测试脚本可以重复执行相同的测试用例,确保测试结果的一致性,同时方便团队随时随地进行测试。
2.支持多平台和多浏览器:自动化测试工具可以支持跨平台和跨浏览器测试,提高测试覆盖范围,确保软件在不同环境下的稳定性。
3.使用了JUnit5中提供的注解:避免生成过多的对象,造成资源和时间的浪费,提高了自动化的执行效率。
4. 只创建一次驱动对象,避免每个用例重复创建驱动对象造成时间和资源的浪费。
5. 使用参数化:保持用例的简洁,提高代码的可读性
6. 使用测试套件:降低了测试人员的工作量,通过套件一次执行所有要运行的测试用例。
7. 使用了等待:提高了自动化的运行效率,提高了自动化的稳定性,减小误报的可能性。
8.使用了屏幕截图:方便问题的追溯以及问题的解决
9.使用了公共类,继承,简化了代码