JAVA项目测试----用户管理系统

一)项目简介:

用户管理系统是依据于前后端分离来实现的,是基于Spring SpringBoot Spring MVC,SpringAOP,MyBatis等框架来实现的一个用户管理网站,并且已经部署到了云服务器上,

目前的用户管理系统实现了超级管理员的注册功能,用户管理员的新增,删除,修改,用户分页展示,批量删除,多条件查询等功能

二)测试计划:

测试对象:基于SSM实现的用户管理系统

测试目的:验证用户管理系统是否可以正常的运行,验证用户管理系统是否符合用户的需求

测试点:主要针对常用的主流程功能进行测试,除此之外还有界面测试+功能测试+兼容性测试+安全性测试+可靠性测试+容错性测试+性能测试+网络测试;

测试方法:主要使用黑盒测试方法,自动化测试工具使用Selenium4+junit5

三)手工测试用例的编写:

 飞书访问链接:https://nxqjlyz94q2.feishu.cn/wiki/GwIRwI5Ebi3qtDkfJq4cG3bPnWe?create_from=create_doc_to_wiki#mindmap

一)针对于登录界面进行测试:

一)界面测试:


二)功能测试:

三)兼容性+易用性+安全性测试+性能测试:

4)可靠性:让软件运行几周,软件正常运行的时间/软件在这段期间运行的时间+软件在这段期间出故障的时间

二)针对于用户列表页进行功能测试:(其他非功能测试和上出的登录非功能测试类似)

三)针对于用户修改页面和用户修改页面进行功能测试(其他非功能测试和上出的登录非功能测试类似)

四)基于selenium4+junit5进行自动化测试

创建全局驱动对象,避免频繁创建销毁

一)针对于登录界面进行自动化测试

1)校验首页是否正常展示功能并且通过多参数验证用户登录功能


@SpringBootTest
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class LoginTest  {private static ChromeDriver driver= (ChromeDriver) CommonDriver.getDriver();//验证首页元素展示是正确@BeforeEachpublic void getUrl(){//打开浏览器driver.get("http://127.0.0.1:8080/login.html");driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));}@Order(1)@Testvoid CheckElementLogin(){//1.检查页面上一些文字的显示,url是否正确String text1=driver.findElement(By.cssSelector("#body > div > h3")).getText();String text2=driver.findElement(By.cssSelector("#body > div > div:nth-child(2) > label")).getText();String text3=driver.findElement(By.cssSelector("#body > div > div:nth-child(3) > label")).getText();String text4=driver.findElement(By.cssSelector("#submit")).getAttribute("value");String url=driver.getCurrentUrl();//2.校验信息元素是否正确,比如说校验文本是否符合预期Assertions.assertEquals(text1,"管理员登录");Assertions.assertEquals(text2,"用户名:");Assertions.assertEquals(text3,"密码:");Assertions.assertEquals(text4,"登录");Assertions.assertEquals(url,"http://127.0.0.1:8080/login.html");}@AfterEachpublic void close(){driver.close();}
}

2)针对于登录构建多数据登录

@ParameterizedTest@MethodSource("loginData")public void login(String username,String password) throws InterruptedException {//定位到登陆页面中的输入框核按钮进行登陆操作driver.findElement(By.cssSelector("#loginname")).sendKeys(username);driver.findElement(By.cssSelector("#password")).sendKeys(password);driver.findElement(By.cssSelector("#submit")).click();Thread.sleep(10);}public static Stream<Arguments> loginData(){return Stream.of(Arguments.arguments("张三","123"),Arguments.arguments("zhangsan","admin"));}
多组参数化执行本身不会新打开一个浏览器的窗口重新进行输入第二组参数化的执行还是使用的是第一组参数画的界面,比如说构造数据的时候会出现当时用到第一组参数化的构造的参数以后,此时还会针对于第二组参数来进行参数化的构造(此时和第一组参数使用的是同一个界面),如果说此是针对于第一组参数用户登陆成功了,直接跳转到列表页了,那么当第二组参数参数构造以后,系统执行以后发现此时页面是在列表页,自然无法定位到输入框和按钮,此时就会出现nosuchelement异常

@SpringBootTest
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class LoginTest  {private static ChromeDriver driver=  CommonDriver.getDriver();// 验证首页元素展示是正确@BeforeAllpublic static void getUrl(){//打开浏览器driver.get("http://127.0.0.1:8080/login.html");driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));}@Test@Order(2)void CheckElementLogin(){//1.检查页面上一些文字的显示,url是否正确String text1=driver.findElement(By.cssSelector("#body > div > h3")).getText();String text2=driver.findElement(By.cssSelector("#body > div > div:nth-child(2) > label")).getText();String text3=driver.findElement(By.cssSelector("#body > div > div:nth-child(3) > label")).getText();String text4=driver.findElement(By.cssSelector("#submit")).getAttribute("value");String url=driver.getCurrentUrl();//2.校验信息元素是否正确,比如说校验文本是否符合预期Assertions.assertEquals(text1,"管理员登录");Assertions.assertEquals(text2,"用户名:");Assertions.assertEquals(text3,"密码:");Assertions.assertEquals(text4,"登录");Assertions.assertEquals(url,"http://127.0.0.1:8080/login.html");}//@ParameterizedTest@Order(1)@MethodSource("loginData")public void login(String username,String password) throws InterruptedException {//这个参数化本身不会新打开一个浏览器的窗口重新进行输入//定位到登陆页面中的输入框核按钮进行登陆操作driver.findElement(By.cssSelector("#loginname")).sendKeys(username);driver.findElement(By.cssSelector("#password")).sendKeys(password);driver.findElement(By.cssSelector("#submit")).click();//第一组参数构造失败以后,登陆失败,手动使用Alert框来将输入框按钮按下Alert alert=driver.switchTo().alert();alert.accept();Thread.sleep(10);}public static Stream<Arguments> loginData(){return Stream.of(Arguments.arguments("zhangsan","admin"));}@AfterAllpublic static void close() throws InterruptedException {driver.close();}
}

1)通过上面进行参数化的校验以后,就可以构造成正确的用户名和错误密码来进行测试,还可以根据更多的测试点进行测试

