概要
複数の引数を取り、組み合わせに応じて返す結果が何パターンもあるとき、
1つ1つテストを書いているとコード量が多くなってしまいます。
そこでParametrised Testを使います。
引数のパターン数だけ用意すれば、一つのメソッドをそのパターン数分だけテストしてくれる優れものです。
Android-Kotlinの単体テストにはJUnit5を使います。
JUnit5導入
build.gradle(トップレベル)
dependencies {
classpath "de.mannodermaus.gradle.plugins:android-junit5:1.4.2.0"
}
build.gradle(app)
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter:5.5.2'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.5.2'
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.5.2'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.5.2'
}
※注意: 自動でImportされないかも
私がJUnit5を試したときにはなぜかAndroidStudioに認識されずハマりました。。
Importを手動でやるとうまくいきます。
JUnit5の@ParameterizedTestがAndroidStudioで認識されない
テストを書く
REST APIを2つ叩いた結果を引数に加えて、使用可能な型リストを返すような関数:
UseCase.getSelectableTypeList()
をテストします。
APIレスポンスはJSON形式で返ってくるのでダミーで作り、data classに変換します。
引数の組み合わせをselectableTestCase
として定義しておき、テストで
@MethodSource("selectableTestCase")
を呼び出します。
テスト内で受け取った引数をdata classのvalueと差し替えて、
関数の返り値が期待通りか判定します。
import com.google.gson.Gson
import com.google.gson.JsonIOException
import com.google.gson.JsonSyntaxException
import jp.ucs.cardApp.domain.entity.auth.HogeResponse
import org.junit.jupiter.api.Assertions.*
import java.io.InputStreamReader
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.Arguments
import org.junit.jupiter.params.provider.Arguments.arguments
import org.junit.jupiter.params.provider.MethodSource
import java.util.stream.Stream
internal class HogeUseCase {
// data class
lateinit var hogeResponse: HogeResponse
lateinit var fugaResponse: FugaResponse
companion object {
const val HOGE_JSON = "{\"id\":\"2\",\"id\":\"3k3k02k\",\"aaaIdFlg\":\"0\",\"hogeFlg\":\"0\",\"cccFlg\":\"0\",\"dddState\":\"0\"}"
const val FUGA_JSON = "{\"beginingDate\":\"20211010\",\"endDate\":\"20210921\",\"hogeType\":\"2\",\"hogeNum\":\"0\",\"hogeAmount\":\"030\",\"fugaTypeFlg":\"0\",\"fugaAmount\":\"030\"}\n"
@JvmStatic
fun selectableTestCase(): Stream<Arguments> =
Stream.of(
// 引数の順番:fugaType id, hogeFlg, hogeType, fugaFlg, 期待値
arguments(FugaType.BANANA, "2", "1", "1", "1", Type.A),
arguments(FugaType.BANANA, "2", "0", "1", "1", Type.B),
arguments(FugaType.BANANA, "2", "0", "2", "2", Type.C),
arguments(FugaType.GORIRA, null, "0", "1", "1", Type.S),
arguments(FugaType.GORIRA, null, "0", "2", "2", Type.G),
arguments(FugaType.GORIRA, "1", "0", "1", "1", Type.S),
arguments(FugaType.GORIRA, "1", "0", "2", "2", Type.ELSE),
arguments(FugaType.GORIRA, "2", "0", "1", "1", Type.S),
arguments(FugaType.GORIRA, "2", "0", "2", "2", Type.ELSE),
)
}
@org.junit.jupiter.api.BeforeEach
fun setUp() {
// JSONをdata classにしておく
try {
hogeResponse = Gson().fromJson(
HOGE_JSON,
HogeResponse::class.java
)
fugaResponse = Gson().fromJson(
FUGA_JSON,
FugaResponse::class.java
)
} catch (e: JsonSyntaxException) {
e.printStackTrace()
} catch (e: JsonIOException) {
e.printStackTrace()
} finally {
}
}
// 予め定義しておいた引数たちをMethodSourceアノテーションで呼び出す
// 引数の数分このテストを回してくれる
@ParameterizedTest
@MethodSource("selectableTestCase")
fun getSelectableTypeList(
fugaType: FugaType,
id: String?,
hogeFlg: String,
hogeType: String,
fugaFlg: String,
expectedValue: List<Type>
) {
Pair(hogeResponse, fugaResponse).let {
val actual = UseCase.getSelectableTypeList(
fugaType,
// ダミーのdata classの中身を差し替える
it.first.copy(id = id, hogeFlg = hogeFlg),
it.second.copy(hogeType = hogeType, fugaFlg = fugaFlg)
)
assertEquals(expectedValue, actual)
}
}