我是Espresso测试的新手,但似乎没有办法测试可绘制的更改。
我有一个教程是ImageView
Drawable
幻灯片,隐藏在'半透明的TextView
。在我的测试中,我想确保在按下下一个按钮时,已在教程Drawable
中插入了正确的ImageView
。
没有默认Matcher
来检查Drawable
,所以我开始使用https://stackoverflow.com/a/28785178/981242编写自己的ImageView
。很遗憾,由于无法检索Drawable
的有效matchesSafely()
的ID,我无法完成Drawable
实施。
这不是测试活跃-movflags empty_moov+default_base_moof
的唯一用例。人们通常在这种情况下使用的工具是什么?
答案 0 :(得分:10)
我不想比较位图,而是遵循这个答案的建议:https://stackoverflow.com/a/14474954/1396068
设置图像视图的drawable时,还会将可绘制ID存储在其setTag(R.drawable.your_drawable)
的标记中。然后使用Espresso的withTagValue(equalTo(R.drawable.your_drawable))
匹配器检查正确的标记。
答案 1 :(得分:9)
请查看我找到的本教程。 似乎工作得很好https://medium.com/@dbottillo/android-ui-test-espresso-matcher-for-imageview-1a28c832626f#.4snjg8frw
以下是复制意大利面的摘要; - )
public class DrawableMatcher extends TypeSafeMatcher<View> {
private final int expectedId;
String resourceName;
public DrawableMatcher(int expectedId) {
super(View.class);
this.expectedId = expectedId;
}
@Override
protected boolean matchesSafely(View target) {
if (!(target instanceof ImageView)){
return false;
}
ImageView imageView = (ImageView) target;
if (expectedId < 0){
return imageView.getDrawable() == null;
}
Resources resources = target.getContext().getResources();
Drawable expectedDrawable = resources.getDrawable(expectedId);
resourceName = resources.getResourceEntryName(expectedId);
if (expectedDrawable == null) {
return false;
}
Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
Bitmap otherBitmap = ((BitmapDrawable) expectedDrawable).getBitmap();
return bitmap.sameAs(otherBitmap);
}
@Override
public void describeTo(Description description) {
description.appendText("with drawable from resource id: ");
description.appendValue(expectedId);
if (resourceName != null) {
description.appendText("[");
description.appendText(resourceName);
description.appendText("]");
}
}
}
请注意,这只适用于Drawable
为BitmapDrawable
的情况。如果您还有VectorDrawable
或其他Drawable
,则必须检查此内容(imageView.getDrawable() instanceOf XXXDrawable
)并从中获取位图。除了你有一些简单的Drawable,你只需要一种颜色就可以进行比较。
要获取VectorDrawable的位图,例如你必须将VectorDrawable绘制到画布并将其保存到位图(当VectorDrawable着色时我遇到了一些麻烦)。 如果你有一个StateListDrawable,你可以得到所选状态的Drawable并重复你的if instanceOf级联。 对于其他Drawable类型,我没有任何经验,抱歉!
答案 2 :(得分:6)
有一个要点包含来自Frankie Sardo的withBackground()
,withCompoundDrawable()
,withImageDrawable()
匹配器。所有归功于他。
关于图像ID - 您可以键入R.drawable.image_name
,然后将自动检索drawable的ID。
答案 3 :(得分:3)
基于@wolle和@FreewheelNat的帮助,用于比较(Vector)Drawable:
public static Matcher<View> withDrawableId(@DrawableRes final int id) {
return new DrawableMatcher(id);
}
public static class DrawableMatcher extends TypeSafeMatcher<View> {
private final int expectedId;
private String resourceName;
public DrawableMatcher(@DrawableRes int expectedId) {
super(View.class);
this.expectedId = expectedId;
}
@Override
protected boolean matchesSafely(View target) {
if (!(target instanceof ImageView)) {
return false;
}
ImageView imageView = (ImageView) target;
if (expectedId < 0) {
return imageView.getDrawable() == null;
}
Resources resources = target.getContext().getResources();
Drawable expectedDrawable = resources.getDrawable(expectedId);
resourceName = resources.getResourceEntryName(expectedId);
if (expectedDrawable != null && expectedDrawable.getConstantState() != null) {
return expectedDrawable.getConstantState().equals(
imageView.getDrawable().getConstantState()
);
} else {
return false;
}
}
@Override
public void describeTo(Description description) {
description.appendText("with drawable from resource id: ");
description.appendValue(expectedId);
if (resourceName != null) {
description.appendText("[");
description.appendText(resourceName);
description.appendText("]");
}
}
}
答案 4 :(得分:1)
这是@drakeet答案的Kotlin版本,并做了一些修改。
class DrawableMatcher(private val targetContext: Context,
@param:DrawableRes private val expectedId: Int) : TypeSafeMatcher<View>(View::class.java) {
override fun matchesSafely(target: View): Boolean {
val drawable: Drawable? = when(target) {
is ActionMenuItemView -> target.itemData.icon
is ImageView -> target.drawable
else -> null
}
requireNotNull(drawable)
val resources: Resources = target.context.resources
val expectedDrawable: Drawable? = resources.getDrawable(expectedId, targetContext.theme)
return expectedDrawable?.constantState?.let { it == drawable.constantState } ?: false
}
override fun describeTo(description: Description) {
description.appendText("with drawable from resource id: $expectedId")
targetContext.resources.getResourceEntryName(expectedId)?.let { description.appendText("[$it]") }
}
}
答案 5 :(得分:0)
我接受@wolle的答案是有效的,但我想承认,即使对于Java,它甚至可以更简单。它可以转换为static function
(或Kotlin中的companion
)并清除一些已弃用的代码。
无论如何,Kotlin的代码压缩 - 不推荐使用的解决方案是这样的:
fun drawableIsCorrect(@DrawableRes drawableResId: Int): Matcher<View> {
return object : TypeSafeMatcher<View>() {
override fun describeTo(description: Description) {
description.appendText("with drawable from resource id: ")
description.appendValue(drawableResId)
}
override fun matchesSafely(target: View?): Boolean {
if (target !is ImageView) {
return false
}
if (drawableResId < 0) {
return target.drawable == null
}
val expectedDrawable = ContextCompat.getDrawable(target.context, drawableResId)
?: return false
val bitmap = (target.drawable as BitmapDrawable).bitmap
val otherBitmap = (expectedDrawable as BitmapDrawable).bitmap
return bitmap.sameAs(otherBitmap)
}
}
}
22行vs 44,嗯?
答案 6 :(得分:0)
我已经在这里回答了类似的话题:Get the ID of a drawable in ImageView。
该方法基于在自定义LayoutInflater
中使用指定的资源ID标记视图。整个过程由一个简单的库TagView自动完成。它对于Espresso测试尤其方便,因为您无需手动标记项目中的每个视图。实际上,除了在运行时设置一些drawable之外,您不需要更改任何内容。在这种情况下,您需要查看Tagging in runtime部分。
因此,您可以仅通过ID来比较两个drawable:
onView(withId(R.id.imageview)).check(assertTagKeyValue(
ViewTag.IMAGEVIEW_SRC.id, android.R.drawable.ic_media_play));
自定义Espresso声明assertTagKeyValue
可用here