2)一定要注意driver.getAttribute()是获取到对应的属性值,element的getText方法是用来获取html标签内的文本的值的;

二)针对于列表页+新增用户进行测试:

1)校验添加完成用户成功以后是否成功跳转到了首页,校验一些首页的重要信息比如说一些重要的文本,一些标签属性是否正确,一般来说出现异常的状况就是:跳转到最终的页面以后要么页面无法找到元素(服务器崩了),要么页面中的内容不符合最终的预期(前端出现问题)

2)此时添加了隐式等待以后,点击弹窗按钮以后弹出警告框并且切换到警告框并且出现no such alert报错,本身隐式等待的作用就是需要等待浏览器加载完成以后再来找到对应的元素,selenium本身不可以通过findElement方法来找到警告框对应的前端代码,隐式等待本身不会等待警告框展示和系统弹窗展示,所以会出现代码执行过快警告框仍然没有出现的情况

既然隐式等待在这里面不生效了,那么就使用强制等待,显示等待也不行,显示等待是等待对应的元素出现才查找,必须使用Thread.sleep(100)

3)关闭弹窗以后才可以正确的获取到当前页面的元素,也就是说可以通过获取当前页面元素来进行判断弹窗是否正确的关闭

@TestMethodOrder(MethodOrderer.class)
public class ListTest {public int count=0;private static ChromeDriver driver=CommonDriver.getDriver();//1.检测列表页中的元素信息,校验当前页面中的元素是否符合预期@Test@Order(1)public void TestList() throws InterruptedException {//1.前提是必须用户登录过了,不会打回给前端driver.get("http://127.0.0.1:8080/login.html");driver.findElement(By.cssSelector("#loginname")).sendKeys("zhangsan");driver.findElement(By.cssSelector("#password")).sendKeys("admin");driver.findElement(By.cssSelector("#submit")).click();Thread.sleep(3000);//2.点击登录按钮Alert alert=driver.switchTo().alert();alert.accept();Thread.sleep(3000);//显示等待,防止程序执行速度远远高于代码执行速度而导致页面无法抓取元素//3.校验首页信息是否正确String text1=driver.findElement(By.xpath("/html/body/div/h3")).getText();Assertions.assertEquals(text1,"用户信息列表");String text2=driver.findElement(By.cssSelector("body > div > div:nth-child(2) > form > div:nth-child(2) > label")).getText();Assertions.assertEquals(text2,"籍贯");//4.跳转到新增用户界面,并验证新增界面的一些元素是否正确driver.findElement(By.cssSelector("body > div > div:nth-child(3) > a:nth-child(1)")).click();String text=driver.findElement(By.cssSelector("body > div > h3")).getText();Assertions.assertEquals(text,"添加用户");}//2.进入到新增用户的界面,进行添加信息以后跳转到首页@Order(2)@ParameterizedTest@MethodSource("")public void TestAddUser(User user) throws InterruptedException {//1.填写登陆名字,用户名密码和登陆密码driver.findElement(By.cssSelector("#loginname")).sendKeys(user.getLoginname());driver.findElement(By.cssSelector("#username")).sendKeys(user.getUsername());driver.findElement(By.cssSelector("#password")).sendKeys(user.getPassword());driver.findElement(By.cssSelector("#password2")).sendKeys(user.getPassword());//2.填写对应的按钮的操作if(user.getSex().equals("男")) driver.findElement(By.cssSelector("#man")).click();else driver.findElement(By.cssSelector("#women")).click();//3.下拉框Select select=new Select(driver.findElement(By.cssSelector("#address")));select.selectByVisibleText(user.getAddress());//4.qq邮箱driver.findElement(By.cssSelector("#qq")).sendKeys(user.getQq());driver.findElement(By.cssSelector("#email")).sendKeys(user.getEmail());driver.findElement(By.cssSelector("#age")).sendKeys(""+user.getAge());if(user.getIsadmin()==1) driver.findElement(By.cssSelector("#admin_yes")).click();else  driver.findElement(By.cssSelector("#admin_no")).click();//5.点击按钮driver.findElement(By.cssSelector("#btn_sub")).click();//6.是否继续添加Thread.sleep(4000);Alert alert=driver.switchTo().alert();alert.accept();alert.accept();//首先弹出对话框添加成功,然后弹出对话框是否手动添加,可以通过增加的动态参数的user个数来灵活地进行调配}public static Stream<User> TestAddUser() throws InterruptedException {User user1=new User();user1.setUsername("wangwu");user1.setPassword("wangwu");user1.setLoginname("wangwu");user1.setIsadmin(1);user1.setAddress("北京");user1.setEmail("wangwu");user1.setSex("男");user1.setAge(10);user1.setQq("123");Thread.sleep(3000);User user2=new User();user2.setUsername("lisi");user2.setPassword("lisi");user2.setLoginname("lisi");user2.setIsadmin(1);user2.setAddress("上海");user2.setEmail("lisi");user2.setSex("男");user2.setAge(10);user2.setQq("123");Thread.sleep(3000);return Stream.of(user1,user2);}
}

