Gradle Plugin Samples 之 Gradle Unit Test(七)

Gradle Unit Test

Android Studio 1.1 正式版本已經發布, 1.1 版本最大的新功能就是正式支持 Unit 。所謂支持 Unit 是指 Gradle 的 Unit 支持。本文中的內容,也需要在 Android Studio 1.1 中才能正常執行。

文本是對 Unit testing support 的個人理解和總結。不足的地方,還望指正。

環境設置

講解1

在默認情況下,Android Studio 只開啓了 Android Instrumentation Test ,需要手動開啓 Unit Test 。

Settings-->Gradle-->Experimental ,勾選 Enable Unit Testing support 。



講解2

在 Build Variants 面板中,選擇 Unit Tests 。



講解3

當你在在 Build Variants 面板中,選擇 Unit Tests 時,可能會有如下的提示:



其實,你可能在上一步勾選 Enable Unit Testing support 時就已經發現了,Android Studio 已經提示了, Unit Testing 需要 Android Gradle plugin 1.1 以及以上版本,所以我們需要設置 {@projectName}/build.gradle 中的 Android Gradle plugin 版本爲 1.1 ,如果你的 Android Gradle plugin 已經爲 1.1 或者以上版本,可以跳過此步。

buildscript {
repositories {
    jcenter()
}
dependencies {
    classpath 'com.android.tools.build:gradle:1.1.0'

    // NOTE: Do not place your application dependencies here; they belong
    // in the individual module build.gradle files
}
}

allprojects {
repositories {
    jcenter()
}
}


講解4

Java 在做 Unit Test 的時候,最常用的便是 JUnit 了,所以我們需要加入 JUnit 的依賴。在{@projectName}/{@moduleName}/build.gradle 中添加 JUnit 的 Maven 依賴。

dependencies {
testCompile 'junit:junit:4.12'
}


testCompile 意思爲,test模式下依賴某一個庫,該庫不會在我們正式發佈時打包到我們的程序中,作用和debugCompile 類似。

講解5

在 {@moduleName}/src 目錄下創建 test/java 文件夾。該文件夾是 Unit Test 代碼存放的位置。

測試代碼的包名、類名、方法名均可以自定義,不用和被測試代碼相同。但是爲了方便自己和他人,建議使用一一對應的方式建立原代碼和測試代碼的關係

編寫測試

講解6

Demo GradleUnitTest 是一個測試 Utils 類中 add 方法的項目,藉助測試該類我們學習 Unit Test 的基本使用。該類的具體文件路徑爲{@projectName}/{@moduleName}/src/main/java/cc/bb/aa/gradleunittest/util/Utils.java 。

public class Utils
{
public static int add(int a, int b)
{
    return a + b;
}
}


我們爲 Utils 類編寫一個測試類,類名爲 UtilsTest ,該類具體的具體文件路徑爲{@projectName}/{@moduleName}/src/test/java/cc/bb/aa/gradleunittest/util/UtilsTest.java 。

public class UtilsTest
{
@Test
public void add()
{
    Assert.assertTrue(3 == Utils.add(1, 2));
}
}


其中 @Test 爲 JUnit 的註解,用於標註測試方法。關於更多 JUnit 的知識,請自行搜索學習。

我們可以在 Build Variants 面板中切換 Unit Tests 和 Android Instrumentation Test 來觀察 Project 面板中項目目錄的顯示情況。

勾選 Android Instrumentation Test 時:



勾選 Unit Tests 時:

執行測試

JUnit

講解7

選擇 Edit configurations



添加一個 JUnit



刪除 Before launch 中的 Make ,添加一個 Gradle-aware make ,Task 可以不用填寫,直接點擊 OK 。

你可以在 Configuration 中設置測試過濾。例如,我在 Test kind 中選擇 All in directory ,並且在 Directory 中選擇了 {@projectName}/{@moduleName}/src/test/java 文件夾,這樣便可以一次性測試所有的測試代碼。

需要在 Use classpath of module 中選擇需要測試的 module 。

最終的設置結果如下:



點擊 OK ,運行剛剛設置的 JUnit ,便可以觀察到測試結果。



Gradle Unit

講解8

我們除了在 Run/Debug Configurations 中添加 JUnit 之外,還可以在 Gradle 面板中執行 test 命令。

雙擊 Gradle 面板中執行 test 命令,發現該命令除了在 Message 和 Run 面板中輸入大段大段的文字,並沒有什麼具體的反應。其實,測試的結果放在了一個目錄下面。

