Unit Test 探求記は、unit test に関してまったりと実験しつつその過程を綴ってみるというものです。
今回のお題
Unit test と instrumented unit test を実行してみます。
Unit Test の実行(失敗例)
ここで言う unit test とは、src/test 以下のテストのことを指しています。
わざと間違えて、テストが実行されていることを確認してみます。
ExampleUnitTest.kt
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
// assertEquals(4, 2 + 2)
// わざと間違えてみる。
assertEquals(5, 2 + 2)
}
}
下記のようにコマンドライン上で実行します:
$ ./gradlew clean test --info
com.objectfanatics.myapplication.ExampleUnitTest > addition_isCorrect FAILED
java.lang.AssertionError: expected:<5> but was:<4>
at org.junit.Assert.fail(Assert.java:88)
at org.junit.Assert.failNotEquals(Assert.java:834)
at org.junit.Assert.assertEquals(Assert.java:645)
at org.junit.Assert.assertEquals(Assert.java:631)
at com.objectfanatics.myapplication.ExampleUnitTest.addition_isCorrect(ExampleUnitTest.kt:18)
ちゃんとテストが失敗していることを確認できました。
Instrumented Unit Test の実行(失敗例)
ここで言う instrumented unit test とは、src/androidTest 以下のテストのことを指しています。
わざと間違えて、テストが実行されていることを確認してみます。
ExampleInstrumentedTest.kt
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
// assertEquals("com.objectfanatics.chrono0020", appContext.packageName)
fail("I made a mistake on purpose.")
}
}
実機を接続た後、下記のようにコマンドライン上で実行します:
$ ./gradlew clean connectedAndroidTest
> Task :app:connectedDebugAndroidTest
Starting 1 tests on ASUS_X00PD - 8.0.0
com.objectfanatics.myapplication.ExampleInstrumentedTest > useAppContext[ASUS_X00PD - 8.0.0] FAILED
java.lang.AssertionError: I made a mistake on purpose.
at org.junit.Assert.fail(Assert.java:88)
> Task :app:connectedDebugAndroidTest FAILED
ちゃんとテストが失敗していることを確認できました。
依存関係を確認してみる
以下に、テスト関連の設定を抜粋し、コメントしてみます。
app/build.gradle.kts
android {
// JUnit 4 のテストクラス群を利用するため、AndroidJUnitRunner をデフォルトの test instrumentation runner としてセットしている。
// instrumented unit test とは実機(やエミュレータ)上で実行される unit test のこと。
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
}
dependencies {
// 通常の unit test から利用される JUnit 4 のクラス群への依存。※ org.junit.Test 等
testImplementation("junit:junit:4.12")
// instrumented unit test から利用される JUnit 4 のクラス群への依存。※ AndroidJUnit4, ActivityScenarioRule 等
androidTestImplementation("androidx.test.ext:junit:1.1.1")
// Espresso testing framework への依存。
// Espresso testing framework は UI テストのためのフレームワーク。
// @see https://developer.android.com/training/testing/ui-testing/espresso-testing
androidTestImplementation("androidx.test.espresso:espresso-core:3.2.0")
}
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
を外しても IDE 上で警告は出ませんが、実行時に以下のようになり、instrumented unit test が失敗します:
$ ./gradlew clean connectedAndroidTest
> Task :app:connectedDebugAndroidTest
Starting 0 tests on ASUS_X00PD - 8.0.0
Tests on ASUS_X00PD - 8.0.0 failed: Instrumentation run failed due to 'Process crashed.'
com.android.build.gradle.internal.testing.ConnectedDevice > No tests found.[ASUS_X00PD - 8.0.0] FAILED
No tests found. This usually means that your test classes are not in the form that your test runner expects (e.g. don't inherit from TestCase or lack @Test annotations).
> Task :app:connectedDebugAndroidTest FAILED
FAILURE: Build failed with an exception.
エラーの表示から依存関係の指定漏れであることを推測するのは難しそうですね、、、。
Test の実行(成功例)
わざと間違った個所を修正してテストを実行します。
ExampleUnitTest.kt
ExampleInstrumentedTest.kt
$ ./gradlew clean test
BUILD SUCCESSFUL in 6s
28 actionable tasks: 28 executed
ちゃんとテストが成功していることを確認できました。
まとめ
今回は、Unit test と instrumented unit test を実行してみました。
ソースコード
Android Studio により Empty Activity project を生成し、build.gradle を build.gradle.kts に変換したものがベースとなっています。
▼ テストに失敗するコード
source tree
$ git clone git@github.com:beyondseeker/chrono0020.git
$ cd chrono0020
$ git checkout bb13107f90c9fadac13b8a4d6b7259e222322739
▼ テストに成功するコード
source tree
$ git clone git@github.com:beyondseeker/chrono0020.git
$ cd chrono0020
$ git checkout 013ee1075230625b8d5a23b12588234246252175