I'm writing an Android app using Jetpack Compose. It has some dialogs. I am testing with Espresso that they disappear when appropriate. When everything's working right, I can test that all dialogs have disappeared with:
composeRule.onNode(isDialog()).assertIsNotDisplayed()
And if Espresso determines there is a displayed dialog, the test fails with an AssertionError
. However, the error's text is only:
Assert failed: The component is displayed!
What component, though? How do I get information on which component is displayed?
Of course, I can run the test on the emulator, set a breakpoint at the AssertionError
, and look at the emulator screen. When I do that, I see no dialog. But Espresso sees a dialog. I want to see information about the dialog Espresso is seeing. How do I do that? Almost any information would do, but right now I'm finding absolutely nothing.
I see that assertIsNotDisplayed()
is defined as
fun SemanticsNodeInteraction.assertIsNotDisplayed()
so that this
is a SemanticsNodeInteraction
, and that such an object
Represents a semantics node and the path to fetch it from the semantics tree.
I clicked around in the debugger, exploring some properties of this
, but haven't yet found the path or tree.
I'm asking how to debug failed Espresso assertions, instead of posting my particular failing code, because I don't think just getting one of my tests to pass is a permanent solution. Tomorrow another test will fail, and I'll be back to square one not knowing how to debug it. If Espresso is telling me my test failed, I need to be able to find out why, if I am to debug and fix my code.
The way to display this is with printToLog()
, as mentioned in the documentation (thanks @Edric). I found it useful to use it together with onAllNodes()
instead of starting from the root:
composeRule.onAllNodes(isDialog()).printToLog("LookAtMe", maxDepth=Int.MAX_VALUE)
While maxDepth
defaults to Int.MAX_VALUE
in SemanticsInteraction.printToLog()
, as would indeed make sense, for SemanticsInteractionCollection.printToLog()
, the more useful function for this situation, maxDepth
unfortunately defaults to 0
so must be set manually.
The reason isDialog()
had been returning things I had thought weren't dialogs was that in Compose 1.7 and 1.8, unlike in 1.6, ModalBottomSheet
is considered a dialog, in the sense that a "dialog" is a separate root, not only those which look like Dialog
s.