Junit 是一个面向 Java 语言的单元测试框架,在 Java 开发过程中的单元测试阶段起着非常重要的作用。同时,在 Web 自动化测试阶段,Junit 是一个非常趁手的测试工具,为 selenium 的使用注入灵魂
在之前写的自动化测试代码中,调用测试用例使用的是非常原始的 main 函数调用,需要实例化对象,调用类的方法。除了书写带来的不便之外,还存在着其他问题,比如调用的其中一个测试用例失败了,就会导致抛出异常,剩下的测试用例没有办法执行到。
那么面对这样的问题,Junit 采用更加简便的高效的注解的方式进行测试用例代码的调用。除了代码调用,这些注解在其他方面使用过程中也发挥着重要的作用。
使用 Junit ,就需要将相关的依赖进行注入操作,放到 pom.xml 中的 标签中,同时selenium 相关依赖也需要注入,注入完成后记得刷新
org.seleniumhq.selenium
selenium-java
4.0.0
org.junit.jupiter
junit-jupiter
5.8.2
test
org.junit.platform
junit-platform-suite
1.8.2
test
org.junit.platform
junit-platform-reporting
1.8.2
test
注解一:@Test
正如前面所说的那样,@Test 注解的作用就是使得测试用例能够被调用
private ChromeDriver driver = new ChromeDriver();
@Test
public void demoTest() {
driver.get("https://www.baidu.com/");
driver.findElement(By.id("kw")).sendKeys("狗狗");
driver.findElement(By.id("su")).click();
driver.quit();
}
添加完 @Test 注解后,可以明显看见 demoTest 这个方法名高亮了,并且左侧有绿色小三角形,表示该测试用例可以通过点击绿色小三件形进行调用起来
执行完毕后,可以在下方的结果区看见测试用例的执行状况。里面包含着用例的执行成功与否,成功几个,失败几个,失败的话失败原因是什么等等
同时在多个测试用例需要被执行时,我们只需要点击类名旁边的绿色小三角形就能执行到所有被启动注解标注过的用例,一个用例的失败并不会影响到其他的用例
BeforeEach 显而易见,它的意思就是在每个之前。该注解的作用就是使得被注解的方法在每个需要被执行的测试用例前都执行一遍
通常来说,被 @BeforeEach 标注的方法就不需要再使用 @Test 注解标注了,否则该用例执行前又会执行一遍该用例
@BeforeEach
public void demoTest1() {
System.out.println("before");
}
@Test
public void demoTest2() {
System.out.println("用例一");
}
@Test
public void demoTest3() {
System.out.println("用例二");
}
同理,@AfterEach 注解的作用自然就是使得被其标注的方法在每个测试用例之后都执行一遍
通过上面的例子,我们可以猜测的到,这两个注解的作用,一个是在所有测试用例执行前执行一遍,另一个是在所有测试用例执行后执行一遍
需要格外注意的是,被这两个注解标注的方法需要被 static 修饰
@BeforeAll
public static void demoTest1() {
System.out.println("before");
}
@Test
public void demoTest2() {
System.out.println("用例一");
}
@Test
public void demoTest3() {
System.out.println("用例二");
}
自动化的测试中, 对于每个的用例来说,一个用例的执行结果中, 必然会有期望结果与实际结果, 从而来判断该用例是通过还是失败。
Junit 提供了Assertions接口,其中有大量的实用方法来检查预期值与实际值, 来验证用例的结果。一般来说, 检查条件大体分为等价性, 逻辑比较以及其他。 如果给定的断言通过, 测试会继续执行到下一行的代码, 如果断言失败, 对应的用例测试会立即停止或者生成错误信息( 一般打印错误信息即可) ,但是不要影响其他的用例执行
在下面的案例中使用到的断言就是 Assertions.assertEquals(期望值,实际结果) 。如果期望值和实际结果相同,就没问题;反之如果不相同,就表示出了错误,在结果区会打印相关的错误日志
private ChromeDriver driver = new ChromeDriver();
@Test
public void demoTest() {
driver.get("https://www.baidu.com/");
String title = driver.getTitle();
Assertions.assertEquals("百度一下,你就知道",title);
driver.quit();
}
断言用法简单且在实际应用过程中发挥着重要的作用,除了上面的断言方法外
Assertions.assertNotEquals(,); //俩参数不同则没问题
Assertions.assertTrue(); //括号内表达式为真则没问题
Assertions.assertFalse(); //括号内表达式为假则没问题
Assertions.assertNull(); //括号内为null则没问题
Assertions.assertNotNull(); //括号内不为null则没问题
//......
在有多个用例需要被执行的时候,有必要时需要去规定用例的执行顺序。因为官方并没有规定顺序,既不是按照用例书写顺序,也不是按照字典序。
public class AutoTest2 {
@Test
public void WTest() {
System.out.println("WWW");
}
@Test
public void DTest2() {
System.out.println("DDD");
}
@Test
public void MTest3() {
System.out.println("MMM");
}
}
如果用例之间存在联系,为了避免这样的联系导致用例执行的失败,我们将就需要进行排序操作
使用到的注解有两个
注解一:@TestMethodOrder
表示需要按照方法进行排序(Junit 中有多种排序方法)
注解二:@Order
使用该注解标注需要进行排序的用例,括号内填写用例执行顺序
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class AutoTest2 {
@Test
@Order(1)
public void WTest() {
System.out.println("WWW");
}
@Test
@Order(2)
public void DTest2() {
System.out.println("DDD");
}
@Test
@Order(3)
public void MTest3() {
System.out.println("MMM");
}
}
参数化是用例编写过程中非常常见的,比如在百度搜索框中输入文本,然后点击“百度一下"按钮,这样简单的操作,如果没有进行参数化,那么就会导致输入的文本的不同而写大量的类似代码,非常的不方便
我们可以将输入的文本进行参数化,从而减少代码冗余
注解一:@ParameterizedTest
标注方法类型为参数化,有了该注解就不需要添加 @Test 之类的启动注解了
注解二:@ValueSource(类型 = {“”,“”})
这里的类型是需要在原生类型的基础上添加s的,比如 strings,ints,doubles,floats,booleans,chars…使用花括号包裹住所有的单参数
private ChromeDriver driver = new ChromeDriver();
@BeforeEach
public void startTest() {
driver.get("https://www.baidu.com/");
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
}
@ParameterizedTest
@ValueSource(strings = {"狗狗","猫猫","兔兔"})
public void demoTest(String content) throws InterruptedException {
driver.findElement(By.id("kw")).sendKeys(content);
driver.findElement(By.id("su")).click();
}
@AfterEach
public void endTest() {
driver.quit();
}
注解三:@CsvSource(value = {“”,“”,“”})
在双引号中的参数默认情况下使用逗号进行分割。
如果某参数中包含逗号,那么就需要使用单引号将参数进行包裹。
如果需要使用其他的符号分割,需要通过delimiterString属性进行说明
PS:数字类型的参数是不能为空的,字符串类型参数为空表示为 null
@ParameterizedTest
@CsvSource(value = {"'李,雷'-15","韩梅梅-18","李明-13"},delimiterString = "-")
public void demoTest(String str,int num) {
System.out.println("str:"+str+" num:"+num);
}
在参数非常多的情况下,全部写在代码中会显得非常的乱,我们可以选择写到csv文件中,从文件中获取参数内容
注解四:@CsvFileSource(resources = “路径”)
表示从 csv 文件中获取信息,如果括号内是resources 表示从 resources 文件夹下面获取文件。如果括号内是files表示可以从任意路径下面获取文件
@ParameterizedTest
@CsvFileSource(resources = "/data1.csv")
//@CsvFileSource(files = "F:\\Work\\Test\\Selenium\\SeleniumPractice\\data2.csv")
public void demoTest1(String str,int num) {
System.out.println("str:"+str+" num:"+num);
}
除了上面提到的获取数据方法外,还可以从其他的方法中获取数据
注解五:@MethodSource
表示从方法中获取参数内容,如果没有说明就是从同名的静态方法中获取。如果不同名的话需要在注解后面的括号中进行说明
@ParameterizedTest
@MethodSource
public void demoTest2(String str) {
System.out.println("str:"+str);
}
//单参数
public static Stream demoTest2() {
return Stream.of("一帆风顺","四喜临门","八面玲珑");
}
@ParameterizedTest
@MethodSource("dataFunc")
public void demoTest3(String str,int num) {
System.out.println("str:"+str+" num:"+num);
}
//多参数
public static Stream dataFunc() {
return Stream.of(Arguments.arguments("七上",7),
Arguments.arguments("八下",8));
}
如果想要一起执行多个类或者包中的用例就需要试用版到测试套件
注解一:@Suite
表示这是一个测试套件
注解二:@SelectClasses(value = {,})
表示将指定的类下面的被执行注标注的用例进行执行
@Suite
@SelectClasses(value = {AutoOneTest.class,AutoTest1.class})
public class RunSuite {
}
注解三:@SelectPackages(“包路径”)
表示将指定的包底下的符合标准的类下的用例进行执行,标准指的是以 Test(s) 开头或结尾的类名
@Suite
@SelectPackages("com.Case.JunitTest")
public class RunSuite {
}
最后我这里给你们分享一下我所积累和真理的文档和学习资料有需要是领取就可以了
以上内容,对于软件测试的朋友来说应该是最全面最完整的备战仓库了,为了更好地整理每个模块,我也参考了很多网上的优质博文和项目,力求不漏掉每一个知识点,很多朋友靠着这些内容进行复习,拿到了BATJ等大厂的offer,这个仓库也已经帮助了很多的软件测试的学习者,希望也能帮助到你。
关注下方我的微信公众号免费领取!↓ ↓ ↓ ↓ ↓