您的位置:軟件測(cè)試 > 開(kāi)源軟件測(cè)試 > 開(kāi)源單元測(cè)試工具 > junit
Junit使用及其原理分析
作者:alighters 發(fā)布時(shí)間:[ 2016/9/13 10:53:28 ] 推薦標(biāo)簽:單元測(cè)試 Junit

  引入
  在 build.gradle 文件中
  dependencies {
  testCompile 'junit:junit:4.12'
  }
  這其中會(huì)引入兩個(gè)jar:junit-4.12.jar 和 hamcrest-core-1.3.jar
  介紹
  junit 中兩個(gè)重要的類(lèi) Assume 和 Assert, 以及其他一些重要的注解:BeforeClass,AfterClass,After,Before 及 Test,Ignore。
  其中,BeforeClass 和 AfterClass 在每個(gè)類(lèi)加載的開(kāi)始和結(jié)束時(shí)運(yùn)行,需要設(shè)置 static 方法;而 Before和After 則是在每個(gè)測(cè)試方法的開(kāi)始之前和結(jié)束之后運(yùn)行。
  在 hamcrest-core 的 jar 包中,在 org.hamcrest.core 包中提供了一系列操作運(yùn)算封裝,使測(cè)試代碼更加地易讀。如is,not,allOf,anyOf等。
  代碼示例
@Test
public void testAssertArrayEquals() {
byte[] expected = "trial".getBytes();
byte[] actual = "trial".getBytes();
assertArrayEquals("failure - byte arrays not same", expected, actual);
}
@Test
public void testAssertEquals() {
assertEquals("failure - strings are not equal", "text", "text");
}
@Test
public void testAssertFalse() {
assertFalse("failure - should be false", false);
}
@Test
public void testAssertNotNull() {
assertNotNull("should not be null", new Object());
}
@Test
public void testAssertNotSame() {
assertNotSame("should not be same Object", new Object(), new Object());
}
@Test
public void testAssertNull() {
assertNull("should be null", null);
}
@Test
public void testAssertSame() {
Integer aNumber = Integer.valueOf(768);
assertSame("should be same", aNumber, aNumber);
}
@Test
public void testAssertTrue() {
assertTrue("failure - should be true", true);
}
  以上代碼來(lái)自官方介紹的 Demo , 列舉的是常用而又基礎(chǔ)的操作,但遇到復(fù)雜的集合判斷操作,力不從心了,不過(guò) Junit 提供了另一更為強(qiáng)大的 assertThat 方法,首先來(lái)看看它的使用:
// JUnit Matchers assertThat
@Test
public void testAssertThatBothContainsString() {
assertThat("albumen", both(containsString("a")).and(containsString("b")));
}
@Test
public void testAssertThatHasItems() {
assertThat(Arrays.asList("one", "two", "three"), hasItems("one", "three"));
}
@Test
public void testAssertThatEveryItemContainsString() {
assertThat(Arrays.asList(new String[] { "fun", "ban", "net" }), everyItem(containsString("n")));
}
// Core Hamcrest Matchers with assertThat
@Test
public void testAssertThatHamcrestCoreMatchers() {
assertThat("good", allOf(equalTo("good"), startsWith("good")));
assertThat("good", not(allOf(equalTo("bad"), equalTo("good"))));
assertThat("good", anyOf(equalTo("bad"), equalTo("good")));
assertThat(7, not(CombinableMatcher.<Integer>either(equalTo(3)).or(equalTo(4))));
assertThat(new Object(), not(sameInstance(new Object())));
}
  這里的 assertThat 用了兩種方法:一個(gè)是 JunitMatchers ,另一個(gè)是 hamcrest matchers 的 assertThat,不過(guò)后者提供的功能相當(dāng)強(qiáng)大,前者的方法已經(jīng)標(biāo)為廢棄了。
  另外,官方也提及了其它第三方提供的 Matchers 實(shí)現(xiàn):
  Excel spreadsheet matchers
  JSON matchers
  XML/XPath matchers
  所以再次我們只看后者,可以看出來(lái)的是其方法的后一個(gè)參數(shù)非常靈活,緊接著我們看看其怎么實(shí)現(xiàn)的?
  assertThat 方法實(shí)現(xiàn)
  public static <T> void assertThat(T actual, Matcher<? super T> matcher) {
  assertThat("", actual, matcher);
  }
  public static <T> void assertThat(String reason, T actual,
  Matcher<? super T> matcher) {
  MatcherAssert.assertThat(reason, actual, matcher);
  }
  再定位到 MatcherAssert 類(lèi)的方法 assertThat:
  public static <T> void assertThat(String reason, T actual, Matcher<? super T> matcher) {
  if (!matcher.matches(actual)) {
  Description description = new StringDescription();
  description.appendText(reason)
  .appendText(" Expected: ")
  .appendDescriptionOf(matcher)
  .appendText("      but: ");
  matcher.describeMismatch(actual, description);
  throw new AssertionError(description.toString());
  }
  }
  可以看出真正地判斷方法是通過(guò) Matcher 類(lèi)的 matches 方法,若是不滿足的話,則返回 AssertionError。所以真正的核心是 Matcher,而關(guān)于它的實(shí)現(xiàn)都在 hamcrest-core-1.3 包中,看看其實(shí)現(xiàn)的類(lèi)結(jié)構(gòu)圖:

  看一下其的實(shí)現(xiàn),可發(fā)現(xiàn)上文提到的 is , anyof 等等靜態(tài)方法都是返回一個(gè)相應(yīng)的 Matcher,這樣通過(guò)一個(gè)簡(jiǎn)單的抽象,在這里提供了極大的靈活性。若是感覺(jué)它提供的這些不滿足的話,也可自己進(jìn)行來(lái)進(jìn)行重寫(xiě),按自己的需求來(lái)定制實(shí)現(xiàn)。
  Rule 介紹
  同樣地,當(dāng)我們?cè)絹?lái)越多需要進(jìn)行單元測(cè)試時(shí),需要使用 Rule 來(lái)幫忙了。其主要目的是針對(duì)一個(gè)測(cè)試類(lèi)中的每個(gè)單元測(cè)試方法進(jìn)行統(tǒng)一添加一些行為。代碼則使用 @Rule 注解的形式來(lái)添加至類(lèi)的屬性上。
  在 Junit 框架中,其相對(duì)應(yīng)的接口是 TestRule,而主要的實(shí)現(xiàn)有:
  ErrorCollector: 將大量的錯(cuò)誤收集起來(lái)
  ExpectedException: 對(duì)拋出的錯(cuò)誤做斷言
  ExternalResource: 可對(duì)測(cè)試方法的開(kāi)始和結(jié)束添加回調(diào)
  TemporaryFolder: 用來(lái)創(chuàng)建文件,并在測(cè)試結(jié)束時(shí)自動(dòng)刪除
  TestName: 用來(lái)獲取測(cè)試所執(zhí)行的方法名稱(chēng)
  TestWatcher: 可在測(cè)試方法的執(zhí)行期間添加邏輯
  Timeout: 超過(guò)固定的時(shí)間讓測(cè)試結(jié)束
  Verifier: 當(dāng)狀態(tài)不正確時(shí),可讓測(cè)試結(jié)束
  它們的更多使用方法,可參照官網(wǎng)的 Rules 介紹。
  實(shí)現(xiàn)原理分析
  Junit4 中的測(cè)試代碼可被執(zhí)行,是因?yàn)槠湔嬲娜肟谑敲麨?JUnitCore。它作為 Junit 的 Facade (門(mén)面)模式,來(lái)對(duì)外進(jìn)行交互。另外,其有一個(gè)靜態(tài)的 main 方法:
  public static void main(String... args) {
  Result result = new JUnitCore().runMain(new RealSystem(), args);
  System.exit(result.wasSuccessful() ? 0 : 1);
  }
  所以,當(dāng)我們執(zhí)行單元測(cè)試的時(shí)候,其實(shí)也是運(yùn)行了一個(gè)新的進(jìn)程應(yīng)用程序,其入口在這里。我們執(zhí)行分析的時(shí)候,也從這里開(kāi)始:

上一頁(yè)12下一頁(yè)
軟件測(cè)試工具 | 聯(lián)系我們 | 投訴建議 | 誠(chéng)聘英才 | 申請(qǐng)使用列表 | 網(wǎng)站地圖
滬ICP備07036474 2003-2017 版權(quán)所有 上海澤眾軟件科技有限公司 Shanghai ZeZhong Software Co.,Ltd