2018年3月27日火曜日

Android で Parameterized テスト(JUnit4, Robolectric)を行う

JUnit4

https://github.com/googlesamples/android-testing/tree/master/runner/AndroidJunitRunnerSample
にサンプルがあります。

具体的には CalculatorAddParameterizedTest.java がテストクラスで、
テスト対象のクラスは Calculator.java です。

上記のサンプルを見ればだいたいわかるのですが、Kotlinで書いた以下のFizzBazzをテストしてみたいと思います。
  1. class FizzBazz {  
  2.   
  3.     fun fizzbazz(value: Int): String {  
  4.         return when {  
  5.             value % 15 == 0 -> "fizzbazz"  
  6.             value % 3 == 0 -> "fizz"  
  7.             value % 5 == 0 -> "bazz"  
  8.             else -> value.toString()  
  9.         }  
  10.     }  
  11. }  

  • 1. テストクラスに @RunWith アノテーションで Parameterized を指定する。
  • 2. Parameterized テストで使う値をコンストラクタの引数として受け取り保持する。
  • 3. @Parameters アノテーションをつけた static メソッドを用意する(つまり @JvmStatic が必要)。このメソッドではコンストラクタ引数に対応した値の配列のIterableを返す。
  • 4. 保持した値を使ってテストする。
  1. /** 
  2.  * @RunWith で Parameterized を指定する 
  3.  * 
  4.  * Parameterized テストで使う値をコンストラクタの引数として受け取る 
  5.  * ここでは fizzbazz() に渡す値と、fizzbazz()の戻り値の期待値の2つを引数として受け取る 
  6.  */  
  7. @RunWith(Parameterized::class)  
  8. class FizzBazzParameterizedTest(  
  9.         private val value: Int,  
  10.         private val expected: String  
  11. ) {  
  12.   
  13.     private lateinit var fizzBazz: FizzBazz  
  14.   
  15.     @Before  
  16.     fun setUp() {  
  17.         fizzBazz = FizzBazz()  
  18.     }  
  19.   
  20.     @Test  
  21.     fun testFizzBazz() {  
  22.         assertThat(fizzBazz.fizzbazz(value)).isEqualTo(expected)  
  23.     }  
  24.   
  25.     companion object {  
  26.   
  27.         /** 
  28.          * @Parameters と @JvmStatic をつける 
  29.          * @return [Iterable] コンストラクタに渡す値のIterableを返す 
  30.          */  
  31.         @Parameters  
  32.         @JvmStatic  
  33.         fun data(): Iterable<Array<Any>> {  
  34.             return listOf(  
  35.                     arrayOf(1"1"),  
  36.                     arrayOf(2"2"),  
  37.                     arrayOf(3"fizz"),  
  38.                     arrayOf(4"4"),  
  39.                     arrayOf(5"bazz"),  
  40.                     arrayOf(15"fizzbazz")  
  41.             )  
  42.         }  
  43.     }  
  44. }  


テスト結果




Robolectric

BlockJUnit4ClassRunnerWithParameters を継承した Runner であれば、@Parameterized.UseParametersRunnerFactory でその Runner を返す ParametersRunnerFactory を指定することで、その Runner で Parameterized テストを実行することができます。

RobolectricTestRunner は SandboxTestRunner を継承しているためこの方法は使えません。 代わりに Robolectric には ParameterizedRobolectricTestRunner が用意されています。


TextUtils を使った次の EmptyChecker をテストしてみます。
  1. class EmptyChecker {  
  2.   
  3.     fun isEmpty(value: String?): Boolean {  
  4.         return TextUtils.isEmpty(value)  
  5.     }  
  6. }  
使い方は Parameterized とほぼ同じです。
違いは @RunWith に ParameterizedRobolectricTestRunner を指定することと、@ParameterizedRobolectricTestRunner.Parameters を使うことです。
  1. /** 
  2.  * @RunWith で ParameterizedRobolectricTestRunner を指定する 
  3.  * 
  4.  * Parameterized テストで使う値をコンストラクタの引数として受け取る 
  5.  * ここでは isEmpty() に渡す値と、isEmpty()の戻り値の期待値の2つを引数として受け取る 
  6.  */  
  7. @RunWith(ParameterizedRobolectricTestRunner::class)  
  8. class EmptyCheckerParameterizedTest(  
  9.         private val value: String?,  
  10.         private val expected: Boolean  
  11. ) {  
  12.   
  13.     private lateinit var emptyChecker: EmptyChecker  
  14.   
  15.     @Before  
  16.     fun setUp() {  
  17.         emptyChecker = EmptyChecker()  
  18.     }  
  19.   
  20.     @Test  
  21.     fun testFizzBazz() {  
  22.         assertThat(emptyChecker.isEmpty(value)).isEqualTo(expected)  
  23.     }  
  24.   
  25.     companion object {  
  26.   
  27.         /** 
  28.          * @ParameterizedRobolectricTestRunner.Parameters と @JvmStatic をつける 
  29.          * @return [Iterable] コンストラクタに渡す値のIterableを返す 
  30.          */  
  31.         @ParameterizedRobolectricTestRunner.Parameters  
  32.         @JvmStatic  
  33.         fun data(): Iterable<Array<Any?>> {  
  34.             return listOf(  
  35.                     arrayOf<Any?>(nulltrue),  
  36.                     arrayOf<Any?>(""true),  
  37.                     arrayOf<Any?>("a"false)  
  38.             )  
  39.         }  
  40.     }  
  41. }  


テスト結果




0 件のコメント:

コメントを投稿