詳解Junit4單元測(cè)試框架的應(yīng)用

引言

這篇文章將幫你了解如下內(nèi)容:

單元測(cè)試框架如何在自動(dòng)化測(cè)試中應(yīng)用;

junit4如何上手;

junit4的高級(jí)功能有哪些;

junit4中用例并發(fā)和用例失敗重試的方案;

單元測(cè)試

單元測(cè)試(Unit Testing),是一種軟件測(cè)試方法,通過(guò)這種測(cè)試方法測(cè)試各個(gè)源代碼單元,一個(gè)或者多個(gè)模塊的集合,使用程序來(lái)測(cè)試程序,來(lái)保證它們的可用性。一般來(lái)說(shuō)單元測(cè)試由開(kāi)發(fā)人員自己來(lái)執(zhí)行。單元測(cè)試是由開(kāi)發(fā)人員編寫(xiě)的一段代碼,用于檢查被測(cè)試代碼的一個(gè)小的、明確的功能是否正確。由于近些年來(lái)ui自動(dòng)化測(cè)試和接口測(cè)試的流行,單元測(cè)試也被引入到自動(dòng)化測(cè)試領(lǐng)域,我們通常編寫(xiě)的自動(dòng)化測(cè)試腳本都是基于單元測(cè)試框架。不同的語(yǔ)言有其對(duì)應(yīng)的單元測(cè)試框架。例如:Java的主流單元測(cè)試框架包括:Junit4\TestNG;Python的主流單元測(cè)試框架包括:unittest\pytest等等。

Junit概念

Junit是一個(gè)可編寫(xiě)重復(fù)測(cè)試的簡(jiǎn)單框架,是基于Xunit架構(gòu)的單元測(cè)試框架的實(shí)例。Junit4最大的改進(jìn)是大量使用注解(元數(shù)據(jù)),很多實(shí)際執(zhí)行 過(guò)程都在Junit的后臺(tái)做完了,而且寫(xiě)test case 的類(lèi)不需要繼承TestCase,只需要在所要做test case的方法前加@Test 注解即可。Junit被默認(rèn)的作為Eclipse插件,集成到Eclipse中。

新特性:

(1)、使用junit4.x版本進(jìn)行單元測(cè)試時(shí),不用測(cè)試類(lèi)繼承TestCase父類(lèi)

(2)、junit4.x版本,引用了注解的方式,進(jìn)行單元測(cè)試;

Junit4環(huán)境搭建

Java 工程中add Library


選擇Junit4 點(diǎn)擊Finish按鈕


Junit4的常用注解

junit4.x版本我們常用的注解:

A、@Before 注解:與junit3.x中的setUp()方法功能一樣,在每個(gè)測(cè)試方法之前執(zhí)行;

B、@After 注解:與junit3.x中的tearDown()方法功能一樣,在每個(gè)測(cè)試方法之后執(zhí)行;

C、@BeforeClass 注解:在所有方法執(zhí)行之前執(zhí)行;

D、@AfterClass 注解:在所有方法執(zhí)行之后執(zhí)行;

JUnit4的用例執(zhí)行順序是:@BeforeClass> @Before> @Test1> @After>@Before> @Test2> @After….. @AfterClass

E、@Test(timeout = xxx) 注解:設(shè)置當(dāng)前測(cè)試方法在一定時(shí)間內(nèi)運(yùn)行完,否則返回錯(cuò)誤;

F、@Test(expected =Exception.class) 注解:設(shè)置被測(cè)試的方法是否有異常拋出。拋出異常類(lèi)型為:Exception.class;

G、@Ignore 注解:注釋掉一個(gè)測(cè)試方法或一個(gè)類(lèi),被注釋的方法或類(lèi),不會(huì)被執(zhí)行。

H、@RunWith注解:指定用例的運(yùn)行Runner,是用來(lái)修飾類(lèi)的,而不是用來(lái)修飾函數(shù)的。只要對(duì)一個(gè)類(lèi)指定了 Runner ,那么這個(gè)類(lèi)中的所有函數(shù)都被這個(gè) Runner 來(lái)調(diào)用。

assertThat

JUnit 4.4 結(jié)合 Hamcrest 提供了一個(gè)全新的斷言語(yǔ)法——assertThat。assertThat 使用了Hamcrest 的Matcher 匹配符,用戶(hù)可以使用匹配符規(guī)定的匹配準(zhǔn)則精確的指定一些想設(shè)定滿足的條件,具有很強(qiáng)的易讀性,而且使用起來(lái)更加靈活。使用assertThat 需要導(dǎo)入:

