1. 程式人生 > >單元測試之Junit功能介紹

單元測試之Junit功能介紹

一.註解
與JUnit3不同,JUnit4通過註解的方式來識別測試方法。目前支援的主要註解有:
@BeforeClass 全域性只會執行一次,而且是第一個執行
@Before 在測試方法執行之前執行
@Test 測試方法
@After 在測試方法執行之後允許
@AfterClass 全域性只會執行一次,而且是最後一個執行
@Ignore 忽略此方法
二.Assert
Junit3和Junit4都提供了一個Assert類(雖然package不同,但是大致差不多)。Assert類中定義了很多靜態方法來進行斷言。列表如下:
assertTrue(String message, boolean condition) 要求condition == true
assertFalse(String message, boolean condition) 要求condition == false
fail(String message) 必然失敗,同樣要求程式碼不可達
assertEquals(String message, XXX expected,XXX actual) 要求expected.equals(actual)
assertArrayEquals(String message, XXX[] expecteds,XXX [] actuals) 要求expected.equalsArray(actual)
assertNotNull(String message, Object object) 要求object!=null
assertNull(String message, Object object) 要求object==null
assertSame(String message, Object expected, Object actual) 要求expected == actual
assertNotSame(String message, Object unexpected,Object actual) 要求expected != actual
assertThat(String reason, T actual, Matcher matcher) 要求matcher.matches(actual) == true
三.Rule

JUnit4中包含兩個註解@Rule和@ClassRule用於修飾Field或返回Rule的 Method,Rule是一組實現了TestRule介面的共享類,提供了驗證、監視TestCase和外部資源管理等能力。JUnit提供了以下幾個Rule實現,必要時也可以自己實現Rule。
Verifier: 驗證測試執行結果的正確性。
ErrorCollector: 收集測試方法中出現的錯誤資訊,測試不會中斷,如果有錯誤發生測試結束後會標記失敗。
ExpectedException: 提供靈活的異常驗證功能。
Timeout: 用於測試超時的Rule。
ExternalResource: 外部資源管理。
TemporaryFolder
: 在JUnit的測試執行前後,建立和刪除新的臨時目錄。
TestWatcher: 監視測試方法生命週期的各個階段。
TestName: 在測試方法執行過程中提供獲取測試名字的能力。
簡單的說就是提供了測試用例執行過程中一些通用功能的共享的能力,使我們不必重複編寫一些功能類似的程式碼。JUnit用於標註Rule的註解包括@Rule和@ClassRule,區別在於作用域不同@Rule的作用域是測試方法,@ClassRule則是測試Class。
四.Assume
Assume直譯為假設,是JUnit提供的一套用於判斷測試用例的入參是否有業務含義的工具,如果入參不符合預期時會丟擲AssumptionViolatedException,預設的BlockJUnit4ClassRunner及其子類會捕獲這個異常並跳過當前測試,如果使用自定義的Runner則無法保證行為,視Runner的實現而定。 
Assume提供的驗證方法包括: assumeTrue/assumeFalse、 assumeNotNull、 assumeThat、 assumeNoException 。具體含義都比較簡單。假設我們有一個列印姓名和年齡的測試用例,使用Theories提供多套引數測試,由於實際年齡不存在負數所以使用Assume排除不合理的資料:
@RunWith(Theories.class)
public class AssumeTest
{
 
    @DataPoints
    public static String[] names = {"LiLei", "HanMeiMei"};
     
    @DataPoints
    public static int[] ages = {10, -2, 12};
     
