旅游網(wǎng)站建設(shè)內(nèi)容網(wǎng)站搜索排名優(yōu)化怎么做
目錄
一、認(rèn)識Junit框架
Junit和Selenium的關(guān)系是什么
導(dǎo)入Junit框架+common-io包
二、Junit框架的使用
2.1Junit有哪些常用注解
2.1.1@Test注解
2.1.2BeforeEach
2.1.3@BeforeAll
2.1.4@AfterAll
2.1.5@AfterEach
2.2Junit的斷言
Assertions.assertEquals(期待值,真實(shí)值);
2.2.1Assertions.assertNotEquals("百度一下",text)
2.2.2Assertions.assertTrue(text.equals("百度一下"))
2.2.3Assertions.assertNull(a);
三、用例的執(zhí)行順序
①針對方法的排序
為什么需要用到j(luò)uit的排序功能
四、測試套件(Suit)
@Suite
@SelectClasses({待測試的類.class})
@SelectPackages("包名")
五、參數(shù)化
5.1@ParameterizedTest、@ValueSource(strings = {})
5.2@CsvSource(value={"第一組數(shù)據(jù)","第二組數(shù)據(jù)"})
?如果參數(shù)當(dāng)中包含逗號:",",就需要使用單引號轉(zhuǎn)義字符串
5.3讀取文件參數(shù):@CsvFileSource(resources="/文件名稱")
?5.3.1讀取其他磁盤文件的操作:指定文件為files=...
5.4動態(tài)參數(shù)(單參數(shù)版本)
5.5動態(tài)參數(shù)(多參數(shù)版本)
六、對于重要測試場景的截圖
第一步:定位到需要的頁面
第二步:調(diào)用getSrceenshotAs方法,傳入的擦參數(shù)是OutputTpye.FILE;
第三步:新建一個(gè)File類,指定路徑;
第四步:調(diào)用copyFile方法,把生成的文件放到指定的目錄當(dāng)中
一、認(rèn)識Junit框架
Junit是一個(gè)開源的Java語言的單元測試框架。
回顧一下,單元測試就是在編碼階段,一般情況下,由開發(fā)進(jìn)行的測試。
Junit和Selenium的關(guān)系是什么
? ? ? Junit是單元測試框架,而selenium是web自動化測試框架。如果把selenium比作燈泡,那么junit就是電燈。因此:一般情況下,junit負(fù)責(zé)運(yùn)行selenium腳本編寫的代碼。
導(dǎo)入Junit框架+common-io包
<dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.6</version></dependency><dependency><groupId>org.seleniumhq.selenium</groupId><artifactId>selenium-java</artifactId><version>4.8.1</version></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><version>${junit.version}</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><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-params</artifactId><version>5.8.2</version><scope>test</scope></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-engine</artifactId><version>${junit.version}</version><scope>test</scope></dependency>
二、Junit框架的使用
2.1Junit有哪些常用注解
2.1.1@Test注解
? ? ? ?這一個(gè)注解作用于方法上面,表示這個(gè)方法是一個(gè)測試用例。當(dāng)@Test注解作用在一個(gè)方法上面的時(shí)候,表示這一個(gè)方法是可以直接運(yùn)行的,無需通過main方法來調(diào)用。
2.1.2BeforeEach
在執(zhí)行每一個(gè)被@Test修飾的方法之前,都會執(zhí)行一次@BeforeEach注釋的方法。
@BeforeEachvoid aaa(){System.out.println("pre");}@Testvoid bbb(){System.out.println("bbb");}@Testvoid ccc(){System.out.println("ccc");}
?每執(zhí)行一個(gè)@Test之前,就需要執(zhí)行一次@BeforeEach注釋的方法
運(yùn)行類上面的運(yùn)行按鈕:
2.1.3@BeforeAll
? ? ? ?首先,被@BeforeAll注釋的方法一定是靜態(tài)的。
? ? ? ?其次,不同于@BeforeEach的是,@BeforeAll注釋的方法一定是靜態(tài)的,并且只會在加載外部類的時(shí)候執(zhí)行一次,并不會在每一個(gè)方法執(zhí)行之前再次執(zhí)行了。
public class Test1 {@BeforeAllstatic void aaa(){System.out.println("pre");}@Testvoid bbb(){System.out.println("bbb");}@Testvoid ccc(){System.out.println("ccc");}
}
2.1.4@AfterAll
被這個(gè)注解修飾的方法也必須是靜態(tài)的,在每一個(gè)@Test之后進(jìn)行修飾。
public class Test1 {@BeforeAllstatic void aaa(){System.out.println("pre");}@Testvoid bbb(){System.out.println("bbb");}@Testvoid ccc(){System.out.println("ccc");}@AfterAllstatic void afterAll(){System.out.println("end...");}
}
運(yùn)行結(jié)果:
2.1.5@AfterEach
同理,在每一個(gè)@Test注釋的方法執(zhí)行結(jié)束的末尾,都會執(zhí)行一次@AfterEach注釋的方法。
public class Test1 {@BeforeEachvoid aaa(){System.out.println("pre");}@Testvoid bbb(){System.out.println("bbb");}@Testvoid ccc(){System.out.println("ccc");}@AfterEachvoid afterAll(){System.out.println("end...");}
}
運(yùn)行結(jié)果:
2.2Junit的斷言
寫自動化測試,結(jié)果要么是成功的,要么是失敗的,不存在成功一半的情況。
那么就需要使用到斷言:assert,斷言預(yù)期結(jié)果和真實(shí)結(jié)果是否一致。
Assertions.assertEquals(期待值,真實(shí)值);
當(dāng)期待值和真實(shí)值一致的時(shí)候,這個(gè)斷言才不會拋出異常;
當(dāng)期待值和真實(shí)值不一致的時(shí)候,就會拋出異常;
代碼實(shí)現(xiàn):
public class Test2 {FirefoxDriver driver;@BeforeEachpublic void get(){driver=new FirefoxDriver();//捕捉到這一個(gè)頁面driver.get("https://www.baidu.com");}@Testpublic void testOne(){//嘗試獲取"百度一下"的文本框String text=driver.findElement(By.cssSelector("#su")).getAttribute("value");//使用AssertEquals來進(jìn)行斷言Assertions.assertEquals("百度一下",text);}@AfterEachpublic void after(){driver.quit();}
}
如果運(yùn)行的結(jié)果一致,那么就提示測試用例通過:
2.2.1Assertions.assertNotEquals("百度一下",text)
與Assertions.assertEquals(期待值,真實(shí)值)相反。
只有不一致的時(shí)候,測試用例才會通過。
2.2.2Assertions.assertTrue(text.equals("百度一下"))
傳入的參數(shù)應(yīng)該是一個(gè)返回值為boolean類型的表達(dá)式;
@Test
public void assertTrueTest(){String text=driver.findElement(By.cssSelector("#su")).getAttribute("value");//如果返回true,那么測試用例通過,否則測試用例不通過Assertions.assertTrue(text.equals("百度一下"));}
同理,還有AssertFalse?
2.2.3Assertions.assertNull(a);
@Testpublic void assertNull(){String a=null;Assertions.assertNull(a);}
如果一個(gè)引用為null,那么默認(rèn)測試用例通過。
同理,還有Assertions.assertNotNull(),那么一個(gè)引用不為null的時(shí)候,測試用例才通過。
三、用例的執(zhí)行順序
①針對方法的排序
第一步:在這個(gè)類上面添加注解:@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
第二步:
使用@Order(執(zhí)行順序)作用在方法上面,表示是第幾個(gè)執(zhí)行;
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class Test2 {FirefoxDriver driver;@BeforeEach@Order(1)public void get(){driver=new FirefoxDriver();//捕捉到這一個(gè)頁面driver.get("https://www.baidu.com");}@Test@Order(2)public void testOne(){//嘗試獲取"百度一下"的文本框String text=driver.findElement(By.cssSelector("#su")).getAttribute("value");Assertions.assertNotEquals("百度一下",text);}@Test@Order(3)public void assertTrueTest(){String text=driver.findElement(By.cssSelector("#su")).getAttribute("value");//如果返回true,那么測試用例通過,否則測試用例不通過Assertions.assertTrue(text.equals("百度一下"));}@AfterEachpublic void after(){driver.quit();}
}
為什么需要用到j(luò)uit的排序功能
? ? ? ?如果用例之間存在關(guān)聯(lián)關(guān)系(存在耦合)(但是不是絕對有關(guān)聯(lián)關(guān)系),那么就需要手動指定用例的執(zhí)行順序。因?yàn)楦鱾€(gè)測試用例的執(zhí)行順序是無序的。
? ? ? ?這樣就可以避免出現(xiàn)各個(gè)測試用例之間執(zhí)行順序不正確的情況。
四、測試套件(Suit)
測試套件,用于把所有的測試用例都執(zhí)行起來。
@Suite
這一個(gè)注解作用于類上面,用于執(zhí)行所有的測試用例。
@SelectClasses({待測試的類.class})
這個(gè)注解和上面的注解需要配合使用,這樣才可以一起執(zhí)行待測試類的測試用例。
當(dāng)然也可以傳遞多個(gè).class對象。
@Suite
@SelectClasses({Test1.class,Test2.class})
public class SuitTest {}
運(yùn)行結(jié)果:
@SelectPackages("包名")
掃描這一個(gè)包下面包含了@Test注解的方法的類。
@Suite
@SelectPackages("TestFile")
public class SuitTest {}
但是掃描的包不可以和當(dāng)前的類在同一個(gè)包下面;
需要注意的是,這種情況下面,被掃描的類一定是xxxTest這樣命名的,否則是掃描不到的。
五、參數(shù)化
對于一個(gè)測試用例,可能會測試傳入的參數(shù)是多種的情況;
例如對于一個(gè)文本框進(jìn)行測試,可以測試多種輸入的情況:
如下圖:如果為每一個(gè)輸入的name都定義一個(gè)方法,那么就顯得非常冗余,于是就引入了參數(shù)化。
5.1@ParameterizedTest、@ValueSource(strings = {})
第一個(gè)注解@Parameterized作用在方法上面,用來表示這個(gè)方法支持傳入多個(gè)參數(shù);
第二個(gè)注解@ValueSource用于指定傳入?yún)?shù)的類型;例如:strings={}就表示傳入的是一個(gè)string類型的數(shù)組;
ints={2,3,4,5}表示傳入的參數(shù)是一個(gè)int類型的數(shù)組;
但是,同一個(gè)@ValueSource注解當(dāng)中只支持一種數(shù)據(jù)類型。
運(yùn)行結(jié)果:
5.2@CsvSource(value={"第一組數(shù)據(jù)","第二組數(shù)據(jù)"})
其中,每一組數(shù)據(jù)當(dāng)中對應(yīng)方法傳入的參數(shù)的值。采用","來分割。?
@ParameterizedTest@CsvSource(value = {"小明,20","小紅,30","小李,40"})public void printStringAndInteger(String name,int age){System.out.println("name:"+name+";age="+age);}
當(dāng)然,一組數(shù)據(jù)當(dāng)中的分隔符也不一定采用系統(tǒng)默認(rèn)的","分割,也可以采用自定義的分隔符。
@ParameterizedTest@CsvSource(value = {"小明-20","小紅-20","小李-40"},delimiter = '-')public void printStringAndAge(String name,int age){System.out.println("name:"+name+";age="+age);}
用戶自定義的分隔符:?
?如果參數(shù)當(dāng)中包含逗號:",",就需要使用單引號轉(zhuǎn)義字符串
5.3讀取文件參數(shù):@CsvFileSource(resources="/文件名稱")
第一步:在resources目錄下面新建一個(gè)文件,并且指定名稱;
第二步:在文件當(dāng)中以逗號的方式分割每一組參數(shù);
然后運(yùn)行程序:
?5.3.1讀取其他磁盤文件的操作:指定文件為files=...
@ParameterizedTest@CsvFileSource(files = "E:\\OJSystem\\src\\main\\resources\\my.csv")public void printStringAndAge3(String name,int age){System.out.println("name:"+name+";age="+age);}
5.4動態(tài)參數(shù)(單參數(shù)版本)
第一步:定義提供數(shù)據(jù)的方法,必須聲明為靜態(tài);返回值為一個(gè)Stream對象;方法內(nèi)部調(diào)用Stream.of(參數(shù)列表);
第二步:定義dyNatickTest(String x)方法獲取參數(shù);并用@MethodSource()指定
第三步:輸出參數(shù)。
@ParameterizedTest@MethodSource("methodDemo")void dyNatickTest(String x){System.out.println(x);}static Stream<String> methodDemo(){return Stream.of("張三","李四","王五");}
如果@MethodSource當(dāng)中不指定參數(shù)的名稱,那么就會調(diào)用跟測試用例同名的靜態(tài)方法
5.5動態(tài)參數(shù)(多參數(shù)版本)
第一步:新建一個(gè)測試方法,并且指定多個(gè)參數(shù)。使用@ParameterizedTest和@MethodSource注解同時(shí)作用
第二步:新建一個(gè)和測試用例同名的靜態(tài)方法;
第三步:在靜態(tài)方法當(dāng)中調(diào)用Stream.of()方法,并且傳入的參數(shù)為多個(gè)Arguments.arguments(第一步創(chuàng)建方法的參數(shù)列表)
?代碼實(shí)現(xiàn):
@ParameterizedTest@MethodSourcevoid paramsTest(String name,int age){System.out.println("name:"+name+";age :"+age);}/*** 多參數(shù)的版本* Stream對象@return*/static Stream<Arguments> paramsTest(){return Stream.of(Arguments.arguments("lucy",29),Arguments.arguments("lili",30),Arguments.arguments("lisi",40));}
六、對于重要測試場景的截圖
第一步:定位到需要的頁面
第二步:調(diào)用getSrceenshotAs方法,傳入的擦參數(shù)是OutputTpye.FILE;
第三步:新建一個(gè)File類,指定路徑;
第四步:調(diào)用copyFile方法,把生成的文件放到指定的目錄當(dāng)中
@Testpublic void screenShortTest() throws IOException, InterruptedException {//百度搜索關(guān)鍵字driver.findElement(By.cssSelector("#kw")).sendKeys("selenium");driver.findElement(By.cssSelector("#su")).click();//屏幕截圖,把截圖的文件存放到指定的位置//以文件的形式存儲File srcFile=driver.getScreenshotAs(OutputType.FILE);//把截圖的文件存放到指定的目錄下面File destFile=new File("E:/OJSystem/src/test/Files/img.png");Thread.sleep(1000);FileUtils.copyFile(srcFile,destFile);}