事の発端
Kotlinでのテストを学んだので学んだ内容を書いておこうと思いました。
つかうもの
- AndroidStudio 4.1
- org.junit.Test
FizzBuzz問題でテストを学ぶ
よくあるFizzBuzz問題を対象にテストを行う工程を紹介しようと思います。
FizzBuzz問題とは、以下のような問題です。
整数が一つ与えられる。
与えられた整数が3の数で割り切れる場合は”Fizz”、5の数で割り切れる場合は”Buzz”、その両方で割り切れる場合は”FizzBuzz”、どれにも当てはまらない場合は与えられた整数をそのまま出力せよ。
出力例:
1, 2, Fizz, 4, Buzz, Fizz, 7, 8, Fizz, Buzz, 11, Fizz, 13, 14, Fizz Buzz, 16…
テスト対象のメソッドを定義
今回テストするメソッド “FizzBuzz” を定義します。
Int型のnをただString型にして返すだけの、不十分なメソッドです。
app/java/com.example.myapplication/FizzBuzz.kt
1 2 3 4 5 6 7 |
package com.example.myapplication class FizzBuzzClass{ fun FizzBuzz(n:Int) : String{ //ただ数字をStringで返すだけ return n.toString(); } } |
テストを書く
次にテストを書きます。
テストは org.junit.Test をインポートした “FizzBuzzTest.kt” の内部に記述することにします。
app/java/com.example.myapplication(androidTest)/FizzBuzzTest.kt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
package com.example.myapplication import org.junit.Test import org.junit.Assert class FizzBuzzTest { private val fizzBuzz = FizzBuzzClass() @Test fun test1(){ val answer = fizzBuzz.FizzBuzz(1) Assert.assertEquals(answer,"1") } @Test fun test2(){ val answer = fizzBuzz.FizzBuzz(3) Assert.assertEquals(answer,"Fizz") } } |
Assert.assertEquals()
は片方の値がもう片方の値と等しいかどうかを判定するメソッドです。
テストを実行する
テストはクラスを右クリックして “Run ‘FizzBuzzTest'”から行うことができます。

FizzBuzz(n:Int) : String
はまだ内部の実装が進んでいないため、正常であればTest2でテストが落ちるはずです。

FizzBuzz(n:Int) : String
を実装しなおすとテストが成功するはずです。

テストの追加
テストの追加は簡単で、”@Test”を上部につけたメソッドを追加するだけです。
例えば今回であれば”Buzz”を検査するコードや、”FizzBuzz”を検査するコードを書くと良いでしょう。
app/java/com.example.myapplication(androidTest)/FizzBuzzTest.kt
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 |
package com.example.myapplication import org.junit.Test import org.junit.Assert class FizzBuzzTest { private val fizzBuzz = FizzBuzzClass() @Test fun test1(){ val answer = fizzBuzz.FizzBuzz(1) Assert.assertEquals(answer,"1") } @Test fun test2(){ val answer = fizzBuzz.FizzBuzz(3) Assert.assertEquals(answer,"Fizz") } @Test fun testBuzz(){ val answer = fizzBuzz.FizzBuzz(5) Assert.assertEquals(answer,"Buzz") } @Test fun testFizzBuzz(){ val answer = fizzBuzz.FizzBuzz(15) Assert.assertEquals(answer,"FizzBuzz") } } |

Privateなメソッドをテストしたい場合
Androidの開発をしていく中でPrivateなメソッドを検証したい場合が出たので、その流れを忘備録代わりに紹介します。
今回説明に利用するテストとテスト対象のメソッドは以下のとおりです。
app/java/com.example.myapplication/FizzBuzz.kt
1 2 3 4 5 6 7 8 |
package com.example.myapplication class FizzBuzzClass{ //Privateになった private fun FizzBuzz(n:Int) : String{ return n.toString() } } |
app/java/com.example.myapplication(android)/FizzBuzzTest.kt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
package com.example.myapplication import org.junit.Test import org.junit.Assert class FizzBuzzTest { private val fizzBuzz = FizzBuzzClass() @Test fun test1(){ val answer = fizzBuzz.FizzBuzz(1) Assert.assertEquals(answer,"1") } @Test fun test2(){ val answer = fizzBuzz.FizzBuzz(3) Assert.assertEquals(answer,"Fizz") } } |
FizzBuzz(n:int)
をPrivateにすると、テストは無事動かないはずです。
これを回避するには javaClass.getDeclaredMethod()
を使用します。
javaClass.getDeclaredMethod( )
javaClass.getDeclaredMethod( )
を利用するには import java.lang.reflect.Method
をファイルの最初に追加する必要があります。
これはメソッドを名前から直接見つけ出すメソッドです。
指定したメソッド名がなかったり引数が違ったりするなどして、メソッドが見つけられなかった場合は NoSuchMethodException
を返します。
app/java/com.example.myapplication(android)/FizzBuzzTest.kt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
package com.example.myapplication import org.junit.Test import org.junit.Assert import java.lang.reflect.Method class FizzBuzzTest { private val fizzBuzzClass = FizzBuzzClass() @Test fun test1(){ var method : Method = fizzBuzzClass.javaClass.getDeclaredMethod("FizzBuzz",Int::class.java) method.isAccessible = true val answer = method.invoke(fizzBuzzClass,1) as String Assert.assertEquals(answer,"1") } @Test fun test2(){ var method : Method = fizzBuzzClass.javaClass.getDeclaredMethod("FizzBuzz",Int::class.java) method.isAccessible = true val answer = method.invoke(fizzBuzzClass,3) as String Assert.assertEquals(answer,"Buzz") } } |

コードの解説
methodにテスト対象のPrivateメソッドを格納した後に、method.isAccessible = true
を呼ぶことでアクセス可能にしています。
その後、 method.invoke()
の第一引数にテスト対象のメソッドを含むクラスのインスタンスを与え、 第二引数にメソッドの第一引数を与えます。
ここで、返り値であるStringに型を合わせるために as String
を利用していることに注意してください。
最後にAssertしてテストの実装が完了します。
自分のハマったところ
PrivateMethodかつ引数を取る場合は、getDeclaredMethdで,Int::class.javaなど第二引数を使わなければなりません。
これに気づかず1時間近く溶かしました。
もっと深く学びたい方は以下の参考文献を読むと良いです。
先人たちの貴重な知恵がたくさんあります。