亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費(fèi)注冊(cè) 查看新帖 |

Chinaunix

  平臺(tái) 論壇 博客 文庫(kù)
最近訪問(wèn)板塊 發(fā)新帖
查看: 1991 | 回復(fù): 0
打印 上一主題 下一主題

JUnit8個(gè)不常被用到的功能 [復(fù)制鏈接]

論壇徽章:
1
IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-06-10 06:20:00
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報(bào)告]
發(fā)表于 2016-06-07 11:54 |只看該作者 |倒序?yàn)g覽


JUnit對(duì)Java開(kāi)發(fā)者來(lái)說(shuō)一個(gè)在普遍使用的單元測(cè)試框架。但是,大多數(shù)使用者僅僅使用了它的一部分功能。本文介紹其中不常被用到的8個(gè)功能。比如臨時(shí)目錄創(chuàng)建及自動(dòng)清理,測(cè)試失敗時(shí)所有斷言的執(zhí)行,失控測(cè)試的強(qiáng)制停止等。

@Rule是JUnit4的新特性。利用@Rule注解我們可以擴(kuò)展JUnit的功能,在執(zhí)行case的時(shí)候加入測(cè)試者特有的操作,而不影響原有的case代碼:減小了特有操作和case原邏輯的耦合。譬如說(shuō)我們要重復(fù)測(cè)試某個(gè)test方法時(shí),當(dāng)然我們可以在@Test方法里面寫(xiě)循環(huán)。但是如果想把循環(huán)和測(cè)試邏輯分開(kāi)就可以利用@Rule。

@Rule只能注解在字段中,該字段必須是public的并且類(lèi)型必須實(shí)現(xiàn)了TestRule接口或MethodRule接口。JUnit 4.9還導(dǎo)入了@ClassRule注解。相對(duì)于@Rule注解來(lái)說(shuō),@ClassRule是一個(gè)類(lèi)級(jí)別的注解。就像@Before與@BeforeClass的區(qū)別。下面介紹JUnit中8個(gè)不常用到但很有用的功能。

通過(guò)@Rule注解可以生成臨時(shí)文件或臨時(shí)文件夾

有時(shí)候程序運(yùn)行時(shí)必須生成文件或文件夾,往往需要寫(xiě)代碼。JUnit4.7以后的版本中引入了TemporaryFolder。測(cè)試可以創(chuàng)建文件與目錄并在測(cè)試運(yùn)行結(jié)束后將其刪除。這對(duì)于那些與文件系統(tǒng)打交道而且獨(dú)立運(yùn)行的測(cè)試來(lái)說(shuō)很有用。這個(gè)功能使測(cè)試中文件夾的生成和管理變的非常簡(jiǎn)單。只要確保生成的文件夾或文件是名字不與既有的重復(fù)就行。并且,無(wú)論測(cè)試成功與否,任何在測(cè)試過(guò)程中添加到臨時(shí)目錄的文件或目錄都會(huì)在測(cè)試結(jié)束時(shí)刪除。

下面的例子中,JUnit生成的臨時(shí)目錄中生成一個(gè)sample.txt的文件,并且寫(xiě)入「JUnit Rocks!」。然后,讀取新生成文件的第一行并進(jìn)行比較。為使代碼簡(jiǎn)化,例子中文件處理使用了Apache Commons IO。

public class TemporaryFolderTests {
@Rule
public TemporaryFolder tempFolder = new  TemporaryFolder();
@Test
public void  fileCreatedAndWrittenSuccessfully() throws IOException {
     File file = tempFolder.newFile("sample.txt");
    FileUtils.writeStringToFile(file,  "JUnit Rocks!");
    String line =  FileUtils.readFileToString(file);
    assertThat(line, is("JUnit  Rocks!"));
}
}
測(cè)試完后(無(wú)論測(cè)試成功與否)文件和目錄會(huì)被刪除。


取得當(dāng)前的測(cè)試方法名稱(chēng)


想要取得執(zhí)行中的測(cè)試方法名的時(shí)候,通過(guò)@Rule注解TestName類(lèi)的實(shí)例化對(duì)象可以取得。
public class TestNameTests {
@Rule
public TestName name = new TestName();
@Test
public void methodNameShouldBePrinted() {
    System.out.println("Test method name:" +  name.getMethodName());
}
}
通過(guò)getMethodName()方法可以得到當(dāng)前測(cè)試方法名稱(chēng)。


