1. gzyueqian
      13352868059

      JUnit框架的使用和Android單元測試-粵嵌教育

      更新時間: 2018-08-22 11:15:11來源: 粵嵌教育瀏覽量:4197

          現在再網上有許多關于單元測試的問題,這里小編就不去說了。小編寫單元測試的理由很簡單粗暴,就是圖一個方便(投一下懶,嘿嘿!)。試想一下這個場景:我們在寫一個新功能,每寫一部分,我們就安裝到手機上查看一下,這個過程中你要點擊到對應的頁面,做對應的操作,才能反饋給你結果。如果達到了預期效果,那么恭喜你。可是一旦這次失敗了,是不是又要重復這一過程?是不是感到很麻煩?很費時間?如果你想早點寫完下班,那么你就需要掌握單元測試。因為它能大大的縮短你自我驗證的時間。
          一、準備工作
          我們新建一個項目,模板代碼會默認在build文件中添加JUnit的依賴,而單元測試代碼是放在src/test/java下面的,如下圖:


      用鼠標右鍵點擊測試方法,選擇菜單中的“Run”選項就可以執行對應的單元測試。我執行了圖中的測試代碼,可以看到執行方法只用了6毫秒,整個過程不到2秒。

      二、JUnit介紹
      JUnit是Java基礎的測試框架,主要的作用就是斷言。

      使用時在app的build文件中添加依賴。注意:用于測試環境框架一律是testCompile開頭。

      dependencies {
          testCompile 'junit:junit:4.12'
      }
      Assert類中主要方法如下:

      方法名 方法描述
      assertEquals 斷言傳入的預期值與實際值是相等的
      assertNotEquals 斷言傳入的預期值與實際值是不相等的
      assertArrayEquals 斷言傳入的預期數組與實際數組是相等的
      assertNull 斷言傳入的對象是為空
      assertNotNull 斷言傳入的對象是不為空
      assertTrue 斷言條件為真
      assertFalse 斷言條件為假
      assertSame 斷言兩個對象引用同一個對象,相當于“==”
      assertNotSame 斷言兩個對象引用不同的對象,相當于“!=”
      assertThat 斷言實際值是否滿足指定的條件
      注意:上面的每一個方法,都有對應的重載方法,可以在前面加一個String類型的參數,表示如果斷言失敗時的提示。

      JUnit 中的常用注解:
      注解名 含義
      @Test 表示此方法為測試方法
      @Before 在每個測試方法前執行,可做初始化操作
      @After 在每個測試方法后執行,可做釋放資源操作
      @Ignore 忽略的測試方法
      @BeforeClass 在類中所有方法前運行。此注解修飾的方法必須是static void
      @AfterClass 在類中運行。此注解修飾的方法必須是static void
      @RunWith 指定該測試類使用某個運行器
      @Parameters 指定測試類的測試數據集合
      @Rule 重新制定測試類中方法的行為
      @FixMethodOrder 指定測試類中方法的執行順序
      執行順序:@BeforeClass –> @Before –> @Test –> @After –> @AfterClass

      三、JUnit用法
      我們測試下面這個簡單的時間轉換工具類,來說明一下具體的用法。
      public class DateUtil {
          /**
           * 英文全稱  如:2017-11-01 22:11:00
           */
          public static String FORMAT_YMDHMS = "yyyy-MM-dd HH:mm:ss";
          /**
           * 掉此方法輸入所要轉換的時間輸入例如("2017-11-01 22:11:00")返回時間戳
           *
           * @param time
           * @return 時間戳
           */
          public static long dateToStamp(String time) throws ParseException{
              SimpleDateFormat sdr = new SimpleDateFormat(FORMAT_YMDHMS, Locale.CHINA);
              Date date = sdr.parse(time);
              return date.getTime();
          }
          /**
           * 將時間戳轉換為時間
           */
          public static String stampToDate(long lt){
              String res;
              SimpleDateFormat simpleDateFormat = new SimpleDateFormat(FORMAT_YMDHMS, Locale.CHINA);
              Date date = new Date(lt);
              res = simpleDateFormat.format(date);
              return res;
          }
      }
      四、基礎用法
      1.首先測試stampToDate方法,測試時我認為返回的結果等于“預期時間”這個字符串。測試方法執行后如下圖:



      可以看到預期值與實際結果不符,測試失敗!想要測試成功要么預期值為”2017-10-15 16:00:02”要么使用assertNotEquals方法斷言。

      2.接下來測試dateToStamp方法。



      很簡單,我認為返回結果不等于4,結果測試通過。

      3.我們注意到在dateToStamp方法中,有拋出一個解析異常(ParseException)。也就是當參數沒有按照規定格式去傳,就會導致這個異常。




      那我們怎么驗證一個方法是否拋出了異常呢?可以給@Test注解設置expected參數來實現,如下:



      拋出了對應的異常則測試成功,反之則測試失敗。

      2.參數化測試
      這時,你是不是覺得還是很麻煩,因為每次測試一個方法都要去設置對應的值,就不能連續用不不同的值去測試一個方法,省的我們不斷地
      修改。這時就用到了@RunWith與@Parameters。
      首先在測試類上添加注解@RunWith(Parameterized.class),在創建一個由 @Parameters 注解的public static方法,讓返回一個對應的測試數據集合。創建構造方法,方法的參數順序和類型與測試數據集合一一對應。


      上圖就是一個簡單的例子,可以看到連續執行了三次測試,其中第二次測試沒有拋出異常,測試失敗!

      3.assertThat用法
      上面我們所用到的一些基本的斷言,如果我們沒有設置失敗時的輸出信息,那么在斷言失敗時只會拋出AssertionError,無法知道到底是哪一部分出錯。而assertThat就幫我們解決了這一點。它的可讀性更好。

      assertThat(T actual, Matcher<? super T> matcher);

      assertThat(String reason, T actual, Matcher<? super T> matcher); 

      其中reason為斷言失敗時的輸出信息,actual為斷言的值,matcher為斷言的匹配器。

      常用的匹配器整理:
      匹配器 說明 例子
      is 斷言參數等于后面給出的匹配表達式 assertThat(5, is (5));
      not 斷言參數不等于后面給出的匹配表達式 assertThat(5, not(6));
      equalTo 斷言參數相等 assertThat(30, equalTo(30));
      equalToIgnoringCase 斷言字符串相等忽略大小寫 assertThat(“Ab”, equalToIgnoringCase(“ab”));
      containsString 斷言字符串包含某字符串 assertThat(“abc”, containsString(“bc”));
      startsWith 斷言字符串以某字符串開始 assertThat(“abc”, startsWith(“a”));
      endsWith 斷言字符串以某字符串結束 assertThat(“abc”, endsWith(“c”));
      nullValue 斷言參數的值為null assertThat(null, nullValue());
      notNullValue 斷言參數的值不為null assertThat(“abc”, notNullValue());
      greaterThan 斷言參數大于 assertThat(4, greaterThan(3));
      lessThan 斷言參數小于 assertThat(4, lessThan(6));
      greaterThanOrEqualTo 斷言參數大于等于 assertThat(4, greaterThanOrEqualTo(3));
      lessThanOrEqualTo 斷言參數小于等于 assertThat(4, lessThanOrEqualTo(6));
      closeTo 斷言浮點型數在某一范圍內 assertThat(4.0, closeTo(2.6, 4.3));
      allOf 斷言符合所有條件,相當于&& assertThat(4,allOf(greaterThan(3), lessThan(6)));
      anyOf 斷言符合某一條件,相當于或 assertThat(4,anyOf(greaterThan(9), lessThan(6)));
      hasKey 斷言Map集合含有此鍵 assertThat(map, hasKey(“key”));
      hasValue 斷言Map集合含有此值 assertThat(map, hasValue(value));
      hasItem 斷言迭代對象含有此元素 assertThat(list, hasItem(element));
      下圖為使用assertThat測試失敗時所顯示的具體錯誤信息。可以看到錯誤信息很詳細!


      當然了匹配器也是可以自定義的。這里我自定義一個字符串是否是手機號碼的匹配器來演示一下。

      只需要繼承BaseMatcher抽象類,實現matches與describeTo方法。代碼如下:

      public class IsMobilePhoneMatcher extends BaseMatcher<String> {

          /**
           * 進行斷言判定,返回true則斷言成功,否則斷言失敗
           */

          @Override
          public boolean matches(Object item) {
              if (item == null) {
                  return false;
              }

              Pattern pattern = Pattern.compile("(1|861)(3|5|7|8)d{9}$*");
              Matcher matcher = pattern.matcher((String) item);

              return matcher.find();
          }

          /**
           * 給期待斷言成功的對象增加描述
           */
          @Override
          public void describeTo(Description description) {
              description.appendText("預計此字符串是手機號碼!");
          }

          /**
           * 給斷言失敗的對象增加描述
           */
          @Override
          public void describeMismatch(Object item, Description description) {
              description.appendText(item.toString() + "不是手機號碼!");
          }
      }

      執行單元測試如下:

      正確的手機號碼測試成功:



      錯誤號碼測試失敗:



      5.@Rule用法
      還記得一開始我們在@Before與@After注解的方法中加入”測試開始”的提示信息嗎?假如我們一直需要這樣的提示,那是不是需要每次在測試類中去實現它。這樣就會比較麻煩。這時你就可以使用@Rule來解決這個問題,它甚至比@Before與@After還要強大。自定義@Rule很簡單,就是實現TestRule 接口,實現apply方法。代碼如下:

      public class MyRule implements TestRule {
          @Override
          public Statement apply(final Statement base, final Description description) {
              return new Statement() {
                  @Override
                  public void evaluate() throws Throwable {
                      // evaluate前執行方法相當于@Before
                      String methodName = description.getMethodName(); // 獲取測試方法的名字
                      System.out.println(methodName + "測試開始!");
                      base.evaluate();  // 運行的測試方法
                      // evaluate后執行方法相當于@After
                      System.out.println(methodName + "測試結束!");
                  }
              };
          }
      }

      我們使用一下我們自定義的MyRule,效果如圖:


      PS:計劃開始寫有關Android單元測試的內容,因為涉及的測試框架比較多,所以由簡至難開始,終再達到日常開發實用的階段。小編也盡量快速的更新這一系列。代碼已上傳至Github。希望大家多多點贊支持!

      粵嵌科技13年專注IT人才培訓學習的專業機構,主要培訓課程為,嵌入式開發Java大數據、Unity游戲開發、Python人工智能、HTML5前端開發、全棧UI設計、網絡營銷、CCIE網絡等專業課程


      免費預約試聽課

      亚洲另类欧美综合久久图片区_亚洲中文字幕日产无码2020_欧美日本一区二区三区桃色视频_亚洲AⅤ天堂一区二区三区

      
      

      1. 亚洲国产国语高清在线网址 | 午夜福利yw在线观看2020 | 在线不卡高速播放AV电影 | 日韩字幕一中文在线综合 | 日本狂喷奶水在线播放212 | 色资源在线精品 |