我有一个Instrument测试,其中包含四个match语句。四个语句中的一个在与其他三个语句一起运行时会失败,但是如果它本身运行则通过。
这是测试失败的
@Test
fun displayTypeFilteredPokemon(){
// When - PokemonList fragment launch and filtered by specific type
launchActivity()
onView(withId(R.id.genAllButton)).perform(click())
// Perform click action to do the filter on specific type
onView(withId(R.id.menu_filter)).perform(click())
onView(withText(R.string.label_type_electric)).perform(click())
// Then - Verify the list is filtered by the selected type
onView(withId(R.id.pokemon_list)).check(RecyclerViewItemCountAssertion(3))
onView(withText("Magnemite")).check(matches(isDisplayed()))
onView(withText("Jolteon")).check(matches(isDisplayed()))
onView(withText("Emolga")).check(matches(isDisplayed()))
}
这是启动活动的代码:
private fun launchActivity(): ActivityScenario<PokemonListActivity>? {
val scenario = launch(PokemonListActivity::class.java)
scenario.onActivity {
val intent = Intent()
intent.putExtra("genId",0)
it.intent = intent
}
return scenario
}
这是自定义匹配器代码:
class RecyclerViewItemCountAssertion(private val matcher: Int) : ViewAssertion {
override fun check(view: View?, noViewFoundException: NoMatchingViewException?) {
if(noViewFoundException != null){
throw noViewFoundException
}
val recyclerView = view as RecyclerView
val adapter = recyclerView.adapter!!
assertThat(adapter.itemCount, IsEqual(matcher))
}
}
使用这组匹配项时,它会通过:
onView(withId(R.id.pokemon_list)).check(RecyclerViewItemCountAssertion(3))
onView(withText("Jolteon")).check(matches(isDisplayed()))
onView(withText("Emolga")).check(matches(isDisplayed()))
或当这组匹配项也通过时:
onView(withText("Magnemite")).check(matches(isDisplayed()))
这是正在测试的视图:
我有点困惑,因为视图中显然有匹配的文本。资源可能没有闲置,因此测试刚刚结束?例如,只有一个匹配器通过的测试是由于速度足够快才能在完成之前匹配?
我曾经考虑过引入EspressoIdlingResource,但是我读过它在代码库中引入了一些困难,并且我希望出于学习目的而使其简单。
我认为竞赛条件是一个问题的另一个指标是,当我调试测试通过时。当我刚运行测试时,它失败了。
编辑1: 单独运行所有测试时,我没有任何错误。在该类中运行所有测试时,出现以下错误:
androidx.test.espresso.NoMatchingViewException: No views in hierarchy found matching: with id: com.stegner.androiddex:id/menu_filter
答案 0 :(得分:1)
您编写浓缩咖啡测试的方法似乎是错误的。
在编写UI测试时,我们要确认的是以下内容。 “如果用户进行交互,请单击按钮X,然后滑动页面,将500写入此编辑文本,然后单击按钮Y,他将能够看到文本Z”。 如您所见,我们正在测试应用程序,就像我们是最终用户一样,只需与屏幕上看到的元素进行交互即可。
private fun launchActivity(): ActivityScenario<PokemonListActivity>? {
val scenario = launch(PokemonListActivity::class.java)
scenario.onActivity {
val intent = Intent()
intent.putExtra("genId",0)
it.intent = intent
}
return scenario
}
当您使用launchActivity并通过意图传递数据时,您无视我们要测试的内容,最终用户无法通过意图传递数据,他们只是单击一个按钮,该按钮触发我们的代码以意图传递数据。因此,一个很好的测试应该是从头到尾(从启动屏幕到您想要的屏幕),并且模仿用户的动作(单击X,单击Y,将500写入Z等) 现在,您的问题很可能是由于在方法中的每个测试中都使用了launchActivity而导致的,第二个测试无法启动Activity(至少它不能足够快地启动活动),因此您会遇到错误第一个断言。
androidx.test.espresso.NoMatchingViewException: No views in hierarchy found matching: with id: com.stegner.androiddex:id/menu_filter
您应该从测试方法中删除 launchActivity(),并使用应用程序显示的第一个屏幕定义活动测试规则。
@Rule
public ActivityTestRule<MyFirstActivity> activityRule =
new ActivityTestRule<>(MyFirstActivity.class);
用注释规则注释此类时,在每次测试开始之前,请确保已加载此活动,然后您可以转到要模拟用户交互的页面。如果您在应用此解决方案后仍然遇到问题,请将其写为注释,因为这样您的问题将与同步相关,需要不同的答案。