Truthのアサーション記述例を紹介します。
Kotlinは「is」が予約語になっているので、Hamcrestで記述すると「`is`」になってしまいます。Java⇒Kotlinの自動変換を行ったら現れたのです。最初、変換ミスかと思いました。
動作に関係のない文字が入るのは嫌いです。
何か解決策はないかと、最近購入した書籍「みんなのKotlin」を見ていたらTruthがあるのを知りました。なかなか良いかも!
なので、今までHamcrestを使っていましたがTruthへ乗り換えます。
目次 [非表示]
スポンサーリンク
Truthとは
TruthはAssertJやHamcrestと同じアサーションライブラリの一つです。
AndroidX Testの一部としてリリースされていて、現在(2020年9月)最新版はVer1.3.0になっています。積極的な開発が行われているようです。また、Truthの標準的なアサーション構文に加えて、Android向けの構文が存在しています。とても興味深いところです。今後、Androidと親和性が増していきそうな感じです。
Truthのさらなる情報はここを参照してください。
スポンサーリンク
環境設定
Truthを使うためにライブラリの依存リストへ次の一行を追加します。
1 2 3 4 5 | dependencies { ... androidTestImplementation 'androidx.test.ext:truth:1.3.0' ... } |
\--- androidx.test.ext:truth:1.3.0 +--- androidx.test:core:1.3.0 (*) +--- com.google.guava:guava:27.0.1-android +--- com.google.truth:truth:1.0 \--- androidx.annotation:annotation:1.0.0
AndroidX(androidx.test.ext:truth)に組み困れているTruth本体(com.google.truth:truth)のバージョンはリリースノートを参照してください。
スポンサーリンク
アサーション記述例(標準的な構文)
※アサーション記述例は全てPassします
※Kotlinのコードのみ
Null
Kotlin
1 2 3 4 5 6 7 8 | @Test fun Nullテスト() { val s: String = "Yamada" val n: String? = null assertThat(n).isNull() // nは Null である assertThat(s).isNotNull() // sは Null でない } |
Number
Kotlin
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | @Test fun Numberテスト() { val n: Int = 5 assertThat(n).isEqualTo( 5 ) // nは 5 と同じである assertThat(n).isNotEqualTo( 0 ) // nは 0 と同じでない assertThat(n).isGreaterThan( 4 ) // nは n>4 である assertThat(n).isLessThan( 6 ) // nは n<6 である assertThat(n).isAtLeast( 5 ) // nは n≧5 である assertThat(n).isAtMost( 5 ) // nは n≦5 である assertThat(n).isIn( 1 .. 10 ) // nは 1~10 内である assertThat(n).isNotIn( 6 .. 10 ) // nは 6~10 内でない assertThat(n).isAnyOf( 4 , 5 , 6 ) // n は 4,5,6 のいずれかである } |
Boolean
Kotlin
1 2 3 4 5 6 7 8 9 10 11 | @Test fun Booleanテスト() { val t: Boolean = true val f: Boolean = false assertThat(t).isEqualTo( true ) // tは true と同じである assertThat(f).isNotEqualTo( true ) // fは true と同じでない assertThat(t).isTrue() // tは true である assertThat(f).isFalse() // fは false である } |
String
Kotlin
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | @Test fun Stringテスト() { val s: String = "abcdefg" val e: String = "" assertThat(s).isEqualTo( "abcdefg" ) // sは "abcdefg" と同じである assertThat(s).isNotEqualTo( "hijklmn" ) // sは "hijklmn" と同じでない assertThat(s).startsWith( "abc" ) // sは "abc" で始まる assertThat(s).endsWith( "efg" ) // sは "efg" で終わる assertThat(s).contains( "cde" ) // sは "cde" を含む assertThat(s).doesNotContain( "c_e" ) // sは "c_e" を含まない assertThat(s).matches( "a.*g" ) // sは 正規表現:"a.*g" に一致する assertThat(s).doesNotMatch( "h.*n" ) // sは 正規表現:"h.*n" に一致しない assertThat(s).containsMatch( "c.e" ) // sは 正規表現:"c.e" に一致する部分を含む assertThat(s).doesNotContainMatch( "j.k" ) // sは 正規表現:"j.k" に一致する部分を含まない assertThat(s).isAnyOf( "123" , "abcdefg" , "456" ) // sは 指定要素 のいずれかである assertThat(e).isEmpty() // eは空である assertThat(s).isNotEmpty() // sは空でない assertThat(s).hasLength( 7 ) // sは 7 の長さを持つ } |
Array
Kotlin
1 2 3 4 5 6 7 8 9 10 11 12 | @Test fun Arrayテスト(){ val c: Array<String> = arrayOf( "abc" , "def" , "ghi" ) val e: Array<String> = arrayOf() assertThat(c).isEqualTo(arrayOf( "abc" , "def" , "ghi" )) // cは 指定配列 と同じである assertThat(c).isNotEqualTo(arrayOf( "abc" , "jkl" , "ghi" )) // cは 指定配列 と同じでない assertThat(c).hasLength( 3 ) // cは 3 の長さを持つ assertThat(e).isEmpty() // eは空である assertThat(c).isNotEmpty() // cは空でない } |
List
Kotlin
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | // ・containsAllOf()/containsAllIn() はTruth 0.46で廃止されました。 // 代わりにcontainsAtLeast()/containsAtLeastElementsIn()を使います。 @Test fun Listテスト(){ val l: List<String> = listOf( "Tokyo" , "Osaka" , "Nagoya" ) val e: List<String> = listOf() // ※Listは順番を問うコレクションである assertThat(l).isEqualTo(listOf( "Tokyo" , "Osaka" , "Nagoya" )) // lは 指定リスト (順番&数一致)と同じである assertThat(l).isNotEqualTo(listOf( "Tokyo" , "Osaka" , "A" )) // lは 指定リスト (順番&数一致)と同じでない assertThat(l).isNotEqualTo(listOf( "Nagoya" , "Osaka" , "Tokyo" )) // lは 指定リスト (順番&数一致)と同じでない assertThat(l).isNotEqualTo(listOf( "Tokyo" , "Osaka" )) // lは 指定リスト (順番&数一致)と同じでない assertThat(l).contains( "Osaka" ) // lは 指定の要素 を含む assertThat(l).doesNotContain( "A" ) // lは 指定の要素 を含まない assertThat(l).containsExactly( "Tokyo" , "Nagoya" , "Osaka" ) // lは 指定要素 の全て(順番不問、数一致)を含む // assertThat(l).containsAllOf("Nagoya", "Tokyo") // lは 指定要素 の全て(順番不問、数不問)を含む assertThat(l).containsAtLeast( "Nagoya" , "Tokyo" ) // lは 少なくとも指定要素(順番不問、数不問)を含む assertThat(l).containsAnyOf( "A" , "Nagoya" , "B" ) // Lは 指定要素 のいずれかを含む assertThat(l).containsNoneOf( "A" , "B" ) // lは 指定要素 の全てを含まない // assertThat(l).containsAllIn(listOf("Nagoya", "Tokyo")) // Lは 指定リスト の要素の全て(順番不問、数不問)を含む assertThat(l).containsAtLeastElementsIn(listOf( "Nagoya" , "Tokyo" )) // Lは 少なくとも指定リスト の要素(順番不問、数不問)を含む assertThat(l).containsAnyIn(listOf( "A" , "Nagoya" , "B" )) // Lは 指定リスト の要素のいずれかを含む assertThat(l).containsNoneIn(listOf( "A" , "B" )) // lは 指定リスト の要素の全てを含まない assertThat(l).containsNoDuplicates() // L は 重複した要素 を含まない assertThat(l).hasSize( 3 ) // Lは 3 のサイズを持つ assertThat(e).isEmpty() // eは 空 である assertThat(l).isNotEmpty() // lは 空 でない } |
Map
Kotlin
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | @Test fun Mapテスト(){ val m: Map<String, Int> = mapOf( "Tokyo" to 3 , "Nagoya" to 52 , "Osaka" to 6 ) val e: Map<String, Int> = mapOf() // ※Mapは順番を問わないコレクションである assertThat(m).isEqualTo(mapOf( "Tokyo" to 3 , "Nagoya" to 52 , "Osaka" to 6 )) // mは 指定マップ(順番不問&数一致)と同じである assertThat(m).isEqualTo(mapOf( "Nagoya" to 52 , "Osaka" to 6 , "Tokyo" to 3 )) // mは 指定マップ(順番不問&数一致)と同じである assertThat(m).isNotEqualTo(mapOf( "Tokyo" to 3 , "Nagoya" to 52 , "A" to 0 )) // mは 指定マップ(順番不問&数一致)と同じでない assertThat(m).isNotEqualTo(mapOf( "Tokyo" to 3 , "Nagoya" to 52 )) // mは 指定マップ(順番不問&数一致)と同じでない assertThat(m).containsEntry( "Osaka" , 6 ) // mは 指定エントリー を含む assertThat(m).doesNotContainEntry( "A" , 0 ) // mは 指定エントリー を含まない assertThat(m).containsKey( "Osaka" ) // mは 指定キー を含む assertThat(m).doesNotContainKey( "A" ) // mは 指定キー を含まない assertThat(m).containsExactly( "Nagoya" , 52 , "Osaka" , 6 , "Tokyo" , 3 ) // mは 指定エントリーの全て(順番不問、数一致)を含む assertThat(m).containsExactlyEntriesIn(mapOf( "Osaka" to 6 , "Tokyo" to 3 , "Nagoya" to 52 )) // isEqualToと同じ assertThat(m).hasSize( 3 ) // mは 3 のサイズを持つ assertThat(e).isEmpty() // eは空である assertThat(m).isNotEmpty() // mは空でない } |
Instance
Kotlin
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | // ・isSameAs()/isNotSameAs() はTruth 0.45で廃止されました。 // isSameInstanceAs()/isNotSameInstanceAs()を使います。 @Test fun Instanceテスト(){ val s: SampleA = SampleA() val t: SampleA = SampleA() val u: SampleB = SampleB() val o: SampleA = s // assertThat(s).isSameAs(o) // sは o と同じインスタンスである assertThat(s).isSameInstanceAs(o) // sは o と同じインスタンスである // assertThat(s).isNotSameAs(t) // sは t と同じインスタンスでない assertThat(s).isNotSameInstanceAs(t) // sは t と同じインスタンスでない assertThat(s).isInstanceOf(SampleA:: class .java) // sは SampleAクラス のインスタンスである assertThat(s).isNotInstanceOf(SampleB:: class .java) // sは SampleBクラス のインスタンスでない } |
Exception
Kotlin
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | @Test fun Exception(){ val e: Exception = IllegalArgumentException( "Must be AAA" ) val x: Exception = Exception( "Argument?" , e) assertThat(e).isInstanceOf(IllegalArgumentException:: class .java) // ↑ eは IllegalArgumentExceptionクラス のインスタンスである assertThat(e).hasMessageThat().isEqualTo( "Must be AAA" ) // ↑ eが持つメッセージは "Must be AAA" と同じである assertThat(x).isInstanceOf(Exception:: class .java) // ↑ xは Exceptionクラス のインスタンスである assertThat(x).hasMessageThat().isEqualTo( "Argument?" ) // ↑ xが持つメッセージは "Argument" と同じである assertThat(x).hasCauseThat().isInstanceOf(IllegalArgumentException:: class .java) // ↑ xが持つCauseは IllegalArgumentExceptionクラス のインスタンスである assertThat(x).hasCauseThat().hasMessageThat().isEqualTo( "Must be AAA" ) // ↑ xが持つCauseのメッセージは "Must be AAA" と同じである } |
スポンサーリンク
アサーション記述例(Android向け構文)
表にあげた構文がサポートされています。
さらなる詳細は各Subjectのドキュメントを参照してください。
Subject | Package | 記述例 |
---|---|---|
BundleSubject | androidx.test.ext.truth.os | 〇 |
IntentSubject | androidx.test.ext.truth.content | 〇 |
NotificationActionSubject | androidx.test.ext.truth.app | |
NotificationSubject | ||
PendingIntentSubject | ||
MotionEventSubject | androidx.test.ext.truth.view | |
PointerCoordsSubject | ||
PointerPropertiesSubject |
※アサーション記述例は全てPassします
※Kotlinのコードのみ
Bundle
Kotlin
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | @Test fun Bundleテスト(){ val b: Bundle = Bundle() b.putInt( "ikey" , 1 ) b.putLong( "lkey" , 2L) b.putBoolean( "bkey" , true ) b.putString( "skey" , "abc" ) val bSub_b: BundleSubject = BundleSubject.assertThat(b) bSub_b.containsKey( "ikey" ) // bは Key="ikey" を含む bSub_b.doesNotContainKey( "xkey" ) // bは Key="xkey" を含まない bSub_b.integer( "ikey" ).isEqualTo( 1 ) // bのintegerは 1 と同じである bSub_b.longInt( "lkey" ).isEqualTo(2L) // bのlongは 2 と同じである bSub_b.bool( "bkey" ).isTrue() // bのboolは true である bSub_b.string( "skey" ).isEqualTo( "abc" ) // bのstringは "abc" と同じである } |
Intent
Kotlin
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | @Test fun Intentテスト(){ val i: Intent = Intent() i.putExtra( "ikey" , 1 ) i.putExtra( "lkey" , 2L) i.putExtra( "bkey" , true ) i.putExtra( "skey" , "abc" ) val uri = Uri.parse( "file:///sdcard/SampleText.txt" ) val j: Intent = Intent(Intent.ACTION_VIEW) j.setDataAndType(uri, "text/plain" ) val m: Intent = Intent(Intent.ACTION_VIEW) m.setDataAndType(uri, "text/plain" ) val context: Context = InstrumentationRegistry.getInstrumentation().targetContext val k: Intent = Intent(context, MainActivity:: class .java) val bSub_i: BundleSubject = IntentSubject.assertThat(i).extras() val iSub_i: IntentSubject = IntentSubject.assertThat(i) val iSub_j: IntentSubject = IntentSubject.assertThat(j) val iSub_k: IntentSubject = IntentSubject.assertThat(k) bSub_i.integer( "ikey" ).isEqualTo( 1 ) // iのintegerは 1 と同じである bSub_i.longInt( "lkey" ).isEqualTo(2L) // iのlongは 2 と同じである bSub_i.bool( "bkey" ).isEqualTo( true ) // iのboolは true と同じである bSub_i.string( "skey" ).isEqualTo( "abc" ) // iのstringは "abc" と同じである iSub_i.hasNoAction() // iは Action を持たない iSub_j.hasAction(Intent.ACTION_VIEW) // jは Action=ACTION_VIEW を持つ iSub_j.hasData(Uri.parse( "file:///sdcard/SampleText.txt" )) // jは Uri= "file:..." を持つ iSub_j.hasType( "text/plain" ) // jは Type="text/plain" を持つ iSub_j.filtersEquallyTo(m) // jは m と同じフィルターである iSub_k.hasComponentClass( "パッケージ名.MainActivity" ) // kは Class=MainActivity を持つ iSub_k.hasComponentClass(MainActivity:: class .java) // kは Class=MainActivity を持つ iSub_k.hasComponentPackage( "パッケージ名" ) // kは Package=パッケージ名 を持つ } |
スポンサーリンク
スポンサーリンク