在 {@projectName}/{@moduleName}/build/reports/tests 中我們可以看到 debug 和 release 兩個文件夾,分別對應的是 debug 和 release 這兩個 BuildTypes 的測試結果( Gradle 的 test 命令實際包含了testDebug 和testRelease 兩個命令)。在這兩個文件夾中,就是各自的測試結果。

例如,在 debug 文件夾中,我們打開 index.html 就可以查看測試結果了。



執行 test 命令時,如果 testDebug 出現了斷言錯誤,命令將停止,不再繼續 testRelease 。如果你想一次性執行所有的測試,即使出現了斷言錯誤也要繼續 testRelease ,請看 講解9 。

講解9

你也可以在命令行中使用 Gradle 命令執行 Unit Test 。

例如,講解8 中的 test 命令,我們可以在命令行中執行 ./gradlew test 完成。

執行 test 命令時,如果 testDebug 出現了斷言錯誤,命令將停止,不再繼續 testRelease 。如果你想一次性執行所有的測試,即使出現了斷言錯誤也要繼續的話,你可以使用 ./gradlew test --continue 命令。這樣,所以的測試結果都會輸出到 {@projectName}/{@moduleName}/build/reports/tests 目錄,包括斷言錯誤的內容。

如果你想單獨測試某個類,你可以添加 --tests 參數。例如: ./gradlew testDebug --tests='*.MyTestClass' 。

在命令行中使用 Gradle 命令是一件很痛苦的事情,因爲它會下載項目構建環境依賴(~~因爲 GFW ,你還可能下載失敗~~)。而這些依賴已經存在 Android Studio 中了。沒有使用已經存在的依賴,是因爲在命令行中執行Gradle 命令已經脫離了 Android Studio,就是純粹地使用 Gradle (Android Studio Gradle plugin 的作用便在於此)。

Flavors 和 BuildTypes

本節內容,請參考 GradleUnitTest2 中的代碼。

講解10

Gradle 支持 Flavors 和 BuildTypes ,因此要有對應的測試。

Flavors 和 BuildTypes 中的代碼需要和對應分支下的測試類有對應的目錄關係。 GradleUnitTest2 中對應的關係如下:

src/main/java/cc/bb/aa/gradleunittest/util/Utils.java
-->
src/test/java/cc/bb/aa/gradleunittest/util/UtilsTest.java

src/amazon/java/cc/bb/aa/gradleunittest/util/ProductFlavors.java
-->
src/testAmazon/java/cc/bb/aa/gradleunittest/util/ProductFlavorsTest.java

src/google/java/cc/bb/aa/gradleunittest/util/ProductFlavors.java
-->
src/testGoogle/java/cc/bb/aa/gradleunittest/util/ProductFlavorsTest.java

src/debug/java/cc/bb/aa/gradleunittest/util/BuildTypes.java
-->
src/testDebug/java/cc/bb/aa/gradleunittest/util/BuildTypesTest.java

src/release/java/cc/bb/aa/gradleunittest/util/BuildTypes.java
-->
src/testRelease/java/cc/bb/aa/gradleunittest/util/BuildTypesTest.java

因此,Gradle 命令不再簡簡單單隻有 test 、 testDebug 、 testRelease 3個,現在爲 test 、testAmazonDebug 、 testAmazonRelease 、 testGoogleDebug 、 testGoogleRelease 。同樣的道理,test 命令包含了其他4個命令。

其他內容

講解11

Unit Test 應該是儘可能獨立的。對一個 class 的 Unit Test 不應該再和其他 class 有任何交互。

用於運行單元測試的 android.jar 文件不包含任何實際的代碼(實際的代碼由程序所運行在的 Android 真實設備提供),相反,所有的方法拋出異常(默認情況下)。需要確保您的單元測試只是測試你的代碼,不依賴於 Android 平臺的任何特定行爲。如果你沒有使用虛擬依賴生產測試框架(例如: Mockito ),你需要在{@projectName}/{@moduleName}/build.gradle 文件中添加以下內容:

android {
// ...
testOptions { 
unitTests.returnDefaultValues = true
}
}


例如,我們在測試代碼中使用了 TextUtils.isEmpty 方法。在測試時,該方法會出現java.lang.RuntimeException: Method isEmpty in android.text.TextUtils not mocked. 異常。當我們設置了unitTests.returnDefaultValues = true ,無論傳入的參數是什麼,TextUtils.isEmpty 方法永遠返回 false 。


轉至:http://ask.android-studio.org/?/article/44

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章