LoginSignup
6
6

More than 1 year has passed since last update.

【Android】TestParameterInjectorを使ってParameterizedテストを行おう

Posted at

はじめに

Googleが出している TestParameterInjector を使うと、すこぶる簡単にParameterizedテスト(パラメータ化テスト)を書くことができたので、サンプルコードなどを載せつつ説明したいと思います。

TestParameterInjectorに関して

詳しくは https://opensource.googleblog.com/2021/03/introducing-testparameterinjector.html のブログ記事を参考いただければと思いますが、簡単にまとめると…

  • Googleが2021年3月に公開したJUnit4 Test Runner
  • Googleのコードベースで新しいテストのために最も使用されているフレームワーク

TestParameterInjector is now the most used framework for new tests in the Google codebase:

という感じです。

使用する場合は

testImplementation 'com.google.testparameterinjector:test-parameter-injector:1.3'

dependencies に追加すればOKです。( 1.3 は執筆時のバージョン)

サンプルコード

サンプルコードを交えつつ、 TestParameterInjector を使うとどうなるのかを説明します。

Piyo

テスト対象のコードとして Piyo クラスを用意しました。

say メソッドがあり、引数の value により

  • 2で割り切れるときは「piyopiyo」
  • それ以外のときは「piyo」

を返却します。

class Piyo {
    fun say(value: Int): String {
        return when {
            value % 2 == 0 -> "piyopiyo"
            else -> "piyo"
        }
    }
}

PiyoTest

Piyo に対して TestParameterInjector を使わないで 素朴なテストコードを記述すると以下のようになるでしょうか。

  • 2のときに「piyopiyo」であること
  • 1, 3のときに「piyo」であること
  • 0のときは「piyopiyo」であること

見ていただけるとわかりますが、パラメータの値( value )とAssertion時の値が違う以外はほぼ重複したコードになってしまっています。

class PiyoTest {

    @Test
    fun piyo_say_piyopiyo_when_2() {
        val value = 2 // ここと
        val piyo = Piyo()

        val result = piyo.say(value)

        Assert.assertEquals("piyopiyo", result) // ここが違うだけ
    }

    @Test
    fun piyo_say_piyo_when_1() {
        val value = 1
        val piyo = Piyo()

        val result = piyo.say(value)

        Assert.assertEquals("piyo", result)
    }

    @Test
    fun piyo_say_piyo_when_3() {
        val value = 3
        val piyo = Piyo()

        val result = piyo.say(value)

        Assert.assertEquals("piyo", result)
    }

    @Test
    fun piyo_say_piyopiyo_when_0() {
        val value = 0
        val piyo = Piyo()

        val result = piyo.say(value)

        Assert.assertEquals("piyopiyo", result)
    }
}

TestParameterInjectorを使ってみる

Piyo に対して TestParameterInjector を使って パラメータ化テストを作成してみると以下のようになります。

@RunWith(TestParameterInjector::class) // ← ①
class PiyoTest2 {

    // ↓ ②
    enum class PiyoTestCase(val value: Int, val expected: String) {
        CASE0(0, "piyopiyo"),
        CASE1(1, "piyo"),
        CASE2(2, "piyopiyo"),
        CASE3(3, "piyo"),
    }

    // ↓ ③
    @Test
    fun piyo_say(@TestParameter piyoTestCase: PiyoTestCase) {
        val value = piyoTestCase.value // valueを使う
        val piyo = Piyo()

        val result = piyo.say(value)

        Assert.assertEquals(piyoTestCase.expected, result) // expectedを使う
    }
}
  1. @RunWithTestParameterInjector を指定する
  2. PiyoTestCase で引数( value )と期待値( expected )の組み合わせを定義する
  3. テストの引数に @TestParameter を指定した PiyoTestCase を指定する

こうしてやると

テストコード piyo_say の引数が
- CASE0 の場合
- CASE1 の場合
- CASE2 の場合
- CASE3 の場合

と4回呼ばれることになります。

↓実行した結果もこの通り、テストメソッドは1つなのに、4つのテスト結果が出力されます。
スクリーンショット 2021-06-05 23.35.42.png

TestParameterInjector の適用前・後でテストコードがかなりスッキリしたことがおわかりになったかと思います。

その他の方法

上記のサンプルコードではテストケースをenumで定義し、テストメソッドの引数に渡す方法でしたが、

  • BooleanInt を使う
  • @TestParameter アノテーションを付けてフィールドに定義する

なども可能です。
フィールドに定義した場合は、テストコード全体でパラメータ化されて実行されることになります。

@RunWith(TestParameterInjector::class)
class MyTest {

    @TestParameter
    var isDryRun = false

    @TestParameter("1", "2", "3")
    var i = 0

    @Test
    fun test1(@TestParameter enableFlag: Boolean) {
        // 12通りの組み合わせで呼ばれる
        // test1[isDryRun=false,i=1,false]
        // test1[isDryRun=false,i=1,true]
        // test1[isDryRun=false,i=2,false]
        // test1[isDryRun=false,i=2,true]
        // test1[isDryRun=false,i=3,false]
        // test1[isDryRun=false,i=3,true]
        // test1[isDryRun=true,i=1,false]
        // test1[isDryRun=true,i=1,true]
        // test1[isDryRun=true,i=2,false]
        // test1[isDryRun=true,i=2,true]
        // test1[isDryRun=true,i=3,false]
        // test1[isDryRun=true,i=3,true]
    }

    @Test
    fun test2() {
        // 6通りの組み合わせで呼ばれる
        // test2[isDryRun=false,i=1]
        // test2[isDryRun=false,i=2]
        // test2[isDryRun=false,i=3]
        // test2[isDryRun=true,i=1]
        // test2[isDryRun=true,i=2]
        // test2[isDryRun=true,i=3]
    }
}

また Advanced usage として動的な @TestParameter の生成などもできるようなので、興味のある方は見てみても良いかもしれません。
https://github.com/google/TestParameterInjector#advanced-usage

終わりに

TestParameterInjector の簡単な説明とサンプルコードをご紹介しました。
テストコードが驚くほどスッキリするので、使えるところでは積極的に使って、楽しくテストコードを書いていきたいところです。

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6