Skip to content

Commit e20b836

Browse files
committed
Eliminates espresso hacks
Trying to reduce Espresso flakes by being more careful and conventional about `RootMatcher` use; about targetting back button presses; and by using `recreate()` for configuration changes.
1 parent c75f737 commit e20b836

File tree

12 files changed

+141
-214
lines changed

12 files changed

+141
-214
lines changed
Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,29 @@
11
package com.squareup.sample.poetryapp
22

3+
import androidx.test.espresso.Espresso.onView
34
import androidx.test.espresso.assertion.ViewAssertions.matches
45
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
56
import androidx.test.espresso.matcher.ViewMatchers.withText
67
import androidx.test.ext.junit.rules.ActivityScenarioRule
78
import androidx.test.ext.junit.runners.AndroidJUnit4
89
import com.squareup.sample.container.poetryapp.R
9-
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
1010
import com.squareup.workflow1.ui.internal.test.IdlingDispatcherRule
11-
import com.squareup.workflow1.ui.internal.test.inAnyView
1211
import leakcanary.DetectLeaksAfterTestSuccess
1312
import org.junit.Rule
1413
import org.junit.Test
1514
import org.junit.rules.RuleChain
1615
import org.junit.runner.RunWith
1716

1817
@RunWith(AndroidJUnit4::class)
19-
@OptIn(WorkflowUiExperimentalApi::class)
2018
class PoetryAppTest {
2119

2220
private val scenarioRule = ActivityScenarioRule(PoetryActivity::class.java)
2321

24-
@get:Rule val rules = RuleChain.outerRule(DetectLeaksAfterTestSuccess())
22+
@get:Rule val rules: RuleChain = RuleChain.outerRule(DetectLeaksAfterTestSuccess())
2523
.around(scenarioRule)
2624
.around(IdlingDispatcherRule)
2725

2826
@Test fun launches() {
29-
inAnyView(withText(R.string.poems))
30-
.check(matches(isDisplayed()))
27+
onView(withText(R.string.poems)).check(matches(isDisplayed()))
3128
}
3229
}
Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,29 @@
11
package com.squareup.sample.ravenapp
22

3+
import androidx.test.espresso.Espresso.onView
34
import androidx.test.espresso.assertion.ViewAssertions.matches
45
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
56
import androidx.test.espresso.matcher.ViewMatchers.withText
67
import androidx.test.ext.junit.rules.ActivityScenarioRule
78
import androidx.test.ext.junit.runners.AndroidJUnit4
8-
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
99
import com.squareup.workflow1.ui.internal.test.IdlingDispatcherRule
10-
import com.squareup.workflow1.ui.internal.test.inAnyView
1110
import leakcanary.DetectLeaksAfterTestSuccess
1211
import org.junit.Rule
1312
import org.junit.Test
1413
import org.junit.rules.RuleChain
1514
import org.junit.runner.RunWith
1615

1716
@RunWith(AndroidJUnit4::class)
18-
@OptIn(WorkflowUiExperimentalApi::class)
1917
class RavenAppTest {
2018

2119
private val scenarioRule = ActivityScenarioRule(RavenActivity::class.java)
2220

23-
@get:Rule val rules = RuleChain.outerRule(DetectLeaksAfterTestSuccess())
21+
@get:Rule val rules: RuleChain = RuleChain.outerRule(DetectLeaksAfterTestSuccess())
2422
.around(scenarioRule)
2523
.around(IdlingDispatcherRule)
2624

2725
@Test fun launches() {
28-
inAnyView(withText("The Raven"))
26+
onView(withText("The Raven"))
2927
.check(matches(isDisplayed()))
3028
}
3129
}
Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
package com.squareup.sample.hellobackbutton
22

