Reputation: 158
I have a ChipGroup
containing some Chip
views that when checked, display some TextViews
and SeekBars
. I am trying to test this using Espresso and I am getting odd results.
Because the following test failed: (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)))
}
I created the following simple test to see what is happening: (Test2) which is also failing. (See stack trace below)
@Test
fun whenEuropeChipIsClicked_CheckIsSelected() {
launchFragmentInContainer<GameConfigSurvivalFragment>()
onView(withId(R.id.europeSurvChip)).perform(click())
onView(withId(R.id.europeSurvChip)).check(matches(isChecked()))
}
Some of my production code for this feature looks like this and I inserted some logs to see what is the state of the chip
when I click on the 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}")
}
}
While testing the selection of the Chip
manually on the emulator I achieve the intended result, and I can see on the log that the Chip
is checked and unchecked. However, the Espresso tests I created never pass. Manually testing everything works as expected and the Seekbars
and TextViews
are displayed as well as the Chip
button being checked.
I disabled animations as other questions suggested it to people suffering from Espresso's click()
method not working properly.
Any idea what am I doing wrong? (everything is happening in the main thread)
Ideas I feel not confident about:
Does it have to do with the fact that I am using observers?
Is Espresso's click()
method not working on Chip
views? (hard to believe)
Test2's stacktrace
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's 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
}
}
Upvotes: 0
Views: 1083
Reputation: 158
Fixed it by making the Chip
clickable and checkable in the XML file.
I am guessing it was made clickable and checkable programmatically somewhere in the code.
Upvotes: 1