上面例子的執(zhí)行結(jié)果是:
Test method name: methodNameShouldBePrinted


在一個(gè)運(yùn)行測(cè)試方法過(guò)程中收集多個(gè)錯(cuò)誤信息


使用ErrorCollector類(lèi),可以在一個(gè)測(cè)試方法中收集多個(gè)測(cè)試錯(cuò)誤。也就是說(shuō),一個(gè)測(cè)試方法執(zhí)行中,不會(huì)在第一個(gè)確認(rèn)出錯(cuò)后就停止執(zhí)行。使用ErrorCollector可以在所有點(diǎn)確認(rèn)完后統(tǒng)一報(bào)出。


下在例子中有三個(gè)點(diǎn)要確認(rèn),它們都用ErrorCollector來(lái)確認(rèn)。
public class ErrorCollectorTests {
@Rule
public ErrorCollector collector = new  ErrorCollector();
@Test
public void statementsCollectedSuccessfully()  {
    String s = null;
    collector.checkThat ("Value should not be null", null,  is(s));
    s = "";
    collector.checkThat( "Value should have the length of 1",  s.length(), is(1));
    s = "Junit!";
    collector.checkThat( "Value should have the length of 10",  s.length(), is(10));
}
}
第一個(gè)點(diǎn)確認(rèn)成功,后面兩個(gè)點(diǎn)都失敗的時(shí)候會(huì)報(bào)下面這樣的錯(cuò)。
java.lang.AssertionError:Value should  have the length of 1
Expected: is <1>
but: was <0>
at  org.hamcrest.MatcherAssert...
java.lang.AssertionError:Value should  have the length of 10
Expected: is <10>
but: was <6>
at  org.hamcrest.MatcherAssert...


一個(gè)測(cè)試方法用不同的參數(shù)來(lái)反復(fù)執(zhí)行


用不同的參數(shù)來(lái)測(cè)試一個(gè)方法是否正確是一個(gè)比較普遍的需求。JUnit4.0以后的版本中,通過(guò)@Parameters注解可以不重復(fù)寫(xiě)測(cè)試方法就能實(shí)現(xiàn)這一需求。


使用@Parameters注解時(shí)不能使用默認(rèn)Runner來(lái)運(yùn)行測(cè)試代碼,必須使用Parameterized.class測(cè)試類(lèi)。


通過(guò)下面的例子來(lái)說(shuō)明一下。
@RunWith(Parameterized.class)
public class FibonacciNumbersTests {
@Parameterized.Parameters
public  static List data() {
    return Arrays.asList(new Object[][]{
     {0, 0}, {1, 1}, {2, 1},
     {3, 2}, {4, 3}, {5, 5},
     {6, 8}});
}
private  int value;
private  int expected;
public  FibonacciNumbersTests( int input, int expected) {
     value = input;
     this.expected = expected;
}
@Test
public  void fibonacciNumberCalc () {
     assertEquals(expected, fib(value));
}
public  static int fib(int n) {
     if (n < 2) {
         return n;
     } else {
         return fib(n - 1) + fib(n - 2);
     }
}
}
第一行指定@RunWith注解,JUnit用專(zhuān)門(mén)的Runner類(lèi)來(lái)運(yùn)行測(cè)試代碼。


List的各項(xiàng)目中第一個(gè)是input參數(shù),第二個(gè)是expected參數(shù)。測(cè)試方法通@Parameterized.Parameters注解,把List的各個(gè)項(xiàng)目做為測(cè)試類(lèi)的構(gòu)造函數(shù)的參數(shù)。


設(shè)定執(zhí)行最長(zhǎng)時(shí)間


通過(guò)@Test注解中的timeout屬性可以使執(zhí)行時(shí)間過(guò)長(zhǎng)的測(cè)試方法強(qiáng)制結(jié)束掉,同時(shí)測(cè)試結(jié)果也表示為測(cè)試失敗。timeout屬性中設(shè)定的時(shí)間是毫秒單位的。并且可以設(shè)定整個(gè)類(lèi)的執(zhí)行最長(zhǎng)時(shí)間。下面例子中設(shè)定了5秒最長(zhǎng)執(zhí)行時(shí)間。
public class LongRunningTests {
@Rule
public  Timeout globalTimeout = Timeout.seconds(5);
@Test
public  void whatWeDoInATestMethodEchoesInEternity() {
      while(true);
}
}
執(zhí)行結(jié)果如下:
org.junit.runners.model.TestTimedOutException:
test  timed out after 5 seconds
at  tr.com.t2.labs.tdd.sample5.LongRunningTests…