    @Theory
    public void printAge(String name, int age)
    {
        Assume.assumeTrue(age > 0);
        System.out.println(String.format("%s's Name is %s.", name, age));
    }
}
列印結果中排除了負數的年齡,並且JUnit測試通過:
LiLei's Name is 10.
LiLei's Name is 12.
HanMeiMei's Name is 10.
HanMeiMei's Name is 12.
五.其他註解功能
[email protected]
Runner
:Runner是一個抽象類,是JUnit的核心組成部分。用於執行測試和通知Notifier執行的結果。JUnit使用@RunWith註解標註選用的Runner,由此實現不同測試行為。 
BlockJUnit4ClassRunner:這個是JUnit的預設Runner,平時我們編寫的JUnit不新增@RunWith註解時使用的都是這個Runner。 
Suit:沒錯,Suit就是個Runner!用來執行分佈在多個類中的測試用例,比如我存在SimpleFunctionTest和ComplexFunctionTest類分別測試Person的簡單和複雜行為,在茫茫的測試用例中如何一次執行所有與Person有關的測試呢——使用Suit。程式碼如下:其中ComplexFunctionTest和SimpleFunctionTest就是兩個普通的測試用例類,這裡忽略。
@RunWith(Suite.class)
@SuiteClasses({ComplexFunctionTest.class, SimpleFunctionTest.class})
public class TestSuitMain
{
 
}
在執行TestSuitMain --> “Run As JUnit Test"的時候會把ComplexFunctionTest和SimpleFunctionTest的用例全部執行一遍。
Parameterized:Parameterized繼承自Suit,從這個身世和名字應該可以猜到一些因果了。Parameterized是在引數上實現了Suit——修飾一個測試類,但是可以提供多組建構函式的引數用於測試不同場景。略微有點抽象,用程式碼說話:
@RunWith(Parameterized.class)
public class TestGenerateParams
{
     
    private String greeting;
     
    public TestGenerateParams(String greeting)
    {
        super();
        this.greeting = greeting;
    }
 
    @Test
    public void testParams()
    {
        System.out.println(greeting);
    }
     
    /**
     * 這裡的返回至少是二維陣列
     * @return
     */
    @Parameters
    public static List<String[]> getParams()
    {
        return
                Arrays.asList(new String[][]{{"hello"}, 
                        {"hi"}, 
                        {"good morning"},
                        {"how are you"}});
    }
}
輸出結果:
hello
hi
good morning
how are you
在這個用例裡,我們首先需要用@RunWith(Parameterized.class)來修飾我們的測試類;接下來提供一組引數,還記得JUnit的生命週期嗎?在每次執行測試方法的時候都會呼叫Constructor來建立一個例項,這裡引數就是通過Constructor的引數傳入的。因此如你所見我們需要一個含有引數的建構函式用於接收引數,這個引數需要用於跑測試用例所以把它儲存做類的變數;然後用@Parameters修飾我們提供引數的靜態方法,它需要返回List<Object[]>,List包含的是引數組,Object[]即按順序提供的一組引數。
Category:Category同樣繼承自Suit,Category似乎是Suit的加強版,它和Suit一樣提供了將若干測試用例類組織成一組的能力,除此以外它可以對各個測試用例進行分組,使你有機會只選擇需要的部分用例。舉個例子Person有獲取age和name的方法也有talk和walk方法,前者用於獲取屬性後者是Person的行為,Category使我們可以只執行屬性測試,反之亦然。
首先修改最初的測試用例PersonTest,新增Category資訊,程式碼如下在每個用例上添加了@Category資訊標識它們是用作Attribute還是Behavior的測試,這不會影響原有用例測執行。
@Category(AttributeFun.class)
@Test
public void testGetAge()
{
    int age = person.getAge();
    assertEquals(3, age);
}
 
@Category(AttributeFun.class)
@Test
public void testGetName()
{
    String name = person.getName();
    assertEquals("Willard", name);
}
 
@Category(BehaviorFun.class)
@Test
public void testTalk()
{
    String message = person.talkTo("Jimy");
    assertNotNull(message);
}
 
@Category(BehaviorFun.class)
@Test(timeout=200)
public void testWalk()
{
    person.walk();
}
接下來編寫我們的Category測試類,程式碼如下:
@RunWith(Categories.class)
@SuiteClasses(PersonTest.class)
public class CategoryTest
{
 
}
Runner選用Categories,SuitClass使用PersonTest.class,這時Categories與Suit擁有完全一致的效果。
Theories:意為原理或者推測的意思,我覺得這裡應該是取推測。Theories繼承自BlockJUnit4ClassRunner,提供了除Parameterized之外的另一種引數測試解決方案——似乎更強大。Theories不再需要使用帶有引數的Constructor而是接受有參的測試方法,修飾的註解也從@Test變成了@Theory,而引數的提供則變成了使用@DataPoint或者@Datapoints來修飾的變數,兩者的唯一不同是前者代表一個數據後者代表一組資料。Theories會嘗試所有型別匹配的引數作為測試方法的入參(有點排列組合的意思)。看一個使用Theories的例子:
@RunWith(Theories.class)
public class TheoriesTest
{
 