4)针对于测试的一些重要信息进行截图:

public class GetTimeClass {public static void getScreenShot( ChromeDriver driver,String className){List<String> times=getTime();String fatherPath="./src/test/autotest-"+className+"-"+times.get(0)+"/"+times.get(1)+".png";File sourceFile=driver.getScreenshotAs(OutputType.FILE);FileUtil.copyFile(sourceFile,new File(fatherPath));}public static List<String> getTime(){//文件名格式20220101-214130-毫秒SimpleDateFormat format1=new SimpleDateFormat("yyyyMMdd-HHmmssSS");//文件夹名称格式2022-08-01SimpleDateFormat format2=new SimpleDateFormat("yyyy-MM-dd");String fileName=format1.format(System.currentTimeMillis());String dirName=format2.format(System.currentTimeMillis());List<String> result=new ArrayList<>();result.add(dirName);result.add(fileName);return result;}
}
三)针对于列表页和删除用户进行测试:

删除单个用户

删除多个用户

四)针对于列表页和批量查询用户做测试:
五)针对于列表页和修改用户做测试:

总结:使用selenium4+junit5作为自动化测试针对想试试自动化测试的亮点以及总结:

1)@Suite(),@SelectClasses("createDriver","业务类","destoryDriver"),如果选择@SelectClasses来指定运行的类的时候,那么类的执行顺序是按照我们在@SelectClasses中手动指定类的执行顺序来执行的

2)不是说每一个用例都需要添加屏幕截图操作,需要考察用例本身的复杂程度和问题定位的难度,以及用例的核心程度来进行考察

1)使用注解@Test,@BeforeEach,@BeforeAll,@AfterEach,@AfterAll

1.1)加上这些注解以后就不需要使用创建Main函数作为方法执行的入口了,就不需要通过传统的创建大量对象的方式来调用测试方法了,避免生成大量对象造成空间浪费以及很好的提升了性能;

1.2)测试模块和测试模块之间就可以解耦合,一个测试用例执行失败,不会影响其他用例的执行,防止大量测试用例执行失败而造成测试用例浪费,模块之间也做到了很好的解耦合;

2)通过static修饰静态变量,全局只是创建一次驱动对象,避免重复创建驱动对象造成时间和空间的浪费,防止每一个用例都重新创建Driver和销毁Driver对象

3)支持单参数,多参数,方法参数,动态参数来减少用例的冗余,保证用例的简介,保证可读性

4)通过junit中的测试套件,一次执行所有我们想要运行的自动化测试用例

5)使用隐式等待和强制等待(Alert框,警告框无法定位,可能代码执行速度远远大于警告框弹出的速度,但是隐式等待和显示等待不会等待ALert框弹出以后程序在执行运行),一方面显示等待使用比较麻烦,另一方面隐式等待和显示等待混用会导致程序失效,提升自动化执行的稳定性,降低自动化误报的概率;

