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

  引入
  在 build.gradle 文件中
  dependencies {
  testCompile 'junit:junit:4.12'
  }
  這其中會引入兩個jar:junit-4.12.jar 和 hamcrest-core-1.3.jar
  介紹
  junit 中兩個重要的類 Assume 和 Assert, 以及其他一些重要的注解:BeforeClass,AfterClass,After,Before 及 Test,Ignore。
  其中,BeforeClass 和 AfterClass 在每個類加載的開始和結(jié)束時運(yùn)行,需要設(shè)置 static 方法;而 Before和After 則是在每個測試方法的開始之前和結(jié)束之后運(yùn)行。
  在 hamcrest-core 的 jar 包中,在 org.hamcrest.core 包中提供了一系列操作運(yùn)算封裝,使測試代碼更加地易讀。如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);
}
  以上代碼來自官方介紹的 Demo , 列舉的是常用而又基礎(chǔ)的操作,但遇到復(fù)雜的集合判斷操作,力不從心了,不過 Junit 提供了另一更為強(qiáng)大的 assertThat 方法,首先來看看它的使用:
// 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 用了兩種方法:一個是 JunitMatchers ,另一個是 hamcrest matchers 的 assertThat,不過后者提供的功能相當(dāng)強(qiáng)大,前者的方法已經(jīng)標(biāo)為廢棄了。
  另外,官方也提及了其它第三方提供的 Matchers 實(shí)現(xiàn):
  Excel spreadsheet matchers
  JSON matchers
  XML/XPath matchers
  所以再次我們只看后者,可以看出來的是其方法的后一個參數(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 類的方法 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());
  }
  }
  可以看出真正地判斷方法是通過 Matcher 類的 matches 方法,若是不滿足的話,則返回 AssertionError。所以真正的核心是 Matcher,而關(guān)于它的實(shí)現(xiàn)都在 hamcrest-core-1.3 包中,看看其實(shí)現(xiàn)的類結(jié)構(gòu)圖:

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

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