Espresso 在自定义视图中找不到文本
Espresso not finding text inside of Custom View
假设我有一个从头开始构建的自定义视图,如下所示:
class CustomTextView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
defStyleRes: Int = 0
) : View(context, attrs, defStyleAttr, defStyleRes) {
private val paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
style = Paint.Style.FILL_AND_STROKE
textSize = 48f
color = Color.BLUE
strokeWidth = 3f
}
override fun onDraw(canvas: Canvas?) {
canvas?.drawText("Text from Custom view", width / 2f, height / 2f, paint)
}
}
这是 Canvas 上非常简单的绘图文本。在片段布局中,我添加了一个 TextView 和我的 CustomText 视图,如下所示:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="32dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text from Text View" />
<com.example.testing.views.CustomTextView
android:layout_width="250dp"
android:layout_height="32dp"
android:layout_marginTop="10dp" />
</LinearLayout
我的浓缩咖啡测试文件如下所示:
@RunWith(AndroidJUnit4::class)
class MyFragmentTest {
private lateinit var scenario: FragmentScenario<MyFragment>
@Before
fun setup() {
scenario = launchFragmentInContainer(themeResId = R.style.Theme_Testing)
scenario.moveToState(Lifecycle.State.STARTED)
}
@Test
fun testNormalTextView() { // -> PASSED
onView(withText("Text from Text View")).check(matches(isDisplayed()))
}
@Test
fun testCustomTextView() { // -> FAILED NoMatchingView Exception
onView(withText("Text from Custom View")).check(matches(isDisplayed()))
}
}
当我 运行 在我的物理设备上进行测试时,它仅通过 testNormalTextView
但在 testCustomTextView
上失败了。如何使用自定义视图使这些 Espresso 测试通过?
根据官方文档,withText()
viewMatcher 与 Textviews 一起使用。
Returns a matcher that matches TextView based on its text property value.
在您的情况下,您的自定义视图正在扩展 View
class。
以下是我建议的两种方式。
- 使您的自定义视图扩展 TextView。 [如果您的要求是仅访问具有特定文本的视图,而不管它的 id]
- 使用
withId()
viewMatcher 而不是 withText()
,传递在 xml 布局中给定的自定义视图的 ID。您需要在 xml 中为您的自定义视图提供 id。 [如果你想检查具有特定 ID 的视图,而不是它包含的文本]
在你的xml
<com.example.testing.views.CustomTextView
android:id="@+id/my_custom_view"
android:layout_width="250dp"
android:layout_height="32dp"
android:layout_marginTop="10dp" />
在你的测试函数中
@Test
fun testCustomTextView() {
onView(withId(R.id.my_custom_view)).check(matches(isDisplayed()))
}
更新:
对于 recyclerview,您可以使用 onData()
而不是 onView()
在参数中传递匹配器。
您可以找到有关测试的更多信息 adapterViews
here
假设我有一个从头开始构建的自定义视图,如下所示:
class CustomTextView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
defStyleRes: Int = 0
) : View(context, attrs, defStyleAttr, defStyleRes) {
private val paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
style = Paint.Style.FILL_AND_STROKE
textSize = 48f
color = Color.BLUE
strokeWidth = 3f
}
override fun onDraw(canvas: Canvas?) {
canvas?.drawText("Text from Custom view", width / 2f, height / 2f, paint)
}
}
这是 Canvas 上非常简单的绘图文本。在片段布局中,我添加了一个 TextView 和我的 CustomText 视图,如下所示:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="32dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text from Text View" />
<com.example.testing.views.CustomTextView
android:layout_width="250dp"
android:layout_height="32dp"
android:layout_marginTop="10dp" />
</LinearLayout
我的浓缩咖啡测试文件如下所示:
@RunWith(AndroidJUnit4::class)
class MyFragmentTest {
private lateinit var scenario: FragmentScenario<MyFragment>
@Before
fun setup() {
scenario = launchFragmentInContainer(themeResId = R.style.Theme_Testing)
scenario.moveToState(Lifecycle.State.STARTED)
}
@Test
fun testNormalTextView() { // -> PASSED
onView(withText("Text from Text View")).check(matches(isDisplayed()))
}
@Test
fun testCustomTextView() { // -> FAILED NoMatchingView Exception
onView(withText("Text from Custom View")).check(matches(isDisplayed()))
}
}
当我 运行 在我的物理设备上进行测试时,它仅通过 testNormalTextView
但在 testCustomTextView
上失败了。如何使用自定义视图使这些 Espresso 测试通过?
根据官方文档,withText()
viewMatcher 与 Textviews 一起使用。
Returns a matcher that matches TextView based on its text property value.
在您的情况下,您的自定义视图正在扩展 View
class。
以下是我建议的两种方式。
- 使您的自定义视图扩展 TextView。 [如果您的要求是仅访问具有特定文本的视图,而不管它的 id]
- 使用
withId()
viewMatcher 而不是withText()
,传递在 xml 布局中给定的自定义视图的 ID。您需要在 xml 中为您的自定义视图提供 id。 [如果你想检查具有特定 ID 的视图,而不是它包含的文本]
在你的xml
<com.example.testing.views.CustomTextView
android:id="@+id/my_custom_view"
android:layout_width="250dp"
android:layout_height="32dp"
android:layout_marginTop="10dp" />
在你的测试函数中
@Test
fun testCustomTextView() {
onView(withId(R.id.my_custom_view)).check(matches(isDisplayed()))
}
更新:
对于 recyclerview,您可以使用 onData()
而不是 onView()
在参数中传递匹配器。
您可以找到有关测试的更多信息 adapterViews
here