In questo talk vedremo come creare test automatici per i tuoi layout realizzati con Jetpack Compose, scopriremo le differenze tra Rules, Finders, Assertions, Actions e Matchers e capiremo perchè un approccio "automatico" garantisce velocità e stabilità per la tua app, senza dimenticare l'accessibilità.
3. Why automated
UI testing?
● Testing UI interactions ensure
users to do not fall into
unexpected results and poor user
experience
● Manual approach is
time-consuming and error prone
● Automatic approach guarantees
quickness and reliability
4. The old way -
Espresso UI testing
import org.junit.Test
onView(withId(R.id.tvName)).perform
(typeText("Steve"))
onView(withId(R.id.btGreet)).perfor
m(click())
5. The new way -
Compose testing API
● Compose provides a set of
testing APIs to find elements
● A semantic tree is generated
alongside the UI hierarchy
● onView “withId” matcher no
longer available
7. Rules
● useful to set up the necessary
environment for a Compose UI test
● common Rule factory methods are
createComposeRule() and
createAndroidComposeRule<YourA
ctivity>()
8. Finders
● Convenient for the most common
searches
● Useful to select one or multiple
nodes of the semantic tree
● Can be used on a single node or on
a group of nodes
● Most common are
onNodeWithText,
onNodeWithContentDescription,
onNodeWithTag
9. Assertions
● Used to check that our
composable tree has the expected
elements with consistent content
and behavior
● If the condition(s) is verified the
test passes, otherwise it fails
● Most common are assertExists,
assertIsDisplayed,
assertTextEquals
10. Actions
● Used to perform a user action on a
UI component and change the
state of the UI
● Most common are performClick(),
performScrollTo(),
performTextInput()
11. Matchers
● Let you go up and down the
semantic tree
● Can be hierarchical or selectors
● Most common are hasParent,
hasAnySibling, hasTestTag
12. Accessibility and testing: contentDescription semantic
1) Accessibility: some people use
our app in a different way from
what we typically do. Semantic
content description tree helps
them to describe the app to users
with impaired vision
2) Testing: We have a convenient and
reliable way to find our “views” in
the semantic tree
13. Testing only alternative: testTag
1) Accessibility: no accessibility info
“out of the box”, still needs a
contentDescription
2) Testing: easy way to find the tag
by using onNodeWithTag finder
14. Setup Compose UI Testing - On/off Switch playground app
● Describe our UI elements with
semantics modifier
● Test ui state “OFF”
● Test ui state “ON”
16. Handling Switch Status
● Keep switch status within an enum
variable, surviving to
recompositions
● Use semantics modifier to make
our layout accessible and test -
friendly
17. Handling User actions
● Enable / disable ON and OFF
buttons according to switch status
● Change status on user clicks
● Describe each button with
semantics modifier
18. Setup UI testing
● Set up our testing scenario by
using createAndroidComposeRule
● Use setContent method to inject
our layout in the UI test
● Perform ON and OFF actions
● Test that our “status description”
composable reacts accordingly
19. Setup UI testing
● createAndroidComposeRule allows you
to start an activity displaying any
composable
● We need “android” test rule, it will
come in handy to access string
resources
● setContent method inherited from
ComponentActivity
20. Perform click action (ON)
● A semantic node is needed to
perform the click action
● We can’t use findviewbyId
(Espresso-like)
● How do we find our semantic
node???
interface ComposeTestRule : TestRule,
SemanticsNodeInteractionsProvider
21. Test click action (ON)
● Find the “on button” semantic
node with
onNodeWithContentDescript
ion finder
● Use .performClick() action
to perform the click
● Find the “status” semantic
node
● assert “status” label has
changed accordingly
22. Test click action (OFF)
● Find the “off button” semantic
node with
onNodeWithContentDescripti
on finder
● Use .performClick()action to
perform the click
● Find the “status” semantic
node
● assert status composable text
has changed accordingly
24. Bonus track 1: custom semantic properties
● Useful to expose additional
semantics information to tests
● Definition by
SemanticsPropertyKey class in a
type safe way
● Property is made available with
SemanticsPropertyReceiver
25. Matching custom property in tests
● Use expectValue predicate to
check that a semantic property
exists with an expected value
26. Bonus track 2: testing navigation
Semantics modifier can be useful also to
describe each screen of our app.
This modifier will come in handy in our
UI test to check what is the current
displayed screen.
27. Bonus track 2: testing navigation - Setup
Before running the test we need to use
a special navController for tests:
TestNavHostController
28. Bonus track 2: testing navigation
Once the test is set up with our
TestNavHostController we can:
● Assert the first visible screen is “Switch
Screen”
● Perform click on “Credits” button
● Verify that our app has switched to
“credits” screen
● Enjoy the greens!!
29. Merged vs Unmerged tree
Sometimes is convenient to merge some
sub-trees of nodes and treat them as one
single node. We can use
mergeDescendants property for this
purpose