【Android】Unit TestでTruthを使ってみる

## はじめに
Android開発のLocal Unit Testを作成していく際に、テストの検証ツールとしてアサーションライブラリを選択するかと思います。
選択肢としては、AssertJ、Truth が多くなるかなと思います。

今回はTruthを選択し、どんな感じで使えるのかまとめていきたいと思います。

## Truthとは何か
[Truth](https://truth.dev/)とは、	Googleが提供しているアサーションライブラリです。
公式サイトを見てみると、Googleのコードのほとんどでこちらが使われているとのこと。

Truthは、他のアラーションライブラリに比べAPIが直感的でシンプルという特徴があり、書きやすく読みやすいテストコードを作成することができます。
```sample.kt
@RunWith(AndroidJUnit4::class)
class TruthUnitTest {
    @Test
    fun list_hasSize_3() {
        val list = listOf(1, 2, 3)
        assertThat(list).hasSize(3)
    }
}

```

また、テスト失敗時に表示してくれるエラーメッセージもわかりやすいです。
期待値、実測値というのがぱっと見でわかります。
```sample.kt
@RunWith(AndroidJUnit4::class)
class TruthUnitTest {
    @Test
    fun list_hasSize_3() {
        val list = listOf(1, 2, 3)
        // 失敗するように変更
        assertThat(list).hasSize(2) 
    }
}

```

``` log
value of    : iterable.size()
expected    : 2
but was     : 3
iterable was: [1, 2, 3]
```
## 導入
簡単にTruthについてまとめましたので、実際に導入していきたいと思います。
導入といってもやることはbuild.gradleに依存関係を追加するだけです。
```build.gradle.kts(app)
dependencies {
　　　　// バージョンは公式サイト等で確認してください
  testImplementation "com.google.truth:truth:1.4.2" 
}
```
TruthはUnit Test環境でのみ使用するので、**testImplementation**で追加します。

## テストの作成
それでは、いくつかTruthを使ったテストを書いていきます。
基本的な使い方としては、**「assertThat(判定したいもの).判定内容」** という形で使うようです。

### isEqualTo：期待されている値と等しいか判定する
isEqualToを使うことで、テスト対象に設定されている値と、isEqualToで設定した期待値が等しいかテストできます。
数値や文字列、真偽値等、幅広く判定できそうです。
真偽値の判定については、この後記載しているisTrue / isFalseを使った方良さそうです。
```sample.kt
     @Test
    fun value_int_is_equal() {
        val value = 2 + 2
        assertThat(value).isEqualTo(4)
    }

    @Test
    fun value_string_is_equal() {
        val value = "Hello"
        assertThat(value).isEqualTo("Hello")
    }
```

### isTrue / isFalse：真偽値を判定する
isTrue / isFalseは真偽値の判定に使います。
```sample.kt
    @Test
    fun value_boolean_is_true() {
        val value = true
        assertThat(value).isTrue()
    }
    
    @Test
    fun value_boolean_is_false() {
        val value = false
        assertThat(value).isFalse()
    }
```

### contains:リストに指定した値が含まれているか判定する
containsはリストや配列の中身に指定した値が含まれているかの判定に使います。

```sample.kt
    @Test
    fun list_contain_value() {
        val actualList = listOf("apple", "banana", "cherry")
        assertThat(actualList).contains("banana")
    }
```

また、複数の値がすべて含まれているかどうか、複数の値のうちのどれかが含まれているかも、似たようなメソッドが用意されています。

```sample.kt
    @Test
    fun list_contains_values() {
        val actualList = listOf("apple", "banana", "cherry", "date")
        // 全て含まれているか
        assertThat(actualList).containsAtLeast("banana", "cherry")
    }
    
    @Test
    fun list_contains_any_values() {
        val actualList = listOf("apple", "banana", "cherry", "date")
        // いずれかが含まれているか
        assertThat(actualList).containsAnyOf("banana", "grape")
    }
```

### hasSize:リストの件数を判定する
hasSizeを使うことで、リストの件数を判定することができます。

```sample.kt
    @Test
    fun list_size() {
        val actualList = listOf("apple", "banana", "cherry", "date")
        assertThat(actualList).hasSize(4)
    }
```

### applyを使って複数の判定をまとめて書く
Kotlinのapplyと組み合わせることで、複数のケースを繋げるように書けます。
一つの確認対象に対し、applyを使って複数の判定をまとめてかけます
```sample.kt
    @Test
    fun list_test() {
        val actualList = listOf("apple", "banana", "cherry", "date")
        assertThat(actualList).apply {
            hasSize(4)
            contains("banana")
            containsAtLeast("banana", "cherry")
            containsAnyOf("banana", "grape")
        }
    }
```

### 例外のテストケースを書く
try-catchと組み合わせることで、例外と捕捉し、Exceptionのクラス、メッセージ等のテストを書くことができます。
```sample.kt
 @Test
    fun test_exception() {
        try {
            throwException()
        } catch (e: IllegalArgumentException) {
            assertThat(e).apply {
                isInstanceOf(IllegalArgumentException::class.java)
                hasMessageThat().isEqualTo("This is an illegal argument")
            }
        }
    }

    private fun throwException() {
        throw IllegalArgumentException("This is an illegal argument")
    }

```

## おわりに
今回はアサーションライブラリのTruthを使ってみました。
私自身も初めて使ってみましたので、あまりまだ深く触れていませんが、直感的にスラスラ書くことができたなーってイメージです。
今後もUnit Testを作るときはTruthを採用し、慣れていきたいと思います。

## 参考
[Android ユニットテスト ヒッチハイク・ガイド](https://zenn.dev/okuzawats/books/android-unit-testing/viewer/truth)
[公式サイト](https://truth.dev/)