    @DataPoint
    public static String nameValue1 = "Tony";
     
    @DataPoint
    public static String nameValue2 = "Jim";
     
    @DataPoint
    public static int ageValue1 = 10;
     
    @DataPoint
    public static int ageValue2 = 20;
     
    @Theory
    public void testMethod(String name, int age)
    {
        System.out.println(String.format("%s's age is %s", name, age));
    }
}
上面的例子列印結果如下:
Tony's age is 10
Tony's age is 20
Jim's age is 10
Jim's age is 20
同樣使用@DataPoints可以獲得一樣的效果:
@RunWith(Theories.class)
public class TheoriesTest
{
 
    @DataPoints
    public static String[] names = {"Tony", "Jim"};
     
    @DataPoints
    public static int[] ageValue1 = {10, 20};
     
    @Theory
    public void testMethod(String name, int age)
    {
        System.out.println(String.format("%s's age is %s", name, age));
    }
}
注:執行順序
1. 獲取元資料資訊的順序
@BeforeClass -> @AfterClass -> ClassRule -> @Test(拿元資料裡的expect Exception) -> @Test(拿元資料裡的timeout資訊) -> @Before -> @After -> @Rule,
2. 註解所標註的方法執行順序
@ClassRule(TestRule.apply()) -> @BeforeClass -> @Rule(TestRule.apply())  -> @Before -> @Test(test method1) ->@After -> if existed @Rule, then Statement.evaluate() -> @Rule(TestRule.apply()) -> @Before -> @Test(test method2) -> @After -> if existed @Rule, then Statement.evaluate() … -> @AfterClass -> if existed @ClassRule, then Statement.evaluate()
通過Statement.evaluate()執行他們的方法實體,最終執行測試方法的主體。

參考文章
1.JUnit框架功能詳細介紹
JUnit框架功能詳細(Rule、Assume、Assert)
2.JUnit4註解基本介紹
3.Junit總體介紹
4.Junit4 Runner以及test case執行順序和原始碼理解

相關推薦

單元測試Junit功能介紹

一.註解 與JUnit3不同,JUnit4通過註解的方式來識別測試方法。目前支援的主要註解有: @BeforeClass 全域性只會執行一次,而且是第一個執行 @Before 在測試方法執行之前執行 @Test 測試方法 @After 在測試方法執行之後允許 @AfterC

Java單元測試JUnit

JUnit4通過註解的方式來識別測試方法。目前主要註解有: @BeforeClass 全域性只會執行一次,而且是第一個執行,且必須為static void @Before 在測試方法執行之前執行,即初

java單元測試junit實戰

1 編寫該文章的起因 博主是一枚小新,經常挖坑填坑。最近在工作中遇到了這樣一種情況。某天小夥伴說博主寫得一個方法有問題,並且相應的測試類也跑不通。博主一直秉著磨刀不誤砍柴工的思想,測試類都是寫得好好地並且能槓槓執行的!懷著好奇,經過一番debug,發現某句程式

Android 單元測試JUnit

在記錄單元測試有關的筆記前,先談談為什麼寫單元測試 看完這篇文章,相比對單元測試有了一定了解。那麼單元測試如何開始呢 一.建立測試類 在任意需要測試的類(或者方法)下面按下Ctrl+Shift+T(這是預設熱鍵)如下圖** 首次建立一個新的測試類

Java單元測試JUnit 5快速上手

前言 單元測試是軟體開發中必不可少的一環,但是在平常開發中往往因為專案週期緊,工作量大而被選擇忽略,這樣往往導致軟體問題層出不窮。線上出現的不少問題其實在有單元測試的情況下就可以及時發現和處理,因此培養自己在日常開發中寫單元測試的能力是很有必要的。無論是對自己的編碼能力的提高,還是專案質量的提升,都是大有好處

談談單元測試(三):測試工具 JUnit 4

前言 上一篇文章《測試工具 JUnit 3》簡單的討論了 JUnit 3 的使用以及內部的方法。這篇文章將會在 JUnit 3 的基礎上,討論一下 JUnit 4 的新特性。同時,與 JUnit 3 做一個簡單的對比。那麼,廢話就不多說了,直

談談單元測試(二):測試工具 JUnit 3

