如何在 Espresso 中测试 ActionMenuItemView 的图标
How to test ActionMenuItemView's icon in Espresso
我在操作栏中有一个按钮,其图标根据布尔值更改。我想检查使用了哪个可绘制资源。
这是更改图标的代码:
@Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
MenuItem item = menu.findItem(R.id.menu_favorite);
if(mIsFavorite)
item.setIcon(R.drawable.ab_icon_on);
else
item.setIcon(R.drawable.ab_icon_off);
}
需要更换图标时,菜单失效:
// request menu update
supportInvalidateOptionsMenu();
最后,我想检查结果的浓缩咖啡代码:
@Test
public void action_setUnsetFavorite() {
// check favorite off
onView(withImageDrawable(R.drawable.ab_icon_off))
.check(matches(isDisplayed()));
// click favorite button
onView(withId(R.id.menu_favorite))
.perform(click());
// check favorite on
onView(withImageDrawable(R.drawable.ab_icon_on))
.check(matches(isDisplayed()));
请注意,我使用的是找到的自定义匹配器 here。
我不能 100% 确定匹配器的工作原理以及这是否是最佳响应,但使用略有不同版本的方法肯定有效。
问题是当前的匹配器只适用于 ImageViews。 ActionMenuItemView 实际上是 textView 的子类,所以不会匹配,它也没有 getDrawable() 方法。
请注意,这仍然需要原始 post 中的 sameBitmap 方法。
public static Matcher<View> withActionIconDrawable(@DrawableRes final int resourceId) {
return new BoundedMatcher<View, ActionMenuItemView>(ActionMenuItemView.class) {
@Override
public void describeTo(final Description description) {
description.appendText("has image drawable resource " + resourceId);
}
@Override
public boolean matchesSafely(final ActionMenuItemView actionMenuItemView) {
return sameBitmap(actionMenuItemView.getContext(), actionMenuItemView.getItemData().getIcon(), resourceId);
}
};
}
@Barry Irvine 的回答很有帮助。只是想澄清是否有人想知道如何在 Espresso 测试中使用给定的 Matcher 方法。 (科特林)
步骤 1:从问题中提到的 link 创建一个新文件 CustomMatchers。
(包括sameBitmap
方法,但是,查看注释,修改了sameBitmap
方法)
您可以直接在您的测试文件中添加该方法,但将它添加到不同的文件中将有助于在您需要测试菜单项图标时重新使用它。
作为参考,这是我的 CustomMatchers
文件的样子
object CustomMatchers {
fun withActionIconDrawable(@DrawableRes resourceId: Int): Matcher<View?> {
return object : BoundedMatcher<View?, ActionMenuItemView>(ActionMenuItemView::class.java) {
override fun describeTo(description: Description) {
description.appendText("has image drawable resource $resourceId")
}
override fun matchesSafely(actionMenuItemView: ActionMenuItemView): Boolean {
return sameBitmap(
actionMenuItemView.context,
actionMenuItemView.itemData.icon,
resourceId,
actionMenuItemView
)
}
}
}
private fun sameBitmap(
context: Context,
drawable: Drawable?,
resourceId: Int,
view: View
): Boolean {
var drawable = drawable
val otherDrawable: Drawable? = context.resources.getDrawable(resourceId)
if (drawable == null || otherDrawable == null) {
return false
}
if (drawable is StateListDrawable) {
val getStateDrawableIndex =
StateListDrawable::class.java.getMethod(
"getStateDrawableIndex",
IntArray::class.java
)
val getStateDrawable =
StateListDrawable::class.java.getMethod(
"getStateDrawable",
Int::class.javaPrimitiveType
)
val index = getStateDrawableIndex.invoke(drawable, view.drawableState)
drawable = getStateDrawable.invoke(drawable, index) as Drawable
}
val bitmap = getBitmapFromDrawable(context, drawable)
val otherBitmap = getBitmapFromDrawable(context, otherDrawable)
return bitmap.sameAs(otherBitmap)
}
private fun getBitmapFromDrawable(context: Context?, drawable: Drawable): Bitmap {
val bitmap: 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
} }
第 2 步:在测试中使用匹配器
onView(withId(R.id.menu_item_id))
.check(matches(CustomMatchers.withActionIconDrawable(R.drawable.ic_favorite_border)))
我在操作栏中有一个按钮,其图标根据布尔值更改。我想检查使用了哪个可绘制资源。
这是更改图标的代码:
@Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
MenuItem item = menu.findItem(R.id.menu_favorite);
if(mIsFavorite)
item.setIcon(R.drawable.ab_icon_on);
else
item.setIcon(R.drawable.ab_icon_off);
}
需要更换图标时,菜单失效:
// request menu update
supportInvalidateOptionsMenu();
最后,我想检查结果的浓缩咖啡代码:
@Test
public void action_setUnsetFavorite() {
// check favorite off
onView(withImageDrawable(R.drawable.ab_icon_off))
.check(matches(isDisplayed()));
// click favorite button
onView(withId(R.id.menu_favorite))
.perform(click());
// check favorite on
onView(withImageDrawable(R.drawable.ab_icon_on))
.check(matches(isDisplayed()));
请注意,我使用的是找到的自定义匹配器 here。
我不能 100% 确定匹配器的工作原理以及这是否是最佳响应,但使用略有不同版本的方法肯定有效。
问题是当前的匹配器只适用于 ImageViews。 ActionMenuItemView 实际上是 textView 的子类,所以不会匹配,它也没有 getDrawable() 方法。
请注意,这仍然需要原始 post 中的 sameBitmap 方法。
public static Matcher<View> withActionIconDrawable(@DrawableRes final int resourceId) {
return new BoundedMatcher<View, ActionMenuItemView>(ActionMenuItemView.class) {
@Override
public void describeTo(final Description description) {
description.appendText("has image drawable resource " + resourceId);
}
@Override
public boolean matchesSafely(final ActionMenuItemView actionMenuItemView) {
return sameBitmap(actionMenuItemView.getContext(), actionMenuItemView.getItemData().getIcon(), resourceId);
}
};
}
@Barry Irvine 的回答很有帮助。只是想澄清是否有人想知道如何在 Espresso 测试中使用给定的 Matcher 方法。 (科特林)
步骤 1:从问题中提到的 link 创建一个新文件 CustomMatchers。
(包括sameBitmap
方法,但是,查看注释,修改了sameBitmap
方法)
您可以直接在您的测试文件中添加该方法,但将它添加到不同的文件中将有助于在您需要测试菜单项图标时重新使用它。
作为参考,这是我的 CustomMatchers
文件的样子
object CustomMatchers {
fun withActionIconDrawable(@DrawableRes resourceId: Int): Matcher<View?> {
return object : BoundedMatcher<View?, ActionMenuItemView>(ActionMenuItemView::class.java) {
override fun describeTo(description: Description) {
description.appendText("has image drawable resource $resourceId")
}
override fun matchesSafely(actionMenuItemView: ActionMenuItemView): Boolean {
return sameBitmap(
actionMenuItemView.context,
actionMenuItemView.itemData.icon,
resourceId,
actionMenuItemView
)
}
}
}
private fun sameBitmap(
context: Context,
drawable: Drawable?,
resourceId: Int,
view: View
): Boolean {
var drawable = drawable
val otherDrawable: Drawable? = context.resources.getDrawable(resourceId)
if (drawable == null || otherDrawable == null) {
return false
}
if (drawable is StateListDrawable) {
val getStateDrawableIndex =
StateListDrawable::class.java.getMethod(
"getStateDrawableIndex",
IntArray::class.java
)
val getStateDrawable =
StateListDrawable::class.java.getMethod(
"getStateDrawable",
Int::class.javaPrimitiveType
)
val index = getStateDrawableIndex.invoke(drawable, view.drawableState)
drawable = getStateDrawable.invoke(drawable, index) as Drawable
}
val bitmap = getBitmapFromDrawable(context, drawable)
val otherBitmap = getBitmapFromDrawable(context, otherDrawable)
return bitmap.sameAs(otherBitmap)
}
private fun getBitmapFromDrawable(context: Context?, drawable: Drawable): Bitmap {
val bitmap: 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
} }
第 2 步:在测试中使用匹配器
onView(withId(R.id.menu_item_id))
.check(matches(CustomMatchers.withActionIconDrawable(R.drawable.ic_favorite_border)))