目錄
一、什么是 JUnit
二、JUnit5 相關(guān)技術(shù)
1.注解
1.1 @Test
1.2 @Disabled
1.3 @BeforeAll、@AfterAll
1.4 @BeforeEach、@AfterEach
2.參數(shù)化
2.1 單參數(shù)
2.2 CSV 獲取參數(shù)
2.3 方法獲取參數(shù)
2.4 多參數(shù)
3.測試用例的執(zhí)行順序
3.1 順序執(zhí)行:@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
3.2 隨機(jī)執(zhí)行:@TestMethodOrder(MethodOrderer.class)
4.斷言
5.測試套件
5.1 通過 class 運(yùn)行測試用例
5.2 通過包運(yùn)行測試用例
??本節(jié)課我們來學(xué)習(xí)單元測試框架?Junit,這里的單元測試指的是對最小的軟件設(shè)計單元(模塊)進(jìn)行驗證,在UI自動化測試?yán)锩妫覀兊膯卧獪y試主要針對UI界面的功能進(jìn)行自動化測試。
一、什么是 JUnit
JUnit是一個Java單元測試框架。它由Kent Beck和Erich Gamma建立,逐漸成為源于Kent Beck的sUnit的xUnit家族中最為成功的一個JUnit有它自己的JUnit擴(kuò)展生態(tài)圈。多數(shù)Java的開發(fā)環(huán)境都已經(jīng)集成了JUnit作為單元測試的工具。
注意:Junit 測試也是程序員測試,即所謂的白盒測試,它需要程序員知道被測試的代碼如何完成功能,以及完成什么樣的功能
它包括以下特性:
- 用于測試期望結(jié)果的斷言(Assertion)
- 用于共享共同測試數(shù)據(jù)的測試工具
- 用于方便的組織和運(yùn)行測試的測試套件
- 圖形和文本的測試運(yùn)行器
使用 Junit 能讓我們快速的完成單元測試。
??通常我們寫完代碼想要測試這段代碼的正確性,那么必須新建一個類,然后創(chuàng)建一個 main() 方法,然后編寫測試代碼。如果需要測試的代碼很多呢?那么要么就會建很多main() 方法來測試,要么將其全部寫在一個 main() 方法里面。這也會大大的增加測試的復(fù)雜度,降低程序員的測試積極性。而 Junit 能很好的解決這個問題,簡化單元測試,寫一點(diǎn)測一點(diǎn),在編寫以后的代碼中如果發(fā)現(xiàn)問題可以較快的追蹤到問題的原因,減小回歸錯誤的糾錯難度。
二、JUnit5 相關(guān)技術(shù)
通常我們使用 JUnit5 版本
1.注解
注解(也可以稱為 元數(shù)據(jù))為在代碼中添加信息提供了一種形式化的方法,使得在代碼中任一時刻可以非常方便的使用這些數(shù)據(jù);注解類型定義了一種新的特殊接口類型,在接口關(guān)鍵期 interface 之前加@符號,即用@interface即可區(qū)分注解與普通接口聲明。目前大部分框架都是通過使用注解簡化代碼提高編碼效率
1.1 @Test
JUnit提供了非常強(qiáng)大的注解功能,通過 @Test 注解修飾到方法上,該方法就變?yōu)榱艘粋€測試方法,執(zhí)行當(dāng)前類時,會自動的執(zhí)行該類下所有帶 @Test?注解的用例
使用這些JUnit提供的注解時,需要在pom.xml文件中進(jìn)行配置(記得配置完要進(jìn)行刷新):maven中央倉庫
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.9.2</version>
<scope>test</scope>
</dependency>
?
<dependencies>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.9.2</version>
</dependency>
</dependencies>
在 main 文件中,我們需要導(dǎo)入 Test 包:
?
我們寫一個測試用例:
import org.junit.jupiter.api.Test;
public class JUnitDemo1 {
@Test
void Test01() {
System.out.println("這是 JunitDemo1 里的 Test01");
}
@Test
void Test02() {
System.out.println("這是 JunitDemo1 里的 Test02");
}
}
??需要注意的是寫的代碼幾個運(yùn)行按鈕:
?
?其中“對號”表示測試通過;“ !”表示測試錯誤
1.2 @Disabled
Disabled 表示 忽略
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class JUnitDemo1 {
@Test
void Test01() {
System.out.println("這是 JunitDemo1 里的 Test01");
}
@Test
void Test02() {
System.out.println("這是 JunitDemo1 里的 Test02");
}
@Disabled
void Test03() {
WebDriver webDriver = new ChromeDriver();
webDriver.get("https://www.baidu.com");
webDriver.findElement(By.cssSelector("#kw")).sendKeys("521");
webDriver.findElement(By.cssSelector("#su")).click();
}
}
?
此時我們看到這個代碼就不執(zhí)行 Test03?
1.3 @BeforeAll、@AfterAll
@BeforeAll:當(dāng)前的方法需要在當(dāng)前類下所有用例執(zhí)行之前執(zhí)行一次,且被該注解修飾的方法必須為靜態(tài)方法
@AfterAll:當(dāng)前的方法需要在當(dāng)前類下所有用例執(zhí)行之后執(zhí)行一次,且被該注解修飾的方法必須為靜態(tài)方法
例如在 UI 自動化中:通常情況下,創(chuàng)建文件、打開網(wǎng)頁放在BeforeAll 里邊;關(guān)閉瀏覽器放在AfterAll 里邊
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class JUnitDemo1 {
@Test
void Test01() {
System.out.println("這是 JunitDemo1 里的 Test01");
}
@Test
void Test02() {
System.out.println("這是 JunitDemo1 里的 Test02");
}
@Disabled
void Test03() {
WebDriver webDriver = new ChromeDriver();
webDriver.get("https://www.baidu.com");
webDriver.findElement(By.cssSelector("#kw")).sendKeys("521");
webDriver.findElement(By.cssSelector("#su")).click();
}
@BeforeAll
static void SetUp() {
System.out.println("這是我們 BeforeAll 里邊的語句");
}
@AfterAll
static void TearDown() {
System.out.println("這是我們 AfterAll 里邊的語句");
}
}
?
1.4 @BeforeEach、@AfterEach
@BeforeEach:當(dāng)前的方法需要在每個用例執(zhí)行之前都執(zhí)行一次
@AfterEach:當(dāng)前的方法需要在每個用例執(zhí)行之后都執(zhí)行一次
import org.junit.jupiter.api.*;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class JUnitDemo1 {
@Test
void Test01() {
System.out.println("這是 JunitDemo1 里的 Test01");
}
@Test
void Test02() {
System.out.println("這是 JunitDemo1 里的 Test02");
}
@Disabled
void Test03() {
WebDriver webDriver = new ChromeDriver();
webDriver.get("https://www.baidu.com");
webDriver.findElement(By.cssSelector("#kw")).sendKeys("521");
webDriver.findElement(By.cssSelector("#su")).click();
}
@BeforeAll
static void SetUp() {
System.out.println("這是我們 BeforeAll 里邊的語句");
}
@AfterAll
static void TearDown() {
System.out.println("這是我們 AfterAll 里邊的語句");
}
@BeforeEach
void BeforeEachTest() {
System.out.println("這是 BeforeEach 里邊的語句");
}
@AfterEach
void AfterEachTest() {
System.out.println("這是 AfterEach 里邊的語句");
}
}
?
2.參數(shù)化
參數(shù)化就是盡可能的通過一個用例,多組參數(shù)來模擬用戶的行為;在使用參數(shù)化注解之前需要先用 @parameterizedTest 聲明該方法為參數(shù)化方法,然后再通過注解提供數(shù)據(jù)來源
使用 @parameterizedTest?需要在 pom.xml 文件中進(jìn)行配置(記得配置完要進(jìn)行刷新):
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-params --> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-params</artifactId> <version>5.9.2</version> </dependency>
??
2.1 單參數(shù)
單參數(shù):@ValueSource(數(shù)據(jù)類型方法={參數(shù)1,參數(shù)2…})
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
public class JUnitDemo2 {
//單參數(shù):@ValueSource(數(shù)據(jù)類型方法={參數(shù)1,參數(shù)2…})
@ParameterizedTest
@ValueSource(ints = {1, 2, 3})
void Test01(int num) {
System.out.println(num);
}
@ParameterizedTest
@ValueSource(strings = {"1", "2", "3"})
void Test02(String number) {
System.out.println(number);
}
}
2.2 CSV 獲取參數(shù)
假設(shè)上述參數(shù)有很多,在注解處手動編寫數(shù)據(jù)源就有些不方便,我們這時就可以借助第三方csv文件來讀取數(shù)據(jù)源
CSV 獲取參數(shù):@CsvFileSource(resources = "____.csv")
這個時候我們需要在 main 文件下 resources 中創(chuàng)建一個 test.csv 文件(.csv 和 參數(shù)必須相同):
張三1,李四1,王五1
張三2,李四2,王五2
代碼編寫:?
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvFileSource;
//參數(shù)化
public class JUnitDemo2 {
@ParameterizedTest
@CsvFileSource(resources = "test.csv")
void Test03(String name) {
System.out.println(name);
}
}
?此時我們就把所有的內(nèi)容都打印出來了;
2.3 方法獲取參數(shù)
@CsvFileSource、@ValueSource 只能傳遞同種類型的參數(shù),那么我們想要傳多種參數(shù),那么可以用方法獲取參數(shù)
方法獲取參數(shù):@MethodSource("Generator")
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import java.util.stream.Stream;
public class JUnitDemo2 {
public static Stream<Arguments> Generator() {
return Stream.of(Arguments.arguments(1, "張三"),
Arguments.arguments(2, "李四"),
Arguments.arguments(3, "王五")
);
}
@ParameterizedTest
@MethodSource("Generator")
void Test04(int num, String name) {
System.out.println(num + ":" + name);
}
}
2.4 多參數(shù)
多參數(shù):@CsvSource({“數(shù)據(jù)組合1”,“數(shù)據(jù)組合2”…}),每個雙引號是一組參數(shù)(測試用例)
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.*;
import java.util.stream.Stream;
public class JUnitDemo2 {
//多參數(shù):@CsvSource({“數(shù)據(jù)組合1”,“數(shù)據(jù)組合2”…})
@ParameterizedTest
@CsvSource({"1, 張三", "2, 李四", "3, 王五"})
void manyTest(int num, String name) {
System.out.println("num:" + num + ", name:" + name);
}
}
3.測試用例的執(zhí)行順序
我們看以下代碼:
此時我們看到打印的依次是 A、B、C?
此時我們看到打印的還是 A、B、C?
所以 測試用例的執(zhí)行順序并不會按照我們編寫代碼的順序來執(zhí)行
3.1 順序執(zhí)行:@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
如果在實際測試中,我們需要完成連貫的多個步驟的測試,是需要規(guī)定測試用例執(zhí)行的順序的,可以通過 @order 注解來實現(xiàn)排序
- 先使用注解說明當(dāng)前類下所有的用例需要使用 @order 注解來進(jìn)行排序(注意:該注解必須要用在類上)
- 然后通過 @order?來指定用例的具體順序
順序執(zhí)行:@TestMethodOrder(MethodOrderer.OrderAnnotation.class),然后再每次執(zhí)行的時候添加 @order(執(zhí)行順序)
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class JUnitDemo1 {
@Order(2)
@Test
void test03() {
System.out.println("C");
}
@Order(3)
@Test
void test01() {
System.out.println("A");
}
@Order(1)
@Test
void test02() {
System.out.println("B");
}
}
這個時候我們通過 @Order 來設(shè)置執(zhí)行順序,按照這個思路,我們得到的結(jié)果為 B -> C -> A
3.2 隨機(jī)執(zhí)行:@TestMethodOrder(MethodOrderer.class)
隨機(jī)執(zhí)行:@TestMethodOrder(MethodOrderer.class),也就是我們看到的一開始的執(zhí)行順序
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
@TestMethodOrder(MethodOrderer.class)
public class JUnitDemo2 {
@Test
void test03() {
System.out.println("C");
}
@Test
void test01() {
System.out.println("A");
}
@Test
void test02() {
System.out.println("B");
}
}
?因此,如果不寫?@TestMethodOrder(MethodOrderer.OrderAnnotation.class) 則是隨即執(zhí)行
4.斷言
檢查測試方法的期望結(jié)果值和真實返回值,通過 Assertions 類實現(xiàn)
- 斷言匹配/不匹配:assertEquals()、assertNotEquals()
- 斷言結(jié)果為真/為假:assertTrue()、assertFalse()
- 斷言結(jié)果為空/非空:assertNull()、assertNotNull()
public class JUnitDemo3 {
@Test
void test01() {
Assertions.assertTrue(1 == 1);
}
@Test
void test02() {
Assertions.assertTrue(2 == 1);
}
}
?在這里我們可以看到 預(yù)期和結(jié)果 是否相同
5.測試套件
當(dāng)我們一個類中有多個測試用例時,我們不可能挨個去運(yùn)行,那樣將會很耗費(fèi)時間,這時我們就需要?測試套件?來指定類或者指定包名來運(yùn)行類下或者包下的所有測試用例。
如果要使用測試套件,首先我們需要先創(chuàng)建一個類,通過 @Suite 注解標(biāo)識該類為測試套件類(而不是測試類)
使用測試套件,需要引入依賴:
<!-- https://mvnrepository.com/artifact/org.junit.platform/junit-platform-suite -->
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-suite</artifactId>
<version>1.9.1</version>
</dependency>
還需要引入依賴(使用 suite 需要引入 引擎engine 依賴):
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-engine -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.9.1</version>
</dependency>
5.1 通過 class 運(yùn)行測試用例
使用 @SelectClasses({指定類, 指定類, 指定類})
JUnitDemo1:
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class JUnitDemo1 {
@Order(2)
@Test
void test03() {
System.out.println("C");
}
@Order(3)
@Test
void test01() {
System.out.println("A");
}
@Order(1)
@Test
void test02() {
System.out.println("B");
}
}
JUnitDemo4:
public class JUnitDemo4 {
public static Stream<Arguments> Generator() {
return Stream.of(Arguments.arguments(1, "張三"),
Arguments.arguments(2, "李四"),
Arguments.arguments(3, "王五")
);
}
@ParameterizedTest
@MethodSource("Generator")
void Test04(int num, String name) {
System.out.println(num + ":" + name);
}
}
RunSuite:
@Suite
@SelectClasses({JUnitDemo4.class, JUnitDemo1.class})
public class RunSuite {
}
此時就是先執(zhí)行 JUnitDemo4,再執(zhí)行?JUnitDemo1
5.2 通過包運(yùn)行測試用例
@SelectPackages(value = {"包1", "包2","..."})
JUnit1 包下 Test1:
public class Test1 {
@Test
void test1() {
System.out.println("JUnit1 package Test1 test1");
}
}
JUnit2 包下 Test2:
public class Test2 {
@Test
void test2() {
System.out.println("JUnit2 package Test2 test2");
}
}
RunSuite2:
@Suite
@SelectPackages(value = {"JUnit1", "JUnit2"})
public class RunSuite2 {
}
此時先執(zhí)行?JUnit1 包下 Test1 ,再執(zhí)行?JUnit2 包下 Test2
文章來源:http://www.zghlxwxcb.cn/news/detail-464109.html
?文章來源地址http://www.zghlxwxcb.cn/news/detail-464109.html
到了這里,關(guān)于自動化測試之JUnit單元測試框架的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!