前言 上一篇文章《 為什麼要進行煩人的單元測試?》討論了一下現階段軟體開發中,程式設計師們測試情況的現狀。這篇文章中,我打算介紹一下單元測試的工具(外掛),並且推薦大家以後在開發中,真正的用上單元測試,用好單元測試。

比較完整的junit單元測試-----mock模擬測試

為什麼需要模擬?    在我們一開始學程式設計時,我們所寫的物件通常都是獨立的。hello world之類的類並不依賴其他的類(System.out除外),也不會操作別的類。但實際上軟體中是充滿依賴關係的。我們會基於service類寫操作類,而service類又是基於資料訪問類(DAOs)的,依

單元測試Stub和Mock

下載 我們 並且 試用 sample 註入 mes oge new 單元測試之Stub和Mock FROM:http://www.cnblogs.com/TankXiao/archive/2012/03/06/2366073.html 在做單元測試的時候,我們會發現我

python + unittest 做單元測試學習筆記

stl unittest 例子 gin pre log script 有關 assert 單元測試在保證開發效率、可維護性和軟件質量等方面有很重要的地位,所謂的單元測試,就是對一個類,一個模塊或者一個函數進行正確性檢測的一種測試方式。 這裏主要是就應用 python + u

性能測試-7.Controller功能介紹

ica 前端 gravity 用戶 initial nts 還需要 linu 隊列 Controller功能介紹 設計場景 配置場景 場景監控 一、設計場景 二、配置場景 規劃場景(場景名、調度方式、運行方式、Initialize方式、Start Vusers方式、D

單元測試重要性

表單 曾經 mybatis 服務 request 第一個 完成 分離 能說 單元測試的重要性不言而喻,自我開發生涯以來,從很少註釋過過場場,到非常重視。 單元測試為什麽會讓人忽視呢? 通常情況像一些查詢或者增刪改之類,拿我來說,即便報錯我大概一掃,我就知道錯誤是什麽了,該如

python筆記24-unittest單元測試mock.patch

rom Coding int self. 錯誤 測試用例 方法 org auto 前言 上一篇python筆記23-unittest單元測試之mock對mock已經有初步的認識, 本篇繼續介紹mock裏面另一種實現方式,patch裝飾器的使用,patch() 作為函數裝飾器

補習系列-springboot 單元測試

try 精彩 一次 run rest spec ner hat ltm 目錄 目標 一、About 單元測試 二、About Junit 三、SpringBoot-單元測試 項目依賴 測試樣例 四、Mock測試 五、最後 目標 了解 單元測試的背景 了解如何 利用

單元測試Mock(Moq)

inter 商品 void 簡單 calc 不用 準備 targe ted Mock翻譯為“嘲弄”,其實就是偽造一個對象用於測試。在單元測試中,被測試方法依賴於其他對象時,為了測試簡單一般“偽造”一個這個對象;這樣做的目的: 不用考慮依賴對象的復雜性(方便準備測試數據)

java單元測試如何實現非同步介面的測試案例

測試是軟體釋出的重要環節,單元測試在實際開發中是一種常用的測試方法,java單元測試主要用junit,最新是junit5,本人開發一般用junit4。因為單元測試能夠在軟體模組組合之前儘快發現問題,所以實際開發中投入產出比很高。實際使用難免會遇到非同步操作的介面測試,最常用的情景是別人家的SD

Java單元測試JUnit

**********************單元測試和JUnit******************************** 為什麼要使用單元測試 1.底層程式碼沒問題,上一層才不會出現問題.. 就像蓋樓一樣 2.提高士氣,明確知道我的東西是沒問題的, 保證你不被開 3.加大測試的力度可以降低後期

前端單元測試Jest

概述 關於前端單元測試的好處自不必說,基礎的介紹和知識可以參考之前的部落格連結:React Native單元測試。在軟體的測試領域,測試主要分為:單元測試、整合測試和功能測試。 單元測試:在計算機程式設計中,單元測試(英語:Unit Testing)又稱為模組測試, 是針對程式模組(軟體設計的最小單

Java單元測試工具JUnit 5新特性一覽

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

python自動化測試python基本介紹、條件判斷\迴圈、

  1、python基本介紹 python語言簡單,語法簡潔,易上手。python可以做很多事情,做自動化測試、做運維、做資料分析、做web開發、做人工智慧等等,用途很廣泛。 目前官方發文稱python2的版本到2020年就不再維護,建議大家學習python3. python是一門解釋性語言