UI 테스트에서 다음과 같은 테스트가 필요할 때가 있습니다.
- 어떤 이벤트가 발생되었을 때 ImageView의 Source 즉 Drawable이 변경되었는지 확인
위 경우와 같은 ImageView의 테스트는 Espresso 라이브러리가 지원해지지 않기 때문에 아래와 같은 유틸 클래스가 필요합니다.
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.drawable.Drawable
import android.view.View
import android.widget.ImageView
import org.hamcrest.Description
import org.hamcrest.TypeSafeMatcher
class DrawableMatcher internal constructor(private val expectedId: Int) :
TypeSafeMatcher<View?>(View::class.java) {
private var resourceName: String? = null
override fun matchesSafely(target: View?): Boolean {
if (target !is ImageView) {
return false
}
val imageView = target
if (expectedId == EMPTY) {
return imageView.drawable == null
}
if (expectedId == ANY) {
return imageView.drawable != null
}
val resources = target.getContext().resources
val expectedDrawable = resources.getDrawable(
expectedId
)
resourceName = resources.getResourceEntryName(expectedId)
if (expectedDrawable == null) {
return false
}
val bitmap = getBitmap(imageView.drawable)
val otherBitmap = getBitmap(expectedDrawable)
return bitmap.sameAs(otherBitmap)
}
private fun getBitmap(drawable: Drawable): Bitmap {
val bitmap = Bitmap.createBitmap(
drawable.intrinsicWidth,
drawable.intrinsicHeight,
Bitmap.Config.ARGB_8888
)
val canvas = Canvas(bitmap)
drawable.setBounds(0, 0, canvas.width, canvas.height)
drawable.draw(canvas)
return bitmap
}
override fun describeTo(description: Description) {
description.appendText("with drawable from resource id: ")
description.appendValue(expectedId)
if (resourceName != null) {
description.appendText("[")
description.appendText(resourceName)
description.appendText("]")
}
}
companion object {
const val EMPTY = -1
const val ANY = -2
}
}
object EspressoTestsMatchers {
fun withDrawable(resourceId: Int): DrawableMatcher {
return DrawableMatcher(resourceId)
}
fun noDrawable(): DrawableMatcher {
return DrawableMatcher(DrawableMatcher.EMPTY)
}
fun hasDrawable(): DrawableMatcher {
return DrawableMatcher(DrawableMatcher.ANY)
}
}
그 다음 아래와 같이 테스트파일을 작성해서 테스트 할 수 있습니다.
@RunWith(AndroidJUnit4::class)
class FlashlightActivityTest {
@Rule
@JvmField
val activityRule = ActivityScenarioRule(
FlashlightActivity::class.java
)
@Test
fun testFlashlightButtonVisibility() {
Espresso.onView(ViewMatchers.withId(R.id.flashlightButton))
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()));
}
@Test
fun testFlashlightButtonToggle() {
val scenario = activityRule.scenario
var viewModel: FlashlightViewModel? = null
scenario.onActivity { activity ->
viewModel = ViewModelProvider(activity).get(FlashlightViewModel::class.java)
}
viewModel?.turnOffFlashlight()
onView(withId(R.id.flashlightButton)).check(matches(withDrawable(R.drawable.off_button)));
}
}
위 테스트의 testFlashlightButtonToggle()에서 viewModel을 이용해서 ImageView의 Source가 변경되었는지 확인할 수 있습니다.
https://medium.com/@dbottillo/android-ui-test-espresso-matcher-for-imageview-1a28c832626f
Android UI Test — Espresso Matcher for ImageView
EDIT: this post has been update to support Vector drawables, thanks to Enrico Gueli
medium.com
https://devtut.github.io/android/testing-ui-with-espresso.html#espresso-simple-ui-test
Android - Testing UI with Espresso
Espresso simple UI test, Overall Espresso, Open Close DrawerLayout , Set Up Espresso, Performing an action on a view, Finding a view with onView, Create Espresso Test Class, Up Navigation, Espresso custom matchers, Group a collection of test classes in a t
devtut.github.io
'Android > UI Test' 카테고리의 다른 글
[Android] UI 테스트 -1 (0) | 2023.09.26 |
---|---|
[Android] UI 테스트란? (0) | 2023.09.26 |