Litho provides basic support for the Espresso UI Testing framework. For the time being, we only provide shallow selectors that will match ComponentHosts and LithoViews to run very high-level tests against. If you find that too limiting, please reach out to us and describe your use case.

Getting Started

We ship with a bunch of custom matchers, which will hopefully make your life easier.

The matchers exist as their own litho-espresso package, so make sure to add the dependencies to your build.gradle file alongside your Espresso setup:

1
2
3
4
5
6
dependencies {
  // ...
  androidTestCompile 'com.facebook.litho:litho-espresso:0.8.0'
  androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
  androidTestCompile 'com.android.support.test.espresso:espresso-intents:2.2.2'
}


Matching

In order to instruct Litho to record where elements are mounted and give you access to testKeys you can set in your ComponentLayouts, replace your usual ActivityTestRule with the specialized LithoActivityTestRule:

1
2
3
4
5
6
7
8
9
@RunWith(AndroidJUnit4.class)
@LargeTest
public class MyTest {
  @Rule
  public LithoActivityTestRule<MyActivity> mActivity =
      new LithoActivityTestRule<>(MyActivity.class);
      
  // ...
}

Afterwards, you can check against ComponentHosts and LithoViews as you normally would for standard Android Views. For instance, let’s assume you have a mounted clickable component like this present in the selected activity:

1
2
3
4
CustomButton.create(c)
    .text("My Button")
    .clickHandler(/* ... */)
    .build();

Then, you could write an Espresso test like this:

1
2
3
4
5
@Test
public void testButtonIsDisplayedAndClickable() {
    onView(ComponentHostMatchers.componentHostWithText(containsString("My Button")))
        .check(matches(allOf(isDisplayed(), isClickable())));
}

Alternatively, you can match against components by using testKey. testKeys allow you to specify a string for a Component, similar to an Android viewTag, but without sacrificing view flattening. Instead, Litho maintains a separate data structure to keep track of the keys and associated metadata, but only if the end-to-end test mode is enabled through the use of LithoActivityTestRule:

1
2
3
4
5
CustomButton.create(c)
    .text("My Button")
    .testKey("my-button")
    .clickHandler(/* ... */)
    .build();
1
2
3
4
5
@Test
public void testButtonIsDisplayedAndClickableByTestKey() {
    onView(LithoViewMatchers.withTestKey("my-button"))
        .check(matches(allOf(isDisplayed(), isClickable())));
}

Additional Resources

There are plenty of additional matchers available, which you can look up in the API docs:

Edit on GitHub