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を使うためにライブラリの依存リストへ次の一行を追加します。
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
@Test
fun Nullテスト() {
val s: String = "Yamada"
val n: String? = null
assertThat(n).isNull() // nは Null である
assertThat(s).isNotNull() // sは Null でない
}
Number
Kotlin
@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
@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
@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
@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
// ・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
@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
// ・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
@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
@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
@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=パッケージ名 を持つ
}
スポンサーリンク
スポンサーリンク
