[go: nahoru, domu]

Improvements in Compose testing lib sync.

After trying to setup tests for jetnews I identified several issues in
our synchonization. After fixing these several other issues surfaced
that were previously hidden by incorrect sync.

I have introduce ComposeIdlingResource that registers itself into
Espresso. This way we leave synchronization to Espresso. It removed
several flakes we had because we used to wait for idle compose and then
did the "Espresso wait". From now on Espresso does all of it at the same
time. This helps in cases where we have regular Android event that later
leads to invalidation of compose.

Thanks to us having ComposeIdlingResource we no longer need to wait
after we perform actions (doClick) for idle Compose. It also makes tests
faster as we don't sync when not needed. This unfortunately broke tests
that were relying on this fact (incorrectly) and touching the UI thread
from the test thread.

So far lots of tests were using waitForIdleCompose() and touching
variables from different threads or did not use any kind of
synchonization at all. They were lucky because methods like doClick used
to wait for UI being idle before leaving. To address that I have
introduced runOnIdleCompose that waits for idle compose and performs the
given lambda on the UI thread. This makes assertions nice and stable! :)
I have also removed waitForIdle {} as it would encourage bad practices
from now on.

Other thing discovered after I removed the flakes was that we were
always recreating SemanticsConfiguration which previsouly wasn't
detected. This however was something on which the testing API relied on.
So I memoized the SemanticsConfiguration. This will need to work with
merging also.

We were also not disposing compositions between tests. This lead to more
synchronization issues as old compositions were still part of the app.

Another wrong thing was that we always send any events to the first
ComposeView. This was wrong in case the second ComposeView would need to
work with events. It wasn't detected becase  MultipleComposeRootsTest
had wrong assertions. Now it is fixed.

Unfortunately I had to fix several tests so sorry for the diff. However
I couldn't split it because the sync changes go hand in hand with how
the tests are written.

Bug: b/122349846
Test: Verified on current tests and local JetNews tests.
Change-Id: If58d3c300e430de4ce81a7e4a963e41c04f71b5b
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/DrawerTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/DrawerTest.kt
index 61a1c8a..64f08a7 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/DrawerTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/DrawerTest.kt
@@ -174,21 +174,22 @@
         findByTag("Drawer")
             .doClick()
 
-        Truth.assertThat(drawerClicks).isEqualTo(0)
-        Truth.assertThat(bodyClicks).isEqualTo(1)
+        composeTestRule.runOnIdleCompose {
+            Truth.assertThat(drawerClicks).isEqualTo(0)
+            Truth.assertThat(bodyClicks).isEqualTo(1)
+        }
 
         composeTestRule.runOnUiThread {
             drawerState.state = DrawerState.Opened
         }
-        // TODO: we aren't correctly waiting for recompositions after clicking, so we need to wait
-        // again
-        Thread.sleep(100L)
 
         findByTag("Drawer")
             .doClick()
 
-        Truth.assertThat(drawerClicks).isEqualTo(1)
-        Truth.assertThat(bodyClicks).isEqualTo(1)
+        composeTestRule.runOnIdleCompose {
+            Truth.assertThat(drawerClicks).isEqualTo(1)
+            Truth.assertThat(bodyClicks).isEqualTo(1)
+        }
     }
 
     @Test