6)使用屏幕截图:方便问题的追溯和自动化执行问题的解决

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

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

相关文章

新手必看!!附源码!!STM32通用定时器输出PWM

一、什么是PWM? PWM&#xff08;脉冲宽度调制&#xff09;是一种用于控制电子设备的技术。它通过调整信号的脉冲宽度来控制电压的平均值。PWM常用于调节电机速度、控制LED亮度、产生模拟信号等应用。 二、PWM的原理 PWM的基本原理是通过以一定频率产生的脉冲信号&#xff0…

Python BDD之Behave测试报告

behave 本身的测试报告 behave 本身提供了四种报告格式&#xff1a; pretty&#xff1a;这是默认的报告格式&#xff0c;提供颜色化的文本输出&#xff0c;每个测试步骤的结果都会详细列出。plain&#xff1a;这也是一种文本格式的报告&#xff0c;但没有颜色&#xff0c;并且…

使用Python画一棵树

&#x1f38a;专栏【不单调的代码】 &#x1f354;喜欢的诗句&#xff1a;更喜岷山千里雪 三军过后尽开颜。 &#x1f386;音乐分享【如愿】 &#x1f970;欢迎并且感谢大家指出我的问题 文章目录 &#x1f339;Turtle模块&#x1f384;效果&#x1f33a;代码&#x1f6f8;代码…

【SpringCloud微服务全家桶学习笔记-Hystrix(服务降级,熔断,接近实时的监控,服务限流等)】

服务雪崩 &#xff08;微服务面临的问题&#xff09; 多个微服务之间调用的时候&#xff0c;假设微服务A调用微服务B和微服务C&#xff0c;微服务B和微服务C又调用其它的微服务&#xff0c;这就是所谓的“扇出”。如果扇出的链路上某个微服务的调用响应时间过长或者不可用&…

Redis的持久化(新)

Redis中数据都保存在内存&#xff0c;但是内存中的数据变换很快&#xff0c;也很容易丢失&#xff0c;比如连接断开、宕机停机等等。而Redis提供的数据持久化机制有RDB(Redis DataBase)和AOF(Append Only File)。 1.RDB RDB是指在指定的时间间隔内将内存中的数据集快照写入到磁…

多普勒流速流量计的功能作用

在当今的城市管理中&#xff0c;排水系统的监控和管理一直是难题之一。传统的人工巡检方式不仅效率低下&#xff0c;而且无法做到实时监控和预警。然而&#xff0c;随着科技的进步&#xff0c;多普勒流速流量计的出现为城市排水管理带来了新的解决方案。 多普勒流速流量计是一种…

UI自动化之Playwright简介

&#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;交流讨论&#xff1a;欢迎加入我们一起学习&#xff01;&#x1f4e2;资源分享&#xff1a;耗时200小时精选的「软件测试」资…

UI设计师岗位的基本职责八篇(合集)

UI设计师岗位的基本职责1 职责&#xff1a; 1. 负责公司互联网产品app、web、h5等的用户界面设计工作; 2. 负责运营活动相关的平面及视频设计支持; 3. 负责完成产品相关的界面、图标、动画等的图形界面设计&#xff0c;并参与制定、编写产品视觉设计规范文档; 4. 整理和分…

解决 VSCode 配置远程连接,过程试图写入的管道不存在

解决 VSCode 配置远程连接&#xff0c;过程试图写入的管道不存在

蓝桥杯每日一题2023.11.22

题目描述 题目分析 由题目知其每个品牌积分一定小于315故直接暴力枚举每个品牌如果符合要求直接输出即可 &#xff08;答案&#xff1a;150&#xff09; #include<bits/stdc.h> using namespace std; int main() {for(int i 1; i < 315; i ){for(int j 1; j <…

Vue 定义只读数据 readonly

readonly 让一个响应式数据变为 **深层次的只读数据**。 isReadonly 判断一个数据是不是只读数据。 应用场景&#xff1a;不希望数据被修改时使用。 readonly 深层次只读&#xff1a; <template><h1>reactive数据</h1><p>姓名&#xff1a;{{ info…

redis运维(十二) 位图

一 位图 ① 概念 1、说明&#xff1a;位图还是在操作字符串2、位图玩字符串在内存中存储的二进制3、ASCII字符通过映射转化为二进制4、操作的是字符串value ② ASCII字符铺垫 1、控制ASCII字符 2、ASCII可显示字符 ③ SETBIT 细节&#xff1a; setbit 命令的返回值是之…