カスタムマッチ
前回の記事AndroidX Espresso Matcher分析でMatcherがどのように動作するか、コード分析をしました。
今回はCustom Matcherを直接実装してみます。理解を助けるためにTextViewのtextを比較するCustom Matcherを実装してみます。
ViewMatchers.withText()
と同じ機能をします。
デフォルトのプロジェクトのコードは、GitHubからダウンロードしてください。 Android EspressoにUIテスト(1)文で使用したサンプルコードです。
実装
androidTestフォルダにCustomMatcher.ktを生成し、次のコードを入力してください。
withText()
の引数としてStringまたはResourceIdが配信されることがありますので、
二つをそれぞれ異なる方法で処理することができるようにTextStringMatcherとTextResourceMatcherクラスを生成しました。
Stringの場合 Matcher<String>
に変換して、既に実装されてロジックで処理し、ResourceIdの場合Stringを持ってきて、直接equals()
で比較するように実装した。
object CustomMatcher {
fun withText(substring: String): Matcher<View> {
return withText(`is`(substring))
}
fun withText(resourceId: Int): Matcher<View> {
return TextResourceMatcher(resourceId)
}
private fun withText(stringMatcher: Matcher<String>): Matcher<View> {
checkNotNull(stringMatcher)
return TextStringMatcher(stringMatcher)
}
private class TextStringMatcher(private val stringMatcher: Matcher<String>)
: BoundedMatcher<View, TextView>(TextView::class.java) {
public override fun matchesSafely(view: TextView): Boolean {
val text: String = view.text.toString()
return text != null && stringMatcher.matches(text)
}
override fun describeTo(description: Description) {
description.appendText("with text: ")
stringMatcher.describeTo(description)
}
}
private class TextResourceMatcher(private val resourceId: Int)
: BoundedMatcher<View, TextView>(TextView::class.java) {
private var expectedText: String? = null
public override fun matchesSafely(view: TextView): Boolean {
expectedText = view.resources.getString(resourceId)
val actualText: String = view.text.toString()
return actualText != null && actualText.equals(expectedText)
}
override fun describeTo(description: Description) {
if (expectedText != null) {
description.appendText("with text: $expectedText")
}
}
}
}
Custom Matcherがよく作成されたテストコードを作成してみましょう。 次のコードのように、最初に引数としてStringを直接転送し、その次には、ResourceIdを引数として伝えました。
テストを実行してみると、すべてのパスしました。
細かいバグがあるか分からないが、 ViewMatchers.withText()
と同じ機能をするCustom Matcherが完成しました!
@RunWith(AndroidJUnit4::class)
@LargeTest
class CustomMatcherTest {
@Rule
@JvmField
var activityRule = ActivityTestRule(LocaleActivity::class.java)
@Test
fun noCountryExtra() {
activityRule.launchActivity(Intent())
Espresso.onView(withId(R.id.tvLocale))
.check(matches(CustomMatcher.withText("No country string")))
Espresso.onView(withId(R.id.tvLocale))
.check(matches(CustomMatcher.withText(R.string.no_country_extra)))
}
}
まとめ
AndroidX Espresso Matcher分析でMatcherのコードを分析し見て、今回はCustom Matcherを作成しました。 基本的なMatcherは既に作られているので、追加で作成があまりないようです。エスプレッソの内部構造を理解するのに役に立てば幸いです。
参考
Related Posts
- Android - FusedLocationProviderClientに位置情報を取得する
- Android - GPS、Network位置情報を取得する(LocationManager)
- Android - adbコマンドでActivity実行
- アンドロイド - MediaStoreにメディアファイルを保存する方法
- Android - Runtime permissionリクエスト方法と例(kotlin)
- Android11 - Storage(ストレージ)の変更まとめ
- Jetpack Compose - RowとColumn
- Android 13 - 細かいメディアファイルの権限
- Android 13でNotification権限をリクエスト、通知を表示する
- エラー解決:android gradle plugin requires java 11 to run. you are currently using java 1.8.
- Query method parameters should either be a type that can be converted into a database column or a List
- Android - TabLayoutの実装方法(+ ViewPager2)
- Android - adbコマンドで特定のパッケージのプロセスの終了
- Android - adb push、pullでファイルのコピー、ダウンロード
- Android - adbコマンドでsettings value確認、変更、
- Android 12 - IntentFilterのexported明示的な宣言
- Android - adb logcatコマンドでログ出力
- Android - ACTION_BOOT_COMPLETEDイベント受信
- Android - Foreground Service実行
- Android - ファイル入出力の例(Read、Write、内部、外部ストレージ)
- Android - アプリの権限を確認(Permission check)
- Android - adbで実行中のプロセス、スレッドリスト及びメモリ情報の確認
- Android - Broadcast Receiver登録およびイベントの受信方法
- Android - Cleartext HTTP ... not permitted例外解決方法
- Androidのビルドエラー - Calls to Java default methods are prohibited in JVM target 1.6
- アンドロイド - Assetsでファイルを読み取る方法
- アンドロイドのさまざまなNotification種類と実装方法
- アンドロイド - INSTALL_FAILED_TEST_ONLYエラー解決方法
- Android EspressoのCustom Matcher実装方法
- Android Espressoを使用してUIをテストする方法(3)
- アンドロイド - CTS hostsideをgradleで構築する方法
- Androidのアプリのデータフォルダーのパスと内部/外部ストレージ説明
- アンドロイド - 最初のApp作成
- Androidをインストールする方法(Windows)