import static org.hamcrest.CoreMatchers.*;

assertThat的主要功能如下

一般匹配符

1、assertThat(testedNumber, allOf( greaterThan(8), lessThan(16) ) );

注釋?zhuān)?allOf匹配符表明如果接下來(lái)的所有條件必須都成立測(cè)試才通過(guò),相當(dāng)于“與”(&&)

2、assertThat(testedNumber, anyOf( greaterThan(16), lessThan(8) ) );

注釋?zhuān)篴nyOf匹配符表明如果接下來(lái)的所有條件只要有一個(gè)成立則測(cè)試通過(guò),相當(dāng)于“或”(||)

3、assertThat(testedNumber, anything() );

注釋?zhuān)篴nything匹配符表明無(wú)論什么條件,永遠(yuǎn)為true

4、assertThat(testedString, is( "developerWorks" ) );

注釋?zhuān)?is匹配符表明如果前面待測(cè)的object等于后面給出的object,則測(cè)試通過(guò)

5、assertThat(testedString, not( "developerWorks" ) );

注釋?zhuān)簄ot匹配符和is匹配符正好相反,表明如果前面待測(cè)的object不等于后面給出的object,則測(cè)試通過(guò)

字符串相關(guān)匹配符

1、assertThat( testedString,containsString( "developerWorks" ) );

注釋?zhuān)篶ontainsString匹配符表明如果測(cè)試的字符串testedString包含子字符串"developerWorks"則測(cè)試通過(guò)

2、assertThat(testedString, endsWith ( "developerWorks" ) );

注釋?zhuān)篹ndsWith匹配符表明如果測(cè)試的字符串testedString以子字符串"developerWorks"結(jié)尾則測(cè)試通過(guò)

3、assertThat(testedString, startsWith ( "developerWorks" ) );

注釋?zhuān)簊tartsWith匹配符表明如果測(cè)試的字符串testedString以子字符串"developerWorks"開(kāi)始則測(cè)試通過(guò)

4、assertThat(testedValue, equalTo( expectedValue ) );

注釋?zhuān)?equalTo匹配符表明如果測(cè)試的testedValue等于expectedValue則測(cè)試通過(guò),equalTo可以測(cè)試數(shù)值之間,字符串之間和對(duì)象之間是否相等,相當(dāng)于Object的equals方法

5、assertThat(testedString, equalToIgnoringCase( "developerWorks" ) );

注釋?zhuān)篹qualToIgnoringCase匹配符表明如果測(cè)試的字符串testedString在忽略大小寫(xiě)的情況下等于"developerWorks"則測(cè)試通過(guò)

6、assertThat(testedString, equalToIgnoringWhiteSpace( "developerWorks" ) );

注釋?zhuān)篹qualToIgnoringWhiteSpace匹配符表明如果測(cè)試的字符串testedString在忽略頭尾的任意個(gè)空格的情況下等于"developerWorks"則測(cè)試通過(guò),注意:字符串中的空格不能被忽略

數(shù)值相關(guān)匹配符

1、assertThat(testedDouble, closeTo( 20.0, 0.5 ) );

注釋?zhuān)篶loseTo匹配符表明如果所測(cè)試的浮點(diǎn)型數(shù)testedDouble在20.0±0.5范圍之內(nèi)則測(cè)試通過(guò)

2、assertThat(testedNumber, greaterThan(16.0) );

注釋?zhuān)篻reaterThan匹配符表明如果所測(cè)試的數(shù)值testedNumber大于16.0則測(cè)試通過(guò)

3、assertThat(testedNumber, lessThan (16.0) );

注釋?zhuān)簂essThan匹配符表明如果所測(cè)試的數(shù)值testedNumber小于16.0則測(cè)試通過(guò)

4、assertThat(testedNumber, greaterThanOrEqualTo (16.0) );

注釋?zhuān)?greaterThanOrEqualTo匹配符表明如果所測(cè)試的數(shù)值testedNumber大于等于16.0則測(cè)試通過(guò)

5、assertThat(testedNumber, lessThanOrEqualTo (16.0) );

注釋?zhuān)簂essThanOrEqualTo匹配符表明如果所測(cè)試的數(shù)值testedNumber小于等于16.0則測(cè)試通過(guò)

collection相關(guān)匹配符

1、assertThat( mapObject,hasEntry( "key", "value" ) );

注釋?zhuān)篽asEntry匹配符表明如果測(cè)試的Map對(duì)象mapObject含有一個(gè)鍵值為"key"對(duì)應(yīng)元素值為"value"的Entry項(xiàng)則測(cè)試通過(guò)

