背景
RecyclerViewのUIテストを作ろうとすると、どうしても標準APIでは満たせないテスト項目が出てきます。
https://qiita.com/AAkira/items/26ee7b18b11635cfc621 を参考にさせていただき、独自のRecyclerViewMatcher
を作成しました。
下記の項目ではそれぞれバラバラに記載していますが、全てのメソッドは1つのRecyclerViewMatcher
の中に定義されています。
実装
【isExist】RecyclerViewの指定した位置に、指定したViewHolderが存在すること
RecyclerViewMatcher.kt
object RecyclerViewMatcher {
inline fun <reified T : RecyclerView.ViewHolder> isExist(position: Int) = object : TypeSafeMatcher<View>() {
override fun describeTo(description: Description) {
description.appendText("RecyclerViewの指定した位置に、指定したViewHolderが存在すること")
}
override fun matchesSafely(view: View): Boolean {
if (view !is RecyclerView) return false
return view.findViewHolderForAdapterPosition(position) is T
}
}
}
【contains】RecyclerViewの指定した範囲内に、指定したViewHolderが存在すること
RecyclerViewMatcher.kt
object RecyclerViewMatcher {
inline fun <reified T : RecyclerView.ViewHolder> contains(range: IntRange) = object : TypeSafeMatcher<View>() {
override fun describeTo(description: Description) {
description.appendText("RecyclerViewの指定した範囲内に、指定したViewHolderが存在すること")
}
override fun matchesSafely(view: View): Boolean {
if (view !is RecyclerView) return false
return range.any { position ->
view.findViewHolderForAdapterPosition(position) is T
}
}
}
}
【isVisible】RecyclerViewの指定した位置のViewHolderに、指定したViewが表示されていること
RecyclerViewMatcher.kt
object RecyclerViewMatcher {
inline fun <reified T : RecyclerView.ViewHolder> isVisible(position: Int, @IdRes id: Int) = object : TypeSafeMatcher<View>() {
override fun describeTo(description: Description) {
description.appendText("RecyclerViewの指定した位置のViewHolderに、指定したViewが表示されていること")
}
override fun matchesSafely(view: View): Boolean {
if (view !is RecyclerView) return false
val viewHolder = view.findViewHolderForAdapterPosition(position) as? T ?: return false
return viewHolder.itemView.findViewById<View>(id)?.visibility == View.VISIBLE
}
}
}