android - Espresso 测试,点击 Chip view not working
问题描述
我有一个ChipGroup
包含一些Chip
观点,这些视图在检查时,显示一些TextViews
视图SeekBars
。我正在尝试使用 Espresso 对此进行测试,但结果很奇怪。
因为下面的测试失败了:(Test1)
@Test
fun whenEuropeChipIsSelected_DisplaySeekBarsAndTextViews() {
launchFragmentInContainer<GameConfigSurvivalFragment>()
onView(withId(R.id.europeSurvChip)).perform(click())
onView(withId(R.id.countriesNumberSeekBar)).check(matches(isDisplayed()))
onView(withId(R.id.selectCountriesNumberTv)).check(matches(isDisplayed()))
onView(withId(R.id.selectedCountriesTV)).check(matches(isDisplayed()))
onView(withId(R.id.timeLimitSeekBar)).check(matches(isDisplayed()))
onView(withId(R.id.timeLimitTv)).check(matches(isDisplayed()))
onView(withId(R.id.selectTimeLimitTv)).check(matches(withEffectiveVisibility(Visibility.VISIBLE)))
}
我创建了以下简单测试以查看发生了什么:(Test2)也失败了。(见下面的堆栈跟踪)
@Test
fun whenEuropeChipIsClicked_CheckIsSelected() {
launchFragmentInContainer<GameConfigSurvivalFragment>()
onView(withId(R.id.europeSurvChip)).perform(click())
onView(withId(R.id.europeSurvChip)).check(matches(isChecked()))
}
我为此功能的一些生产代码如下所示,我插入了一些日志以查看chip
单击芯片时的状态:
binding.europeSurvChip.setOnCheckedChangeListener { isChecked ->
if (isChecked) {
counter.value = counter.value!!.plus(Europe.totalCountries)
continentsList.add(Europe)
Log.d("ChipSelected", "EuropeChipSelected: isChecked: ${europeSurvChip.isChecked}")
} else {
counter.value = counter.value!!.minus(Europe.totalCountries)
continentsList.remove(Europe)
Log.d("ChipSelected", "EuropeChipSelected: isChecked: ${europeSurvChip.isChecked}")
}
}
在模拟器上测试Chip
手动选择时,我达到了预期的结果,并且我可以在日志中看到Chip
已选中和未选中。但是,我创建的 Espresso 测试从未通过。手动测试一切都按预期工作,Seekbars
并TextViews
显示 和 以及Chip
正在检查的按钮。
我禁用了动画,因为其他问题向患有Espresso click()
方法无法正常工作的人提出了建议。
知道我在做什么错吗?(一切都在主线程中发生)
我不自信的想法:
这是否与我使用观察者的事实有关?
Espresso 的方法对视图
click()
不起作用吗?Chip
(难以置信)
Test2 的堆栈跟踪
E/TestRunner: failed: whenEuropeChipIsClicked_CheckIsSelected(com.example.capitalcityquizktx.ui.survivalmode.config.GameConfigSurvivalFragmentTest)
----- begin exception -----
E/TestRunner: androidx.test.espresso.base.DefaultFailureHandler$AssertionFailedWithCauseError: 'with checkbox state: is <true>' doesn't match the selected view.
Expected: with checkbox state: is <true>
Got: "Chip{id=2131230840, res-name=europeSurvChip, visibility=VISIBLE, width=315, height=88, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=true, is-layout-requested=false, is-selected=false, layout-params=android.widget.TableRow$LayoutParams@b19ff14, tag=null, root-is-layout-requested=false, has-input-connection=false, x=11.0, y=11.0, text=Europe, input-type=0, ime-target=false, has-links=false, is-checked=false}"
at dalvik.system.VMStack.getThreadStackTrace(Native Method)
at java.lang.Thread.getStackTrace(Thread.java:1720)
at androidx.test.espresso.base.DefaultFailureHandler.getUserFriendlyError(DefaultFailureHandler.java:94)
at androidx.test.espresso.base.DefaultFailureHandler.handle(DefaultFailureHandler.java:57)
at androidx.test.espresso.ViewInteraction.waitForAndHandleInteractionResults(ViewInteraction.java:318)
at androidx.test.espresso.ViewInteraction.check(ViewInteraction.java:300)
at com.example.capitalcityquizktx.ui.survivalmode.config.GameConfigSurvivalFragmentTest.whenEuropeChipIsClicked_CheckIsSelected(GameConfigSurvivalFragmentTest.kt:63)
at java.lang.reflect.Method.invoke(Native Method)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at androidx.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:80)
at androidx.test.internal.runner.junit4.statement.RunAfters.evaluate(RunAfters.java:61)
at androidx.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:527)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at androidx.test.ext.junit.runners.AndroidJUnit4.run(AndroidJUnit4.java:104)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:388)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2189)
Caused by: junit.framework.AssertionFailedError: 'with checkbox state: is <true>' doesn't match the selected view.
Expected: with checkbox state: is <true>
Got: "Chip{id=2131230840, res-name=europeSurvChip, visibility=VISIBLE, width=315, height=88, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=true, is-layou
----- end exception -----
Test1 的 stackTrace
E/TestRunner: failed: whenEuropeChipIsSelected_DisplaySeekBarsAndTextViews_numberOfCountriesAndTimeLimit(com.example.capitalcityquizktx.ui.survivalmode.config.GameConfigSurvivalFragmentTest)
----- begin exception -----
E/TestRunner: androidx.test.espresso.base.DefaultFailureHandler$AssertionFailedWithCauseError: 'is displayed on the screen to the user' doesn't match the selected view.
Expected: is displayed on the screen to the user
Got: "SeekBar{id=2131230817, res-name=countriesNumberSeekBar, visibility=GONE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=true, is-layout-requested=true, is-selected=false, layout-params=androidx.constraintlayout.widget.ConstraintLayout$LayoutParams@1f49905, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0}"
at dalvik.system.VMStack.getThreadStackTrace(Native Method)
at java.lang.Thread.getStackTrace(Thread.java:1720)
at androidx.test.espresso.base.DefaultFailureHandler.getUserFriendlyError(DefaultFailureHandler.java:94)
at androidx.test.espresso.base.DefaultFailureHandler.handle(DefaultFailureHandler.java:57)
at androidx.test.espresso.ViewInteraction.waitForAndHandleInteractionResults(ViewInteraction.java:318)
at androidx.test.espresso.ViewInteraction.check(ViewInteraction.java:300)
at com.example.capitalcityquizktx.ui.survivalmode.config.GameConfigSurvivalFragmentTest.whenEuropeChipIsSelected_DisplaySeekBarsAndTextViews_numberOfCountriesAndTimeLimit(GameConfigSurvivalFragmentTest.kt:49)
at java.lang.reflect.Method.invoke(Native Method)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at androidx.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:80)
at androidx.test.internal.runner.junit4.statement.RunAfters.evaluate(RunAfters.java:61)
at androidx.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:527)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at androidx.test.ext.junit.runners.AndroidJUnit4.run(AndroidJUnit4.java:104)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:388)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2189)
Caused by: junit.framework.AssertionFailedError: 'is displayed on the screen to the user' doesn't match the selected view.
Expected: is displayed on the screen to the user
Got: "SeekBar{id=2131230817, res-name=countriesNumberSeekBar, visibility=GONE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=fals
----- end exception -----
生产代码类。(它按预期工作):
class GameConfigSurvivalFragment : Fragment(),
GameConfigSurvivalView {
override val continentsList = MutableLiveData<List<Continent>>().default(arrayListOf())
private val displayTimeLimitSeekBar = MutableLiveData<Boolean>().default(false)
private val displayQuestionNumberSeekBar = MutableLiveData<Boolean>().default(false)
override fun showQuestionsNumberSelection() {
displayQuestionNumberSeekBar.value = true
}
override fun showTimeLimitSelection() {
displayTimeLimitSeekBar.value = true
}
override fun hideQuestionsNumberSelection() {
displayQuestionNumberSeekBar.value = false
}
override fun hideTimeLimitSelection() {
displayTimeLimitSeekBar.value = false
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val binding: GameConfigSurvivalFragmentBinding = inflate(
inflater, R.layout.game_config_survival_fragment, container, false
)
val presenter = GameConfigSurvivalPresenter(this)
presenter.receiveContinentSelection()
//Minimum amount of seconds that will be added to timeLimitSeekbar
val minTimeLimit = 5
// This counter is used to count the amount of countries to set up the seekBar acording to its value
val counter = MutableLiveData<Int>()
counter.value = 0
// This val is used to gather information about the number of chips that are checked
// in order to show the seekBar if there are any of them checked
val continentsSelected = MutableLiveData<Int>()
continentsSelected.value = 0
displayQuestionNumberSeekBar.observe(this,
Observer { displayIt ->
if (displayIt){
binding.selectCountriesNumberTv.isVisible = true
binding.countriesNumberSeekBar.isVisible = true
binding.selectedCountriesTV.isVisible = true
binding.countriesNumberSeekBar.max = counter.value!!
binding.countriesNumberSeekBar.progress = binding.countriesNumberSeekBar.max
}else{
binding.selectCountriesNumberTv.isVisible = false
binding.countriesNumberSeekBar.isVisible = false
binding.selectedCountriesTV.isVisible = false
}
})
displayTimeLimitSeekBar.observe(this,
Observer { displayIt ->
if (displayIt){
binding.selectTimeLimitTv.isVisible = true
binding.timeLimitSeekBar.isVisible = true
binding.timeLimitTv.isVisible = true
}else{
binding.selectTimeLimitTv.isVisible = false
binding.timeLimitSeekBar.isVisible = false
binding.timeLimitTv.isVisible = false
}
})
/* The following listeners check the state of the chips whether they are checked or not,
in order to count the number of countries and to count the number of continents selected */
binding.europeSurvChip.setOnCheckedChangeListener { buttonView, isChecked ->
if (isChecked) {
counter.value = counter.value!!.plus(Europe.totalCountries)
continentsList.add(Europe)
Log.d("ChipSelected", "EuropeChipSelected: isChecked: ${europeSurvChip.isChecked}")
} else {
counter.value = counter.value!!.minus(Europe.totalCountries)
continentsList.remove(Europe)
Log.d("ChipSelected", "EuropeChipSelected: isChecked: ${europeSurvChip.isChecked}")
}
}
return binding.root
}
}
解决方案
Chip
通过使XML 文件中的可点击和可检查来修复它。
我猜它是在代码中的某处以编程方式使其可点击和可检查的。
推荐阅读
- mule-esb - 在记录之前屏蔽 Mule4 中的敏感数据
- javascript - 脚本只显示一个结果如何输出 ap 标签内的所有结果?
- python - 在 genfromtxt next(fhd) 中,添加新的“带打开文件”行时出现 StopIteration 错误
- java - 回调在 NIO.2 库中的行为方式
- java - libGDX html:draftCompileGwt 编译错误
- javascript - 正则表达式匹配字符串中的所有href,除非包含一个单词
- swift - 已经添加了 LSApplicationQueriesScheme,但我仍然收到错误:“此应用不允许查询方案 whatsapp”
- java - 如何在不引发 org.threeten.bp.zone.ZoneRulesException 的情况下对使用 ZoneId.systemDefault 的代码进行单元测试
- qt - 带有特殊字符的 Qt qmake TARGET 值
- node.js - Node.js Auto Increment E11000 重复键错误收集