3+
import androidx.test.espresso.Espresso.onView
34
import androidx.test.espresso.action.ViewActions.click
5+
import androidx.test.espresso.action.ViewActions.pressBack
46
import androidx.test.espresso.assertion.ViewAssertions.matches
7+
import androidx.test.espresso.matcher.RootMatchers.isDialog
58
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
69
import androidx.test.espresso.matcher.ViewMatchers.withId
710
import androidx.test.espresso.matcher.ViewMatchers.withText
811
import androidx.test.ext.junit.rules.ActivityScenarioRule
912
import androidx.test.ext.junit.runners.AndroidJUnit4
1013
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
1114
import com.squareup.workflow1.ui.internal.test.IdlingDispatcherRule
12-
import com.squareup.workflow1.ui.internal.test.actuallyPressBack
13-
import com.squareup.workflow1.ui.internal.test.inAnyView
14-
import com.squareup.workflow1.ui.internal.test.retryBlocking
1515
import leakcanary.DetectLeaksAfterTestSuccess
1616
import org.junit.Rule
1717
import org.junit.Test
@@ -24,29 +24,32 @@ class HelloBackButtonEspressoTest {
2424

2525
private val scenarioRule = ActivityScenarioRule(HelloBackButtonActivity::class.java)
2626

27-
@get:Rule val rules = RuleChain.outerRule(DetectLeaksAfterTestSuccess())
27+
@get:Rule val rules: RuleChain = RuleChain.outerRule(DetectLeaksAfterTestSuccess())
2828
.around(scenarioRule)
2929
.around(IdlingDispatcherRule)
3030

31-
@Test fun wrappedTakesPrecedence() = retryBlocking {
32-
inAnyView(withId(R.id.hello_message)).apply {
31+
@Test fun wrappedTakesPrecedence() {
32+
onView(withId(R.id.hello_message)).apply {
3333
check(matches(withText("Able")))
3434
perform(click())
3535
check(matches(withText("Baker")))
3636
perform(click())
3737
check(matches(withText("Charlie")))
38-
actuallyPressBack()
38+
perform(pressBack())
3939
check(matches(withText("Baker")))
40-
actuallyPressBack()
40+
perform(pressBack())
4141
check(matches(withText("Able")))
4242
}
4343
}
4444

45-
@Test fun outerHandlerAppliesIfWrappedHandlerIsNull() = retryBlocking {
46-
inAnyView(withId(R.id.hello_message)).apply {
47-
actuallyPressBack()
48-
inAnyView(withText("Are you sure you want to do this thing?"))
49-
.check(matches(isDisplayed()))
45+
@Test fun outerHandlerAppliesIfWrappedHandlerIsNull() {
46+
onView(withId(R.id.hello_message)).apply {
47+
check(matches(isDisplayed()))
48+
perform(pressBack())
5049
}
50+
51+
onView(withText("Are you sure you want to do this thing?"))
52+
.inRoot(isDialog())
53+
.check(matches(isDisplayed()))
5154
}
5255
}
Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,30 @@
11
package com.squareup.sample.dungeon
22

3+
import androidx.test.espresso.Espresso.onView
34
import androidx.test.espresso.assertion.ViewAssertions.matches
45
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
56
import androidx.test.espresso.matcher.ViewMatchers.withText
67
import androidx.test.ext.junit.rules.ActivityScenarioRule
78
import androidx.test.ext.junit.runners.AndroidJUnit4
89
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
910
import com.squareup.workflow1.ui.internal.test.IdlingDispatcherRule
10-
import com.squareup.workflow1.ui.internal.test.inAnyView
1111
import leakcanary.DetectLeaksAfterTestSuccess
1212
import org.junit.Rule
1313
import org.junit.Test
1414
import org.junit.rules.RuleChain
1515
import org.junit.runner.RunWith
1616

1717
@RunWith(AndroidJUnit4::class)
18-
@OptIn(WorkflowUiExperimentalApi::class)
1918
class DungeonAppTest {
2019

2120
private val scenarioRule = ActivityScenarioRule(DungeonActivity::class.java)
2221

23-
@get:Rule val rules = RuleChain.outerRule(DetectLeaksAfterTestSuccess())
22+
@get:Rule val rules: RuleChain = RuleChain.outerRule(DetectLeaksAfterTestSuccess())
2423
.around(scenarioRule)
2524
.around(IdlingDispatcherRule)
2625

2726
@Test fun loadsBoardsList() {
28-
inAnyView(withText(R.string.boards_list_label))
27+
onView(withText(R.string.boards_list_label))
2928
.check(matches(isDisplayed()))
3029
}
3130
}
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
package com.squareup.sample.helloworkflowfragment
22

3+
import androidx.test.espresso.Espresso.onView
34
import androidx.test.espresso.action.ViewActions.click
45
import androidx.test.espresso.assertion.ViewAssertions.matches
56
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
67
import androidx.test.espresso.matcher.ViewMatchers.withText
78
import androidx.test.ext.junit.rules.ActivityScenarioRule
89
import androidx.test.ext.junit.runners.AndroidJUnit4
9-
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
1010
import com.squareup.workflow1.ui.internal.test.IdlingDispatcherRule
11-
import com.squareup.workflow1.ui.internal.test.inAnyView
1211
import leakcanary.DetectLeaksAfterTestSuccess
1312
import org.hamcrest.Matchers.containsString
1413
import org.junit.Rule
@@ -17,25 +16,24 @@ import org.junit.rules.RuleChain
1716
import org.junit.runner.RunWith
1817

1918
@RunWith(AndroidJUnit4::class)
20-
@OptIn(WorkflowUiExperimentalApi::class)
2119
class HelloWorkflowFragmentAppTest {
2220

2321
private val scenarioRule = ActivityScenarioRule(HelloWorkflowFragmentActivity::class.java)
2422

25-
@get:Rule val rules = RuleChain.outerRule(DetectLeaksAfterTestSuccess())
23+
@get:Rule val rules: RuleChain = RuleChain.outerRule(DetectLeaksAfterTestSuccess())
2624
.around(scenarioRule)
2725
.around(IdlingDispatcherRule)
2826

2927
@Test fun togglesHelloAndGoodbye() {
30-
inAnyView(withText(containsString("Hello")))
28+
onView(withText(containsString("Hello")))
3129
.check(matches(isDisplayed()))
3230
.perform(click())
3331

34-
inAnyView(withText(containsString("Goodbye")))
32+
onView(withText(containsString("Goodbye")))
3533
.check(matches(isDisplayed()))
3634
.perform(click())
3735

38-
inAnyView(withText(containsString("Hello")))
36+
onView(withText(containsString("Hello")))
3937
.check(matches(isDisplayed()))
4038
}
4139
}
Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,38 @@
11
package com.squareup.sample.helloworkflow
22

3+
import androidx.test.espresso.Espresso.onView
34
import androidx.test.espresso.action.ViewActions.click
45
import androidx.test.espresso.assertion.ViewAssertions.matches
56
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
67
import androidx.test.espresso.matcher.ViewMatchers.withText
78
import androidx.test.ext.junit.rules.ActivityScenarioRule
89
import androidx.test.ext.junit.runners.AndroidJUnit4
9-
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
1010
import com.squareup.workflow1.ui.internal.test.IdlingDispatcherRule
11-
import com.squareup.workflow1.ui.internal.test.inAnyView
1211
import leakcanary.DetectLeaksAfterTestSuccess
1312
import org.junit.Rule
1413
import org.junit.Test
1514
import org.junit.rules.RuleChain
1615
import org.junit.runner.RunWith
1716

1817
@RunWith(AndroidJUnit4::class)
19-
@OptIn(WorkflowUiExperimentalApi::class)
2018
class HelloWorkflowAppTest {
2119

2220
private val scenarioRule = ActivityScenarioRule(HelloWorkflowActivity::class.java)
2321

24-
@get:Rule val rules = RuleChain.outerRule(DetectLeaksAfterTestSuccess())
22+
@get:Rule val rules: RuleChain = RuleChain.outerRule(DetectLeaksAfterTestSuccess())
2523
.around(scenarioRule)
2624
.around(IdlingDispatcherRule)
2725

2826
@Test fun togglesHelloAndGoodbye() {
29-
inAnyView(withText("Hello"))
27+
onView(withText("Hello"))
3028
.check(matches(isDisplayed()))
3129
.perform(click())
3230

33-
inAnyView(withText("Goodbye"))
31+
onView(withText("Goodbye"))
3432
.check(matches(isDisplayed()))
3533
.perform(click())
3634

37-
inAnyView(withText("Hello"))
35+
onView(withText("Hello"))
3836
.check(matches(isDisplayed()))
3937
}
4038
}
Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
package com.squareup.sample.stubvisibility
22

3+
import androidx.test.espresso.Espresso.onView
34
import androidx.test.espresso.action.ViewActions.click
45
import androidx.test.espresso.assertion.ViewAssertions.matches
56
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
67
import androidx.test.espresso.matcher.ViewMatchers.withId
78
import androidx.test.espresso.matcher.ViewMatchers.withText
89
import androidx.test.ext.junit.rules.ActivityScenarioRule
910
import androidx.test.ext.junit.runners.AndroidJUnit4
10-
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
1111
import com.squareup.workflow1.ui.internal.test.IdlingDispatcherRule
12-
import com.squareup.workflow1.ui.internal.test.inAnyView
1312
import leakcanary.DetectLeaksAfterTestSuccess
1413
import org.hamcrest.CoreMatchers.not
1514
import org.junit.Rule
@@ -18,29 +17,28 @@ import org.junit.rules.RuleChain
1817
import org.junit.runner.RunWith
1918

2019
@RunWith(AndroidJUnit4::class)
21-
@OptIn(WorkflowUiExperimentalApi::class)
2220
internal class StubVisibilityAppTest {
2321

2422
private val scenarioRule = ActivityScenarioRule(StubVisibilityActivity::class.java)
2523

26-
@get:Rule val rules = RuleChain.outerRule(DetectLeaksAfterTestSuccess())
24+
@get:Rule val rules: RuleChain = RuleChain.outerRule(DetectLeaksAfterTestSuccess())
2725
.around(scenarioRule)
2826
.around(IdlingDispatcherRule)
2927

3028
@Test fun togglesFooter() {
31-
inAnyView(withId(R.id.should_be_wrapped))
29+
onView(withId(R.id.should_be_wrapped))
3230
.check(matches(not(isDisplayed())))
3331

34-
inAnyView(withText("Click to show footer"))
32+
onView(withText("Click to show footer"))
3533
.perform(click())
3634

37-
inAnyView(withId(R.id.should_be_wrapped))
35+
onView(withId(R.id.should_be_wrapped))
3836
.check(matches(isDisplayed()))
3937

40-
inAnyView(withText("Click to hide footer"))
38+
onView(withText("Click to hide footer"))
4139
.perform(click())
4240

43-
inAnyView(withId(R.id.should_be_wrapped))
41+
onView(withId(R.id.should_be_wrapped))
4442
.check(matches(not(isDisplayed())))
4543
}
4644
}

0 commit comments

Comments
 (0)