用@Category把測(cè)試分組


JUnit 4.8以后的版本中,加入了分組測(cè)試的功能。下面例6的兩個(gè)測(cè)試方法中thisTestRunsSlowly()加上了@Category注解。
public class CategorizedTests {
@Test
@Category(SlowTests.class)
public  void thisTestRunsSlowly() {
     System.out.println("Slow test  running");
}

@Test
public  void thisTestRunsFast() {
     System.out.println("Fast test  running");
}
}

SlowTests.class的定義是下面這樣的。
public interface SlowTests {
}

在例7中用Categories.class的Runner來(lái)運(yùn)行分組后的測(cè)試代碼。指定類(lèi)的Runner沒(méi)有設(shè)定的話@Category注解是無(wú)效的。用@IncludeCategory注解來(lái)指定要執(zhí)行的接口。這樣只有指定的分組才會(huì)被執(zhí)行到。
@RunWith(Categories.class)
@Categories.IncludeCategory(SlowTests.class)
@Suite.SuiteClasses(CategorizedTests.class)
public class SlowTestsTestSuite {
}


自定義測(cè)試規(guī)則


通過(guò)實(shí)現(xiàn)TestRule接口可以簡(jiǎn)單的實(shí)現(xiàn)自定義測(cè)試規(guī)則。TestRule中只定義了apply()方法。在實(shí)現(xiàn)apply()方法時(shí)返回一個(gè)Statement類(lèi)型的返回值。Statement類(lèi)是定義了evaluate()方法的抽象類(lèi)。具體參照以下例子。
public class MyCustomRule implements TestRule  {
private  String label;
public  MyCustomRule(String label) {
    this.label = label;
}
@Override
public  Statement apply(final Statement base, Description description){
    return new Statement() {
       @Override
       public  void evaluate() throws Throwable {
           System.out.println(label + "  before");
           base.evaluate();
           System.out.println(label + "  after");
       }
     };
   }
}

下面例9中引入了例8的自定義規(guī)則。
public class CustomRuleTests {
@Rule
public  MyCustomRule myCustomRule = new MyCustomRule("custom");
@Test
public  void myAwesomeMethodInvokedSuccessfully() {
     System.out.println("Test worked  OK");
}
}
執(zhí)行結(jié)果如下。
custom before
Test worked OK
custom after


使用RuleChain


RuleChain提供一種將多個(gè)TestRule串在一起執(zhí)行的機(jī)制。這在JUnit 4.10以后的版本中可以使用。需要根據(jù)特定順序執(zhí)行多個(gè)處理的時(shí)候,用RuleChain可以提高效率。


下面例10是在例9上寫(xiě)的一個(gè)例子。
public class RuleChainTests {
@Rule
public  RuleChain chain = RuleChain.outerRule(
new MyCustomRule("outer")).around(new  MyCustomRule("inner")
);
@Test
public  void ruleChainWorkedOK() {
     System.out.println("Test worked  OK");
}
}
執(zhí)行如下:
outer before
inner before
Test worked OK
inner after
outer after

以上內(nèi)容是一位資深的碼農(nóng)大哥寫(xiě)的,不知道大家看了理解的怎樣?可以在評(píng)論區(qū)發(fā)布想法交流哦。

優(yōu)云軟件的碼農(nóng)都是能文能武!來(lái)認(rèn)識(shí)下作者

作者自我評(píng)價(jià):鮑震淵是一名工作10多年的老碼農(nóng)。2016年前專(zhuān)注于CRM系統(tǒng)的設(shè)計(jì)與開(kāi)發(fā)。

秉承devops的理念,從監(jiān)控、到應(yīng)用體驗(yàn),到自動(dòng)化持續(xù)交付,優(yōu)云軟件一切為了您做的更好!
將IT運(yùn)維化繁為簡(jiǎn),請(qǐng)?jiān)L問(wèn)優(yōu)云官網(wǎng):


您需要登錄后才可以回帖 登錄 | 注冊(cè)

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號(hào)-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號(hào):11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報(bào)專(zhuān)區(qū)
中國(guó)互聯(lián)網(wǎng)協(xié)會(huì)會(huì)員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過(guò)ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請(qǐng)注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP