1. 程式人生 > >單元測試(二)

單元測試(二)

features 連接 相關 ext add 才會 ofo itself 源碼

前言:junit 介紹。轉載請註明出處:https://www.cnblogs.com/yuxiaole/p/9405519.html

二、 java單測工具

junit4介紹

Java用的最多的單測框架,使用非常簡單,主流IDE基本都集成了JUnit,具體用法看看官方文檔http://junit.org/junit4/

常用註解

  @Before:初始化方法,在任何一個測試方法執行之前,必須執行的代碼。對比 JUnit 3 ,和 setUp()方法具有相同的功能。在該註解的方法中,可以進行一些準備工作,比如初始化對象,打開網絡連接等。

  @After:釋放資源,在任何一個測試方法執行之後,需要進行的收尾工作。對比 JUnit 3 ,和 tearDown()方法具有相同的功能。

  @Test:測試方法,表明這是一個測試方法。在 JUnit 中將會自動被執行。對與方法的聲明也有如下要求:名字可以隨便取,沒有任何限制,但是返回值必須為 void ,而且不能有任何參數。如果違反這些規定,會在運行時拋出一個異常。不過,為了培養一個好的編程習慣,我們一般在測試的方法名上加 test ,比如:testAdd()。同時,該 Annotation(@Test) 還可以測試期望異常和超時時間,如 @Test(timeout=100),我們給測試函數設定一個執行時間,超過這個時間(100毫秒),他們就會被系統強行終止,並且系統還會向你匯報該函數結束的原因是因為超時,這樣你就可以發現這些 bug 了。而且,它還可以測試期望的異常,例如,我們剛剛的那個空指針異常就可以這樣:@Test(expected=NullPointerException.class)。

   @Ignore:忽略的測試方法,標註的含義就是“某些方法尚未完成,咱不參與此次測試”;這樣的話測試結果就會提示你有幾個測試被忽略,而不是失敗。一旦你完成了相應的函數,只需要把 @Ignore 註解刪除即可,就可以進行正常測試了。當然,這個 @Ignore 註解對於像我這樣有“強迫癥”的人還是大有意義的。每當看到紅色條(測試失敗)的時候就會全身不舒服,感覺無法忍受(除非要測試的目的就是讓它失敗)。當然,對代碼也是一樣,無法忍受那些雜亂不堪的代碼。

  @BeforeClass:針對所有測試,也就是整個測試類中,在所有測試方法執行前,都會先執行由它註解的方法,而且只執行一次。當然,需要註意的是,修飾符必須是 public static void xxxx ;此 Annotation 是 JUnit 4 新增的功能。

  @AfterClass:針對所有測試,也就是整個測試類中,在所有測試方法都執行完之後,才會執行由它註解的方法,而且只執行一次。當然,需要註意的是,修飾符也必須是 public static void xxxx ;此 Annotation 也是 JUnit 4 新增的功能,與 @BeforeClass 是一對。

執行順序

  在 JUnit 4 中,單元測試用例的執行順序為:

  @BeforeClass、@Before、@Test、@After、@AfterClass

assertThat 是什麽?

  建議直接看官方文檔吧,https://github.com/junit-team/junit4/wiki/Matchers-and-assertthat

  在org.junit.Assert中除了常用的相等、布爾、非空等斷言,還有一種assertThat,需要配合org.hamcrest.Matcher使用,這種斷言的語法為:

  assertThat([reason, ]T actual, Matcher<? super T> matcher),其中,reason為斷言失敗時的輸出信息,actual為斷言的值或對象,matcher為斷言的匹配器,裏面的邏輯決定了給定的actual對象滿不滿足斷言。

  在org.hamcrest.CoreMatchers類中組織了所有JUnit內置的Matcher,調用其任意一個方法都會創建一個與方法名字相關的Matcher。

  我認為assertThat+Matcher是為了代碼的可讀性更好,也支持用戶自定義斷言。

org.hamcrest.Matcher接口的源碼

/** 
 * A matcher over acceptable values. 
 * A matcher is able to describe itself to give feedback when it fails. 
 * <p/> 
 * Matcher implementations should <b>NOT directly implement this interface</b>. 
 * Instead, <b>extend</b> the {@link BaseMatcher} abstract class, 
 * which will ensure that the Matcher API can grow to support 
 * new features and remain compatible with all Matcher implementations. 
 * <p/> 
 * For easy access to common Matcher implementations, use the static factory 
 * methods in {@link CoreMatchers}. 
 * <p/> 
 * N.B. Well designed matchers should be immutable. 
 *  
 * @see CoreMatchers 
 * @see BaseMatcher 
 */  
public interface Matcher<T> extends SelfDescribing {  
  
    boolean matches(Object item);  
      
    void describeMismatch(Object item, Description mismatchDescription);  
  
    @Deprecated  
    void _dont_implement_Matcher___instead_extend_BaseMatcher_();  
}

  註釋中有提到自定義Matcher不應該直接實現這個接口,而應該繼承org.hamcrest.BaseMatcher抽象類

Runner

  JUnit的Runner是指繼承了org.junit.runner.Runner的類,是用來真正執行單測方法的類,JUnit有提供默認的Runner,如org.junit.runners.JUnit4,也可以通過@RunWith註解來指定自定義的Runner,如@RunWith(SpringRunner.class)

  參考:https://blog.csdn.net/baiyun8789/article/details/72876597

  Runner的介紹還可以參考這篇文章: https://www.mscharhag.com/java/understanding-junits-runner-architecture

Rule

  JUnit自帶了一些方便使用的Rule實現,可以參考下面的文檔 https://github.com/junit-team/junit4/wiki/Rules

Examples  

import static org.hamcrest.CoreMatchers.allOf;
import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.both;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.everyItem;
import static org.hamcrest.CoreMatchers.hasItems;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.sameInstance;
import static org.hamcrest.CoreMatchers.startsWith;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

import java.util.Arrays;

import org.hamcrest.core.CombinableMatcher;
import org.junit.Test;

public class AssertTests {
  @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);
  }

  // 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())));
  }

  @Test
  public void testAssertTrue() {
    assertTrue("failure - should be true", true);
  }
}

單元測試(二)