2、assertThat(iterableObject, hasItem ( "element" ) );

注釋?zhuān)篽asItem匹配符表明如果測(cè)試的迭代對(duì)象iterableObject含有元素“element”項(xiàng)則測(cè)試通過(guò)

3、assertThat( mapObject,hasKey ( "key" ) );

注釋?zhuān)?hasKey匹配符表明如果測(cè)試的Map對(duì)象mapObject含有鍵值“key”則測(cè)試通過(guò)

4、assertThat( mapObject,hasValue ( "key" ) );

注釋?zhuān)篽asValue匹配符表明如果測(cè)試的Map對(duì)象mapObject含有元素值“value”則測(cè)試通過(guò)

Junit4應(yīng)用

創(chuàng)建一個(gè)junit4用例

New>選則JUnit Test Case



選擇New Junit4 test,點(diǎn)擊Finish即完成了一個(gè)Junit4 用例的創(chuàng)建工作


實(shí)例代碼

public class Junit4Demo {

?????? @BeforeClass

?????? public static void setUpBeforeClass()throws Exception {

?????? }

?????? @AfterClass

?????? public static void tearDownAfterClass()throws Exception {

?????? }

?????? @Before

?????? public void setUp() throws Exception {

?????? }

?????? @After

?????? public void tearDown() throws Exception {

?????? }

?????? @Test

?????? public void EmptyCollection() {

????????????? Collection collection =newArrayList();

????????????? assertTrue(collection.isEmpty());

????????????? }

?????? @Test

?????? public void MyString() {

????????????? assertEquals("Test",newString("Test"));

????????????? }

?????? @Test

????? public void MyNull() {

????????????? assertEquals(null,"abc");

????????????? }

}

執(zhí)行多個(gè)測(cè)試用例

執(zhí)行多個(gè)測(cè)試用例的意義是將多個(gè)測(cè)試用例通過(guò)suite管理起來(lái)。

New一個(gè)Test Suite,點(diǎn)擊Next


可以自定義需要執(zhí)行的測(cè)試用例


點(diǎn)擊Finish,生成代碼如下:

import org.junit.runner.RunWith;

import org.junit.runners.Suite;

import org.junit.runners.Suite.SuiteClasses;

@RunWith(Suite.class)

@SuiteClasses({Junit4Demo.class, Junit4Demo2.class })

public class AllTests {


}

使用@Rule擴(kuò)展Junit4

Rule是JUnit4中的新特性,它讓我們可以擴(kuò)展JUnit的功能,靈活地改變測(cè)試方法的行為。JUnit4中包含兩個(gè)注解@Rule和@ClassRule用于修飾Field或返回Rule的?Method,Rule是一組實(shí)現(xiàn)了TestRule接口的共享類(lèi),提供了驗(yàn)證、監(jiān)視TestCase和外部資源管理等能力。JUnit提供了以下幾個(gè)Rule實(shí)現(xiàn),必要時(shí)也可以自己實(shí)現(xiàn)Rule。

Verifier: 驗(yàn)證測(cè)試執(zhí)行結(jié)果的正確性。

ErrorCollector: 收集測(cè)試方法中出現(xiàn)的錯(cuò)誤信息,測(cè)試不會(huì)中斷,如果有錯(cuò)誤發(fā)生測(cè)試結(jié)束后會(huì)標(biāo)記失敗。

ExpectedException: 提供靈活的異常驗(yàn)證功能。

Timeout: 用于測(cè)試超時(shí)的Rule。

ExternalResource: 外部資源管理。

TemporaryFolder: 在JUnit的測(cè)試執(zhí)行前后,創(chuàng)建和刪除新的臨時(shí)目錄。

TestWatcher: 監(jiān)視測(cè)試方法生命周期的各個(gè)階段。

TestName: 在測(cè)試方法執(zhí)行過(guò)程中提供獲取測(cè)試名字的能力。

簡(jiǎn)單的說(shuō)就是提供了測(cè)試用例執(zhí)行過(guò)程中一些通用功能的共享的能力,使我們不必重復(fù)編寫(xiě)一些功能類(lèi)似的代碼。JUnit用于標(biāo)注Rule的注解包括@Rule和@ClassRule,區(qū)別在于作用域不同@Rule的作用域是測(cè)試方法,@ClassRule則是測(cè)試Class。

自定義Rule實(shí)例:

自定義一個(gè)rule, 實(shí)現(xiàn)循環(huán)執(zhí)行一個(gè)方法,代碼如下:

import java.util.Arrays;

import org.junit.rules.MethodRule;

import org.junit.runners.model.FrameworkMethod;

import org.junit.runners.model.Statement;


class RepeatableRule implements MethodRule{


?????? int times=1;

?????? String[] testMethods = null;


?????? RepeatableRule(int times, String[]testMethods){

????????????? this.times = times;

????????????? this.testMethods = testMethods;

?????? }


?????? @Override

?????? public Statement apply(final Statementbase, final FrameworkMethod method, Object target) {

?????? ?return new Statement() {

???????? @Override

???????? public void evaluate() throwsThrowable {

??????? ?????? int loopTime = 1;

??????? ?????? if(Arrays.asList(testMethods).contains(method.getName())){

??????? ????????????? loopTime= times;

??????? ?????? }?

??????? ?????? for(int i=0;i<loopTime;i++){

??????????????? base.evaluate();

???????? }

????? };

?????? }

}

調(diào)用自定義的rule

import org.junit.After;

import org.junit.Before;

import org.junit.Rule;

import org.junit.Test;

import org.junit.rules.MethodRule;


public class TestCase {


?????? @Rule

?????? public MethodRule rule = new RepeatableRule(5, new String[]{"test1"});


?????? @Before

?????? public void setUp() throws Exception {

?????? }


?????? @After

?????? public void tearDown() throws Exception {

?????? }


?????? @Test

?????? public void test() {

????????????? System.out.println("test");

?????? }

?????? @Test

?????? public void test1() {

????????????? System.out.println("test1");

?????? }


}

執(zhí)行用例可以看到用例 test1被執(zhí)行了5次。

用例并發(fā)執(zhí)行與出錯(cuò)重試機(jī)制

Junit4并發(fā)不便利往往是其被TestNG用戶(hù)詬病的原因,其實(shí)我們可以使用Maven的maven-surefire-plugin插件解決這個(gè)問(wèn)題,而這一方法也是在持續(xù)集成過(guò)程中運(yùn)行自動(dòng)化測(cè)試用例最常用的解決方案之一。maven-surefire-plugin是一個(gè)用于mvn?生命周期的測(cè)試階段的插件,可以通過(guò)一些參數(shù)設(shè)置方便的在testNG或junit下對(duì)測(cè)試階段進(jìn)行自定義。在實(shí)際工作中我們可以利用該插件指定運(yùn)行的測(cè)試用例,并通過(guò)多線程的方式來(lái)運(yùn)行用例,我們僅僅需要配置參數(shù)<threadCount>即可,例如:<threadCount>3</threadCount>,表示用3個(gè)線程執(zhí)行測(cè)試使用。更為方便的是我們還可以通過(guò)參數(shù)<rerunFailingTestsCount>來(lái)控制重新運(yùn)行失敗的測(cè)試用例的執(zhí)行次數(shù)。例如:<rerunFailingTestsCount>2</rerunFailingTestsCount>,表示用例失敗后將再重新執(zhí)行2次。關(guān)于詳細(xì)使用maven-surefire-plugin插件的方法請(qǐng)參考文章:

詳解maven-surefire-plugin在自動(dòng)化測(cè)試中的應(yīng)用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 簡(jiǎn)介 測(cè)試 在軟件開(kāi)發(fā)中是一個(gè)很重要的方面,良好的測(cè)試可以在很大程度決定一個(gè)應(yīng)用的命運(yùn)。軟件測(cè)試中,主要有3大種類(lèi)...
    Whyn閱讀 5,813評(píng)論 0 2
  • 一、JUnit概述&配置 1、JUnit是什么? JUnit是一個(gè)Java 編程語(yǔ)言的開(kāi)源測(cè)試框架,用于編寫(xiě)和運(yùn)行...
    Tina_Xu閱讀 686評(píng)論 0 1
  • 前言 這次來(lái)介紹下Spring Boot中對(duì)單元測(cè)試的整合使用,本篇會(huì)通過(guò)以下4點(diǎn)來(lái)介紹,基本滿足日常需求 Ser...
    嘟爺MD閱讀 7,093評(píng)論 14 177
  • junit特性 項(xiàng)目多元化,導(dǎo)致最基本的功能有時(shí)難以應(yīng)付。所以,junit自4.x發(fā)布以來(lái),每次新版本的推出都引入...
    juconcurrent閱讀 1,632評(píng)論 0 10
  • 喜歡上了一個(gè)男孩,莫名的,卻也不是毫無(wú)預(yù)兆的。從好感到他知道我的心思,時(shí)間已經(jīng)過(guò)了三年。前天他說(shuō)我們還是朋友,但我...
    用力奔跑閱讀 236評(píng)論 1 1