learn, learn and learn…

Barista UI Testing(on top of Espresso)

it provides simple implementation and we can avoid lots of boilerplate code.

Runtime Permissions

The new Marshmallow permissions system requires checking for permissions at runtime. As Espresso can’t interact with the system dialog, Barista offers a way to allow permissions when needed.

PermissionGranter.allowPermissionsIfNeeded(Manifest.permission.GET_ACCOUNTS);PermissionGranter.allowPermissionOneTime(Manifest.permission.GET_ACCOUNTS);

Import Barista as a testing dependency

androidTestImplementation('com.adevinta.android:barista:4.2.0') {
exclude group: 'org.jetbrains.kotlin' // Only if you already use Kotlin in your project
}

may need to include which is required by Espresso 3

repositories {
google()
}

API Description:

click widgets

Click widgetsclickOn(R.id.button);
clickOn(R.string.button_text);
clickOn("Next");
clickBack();

Long click widgets

longClickOn(R.id.button);
longClickOn(R.string.button_text);
longClickOn("Next");

Click menu items, with or without overflow

clickMenu(R.id.menu_item);

Open the overflow menu without clicking any item

openMenu();

Writing into widgets

writeTo(R.id.edittext, "A great text"); // Ignores the EditText restrictions like maxLength and textFilter. It's blazing fast.
typeTo(R.id.edittext, "A great text"); // Honors the EditText restrictions like maxLength and textFilter. It slows down the test.
writeToAutoComplete(R.id.autocomplete, "Another great text");
clearText(R.id.edittext

Operate on ListViews and RecyclerViews indistinctly by position

clickListItem(R.id.list, 4);
clickListItemChild(R.id.list, 3, R.id.row_button);
scrollListToPosition(R.id.list, 4);

clickSpinnerItem(R.id.spinner, 1);

Select items on RadioButtons

clickRadioButtonItem(R.id.radiogroup, R.id.radio_item);
clickRadioButtonItem(R.id.radiogroup, "The radio text");
clickRadioButtonPosition(R.id.radiogroup, 42);

Pick data on pickers

setDateOnPicker(1986, 03, 23);
setTimeOnPicker(17, 2);

Interact with dialogs

clickDialogPositiveButton();
clickDialogNeutralButton();
clickDialogNegativeButton();

Scroll on scrolls and pagers

scrollTo(R.id.far_away_widget);
scrollTo(R.string.text);
scrollTo("A widget with this text");
scrollTo(withTagValue(is("tagName"))) // using custom matchers
swipeViewPagerForward();
swipeViewPagerBack();

Interact with the navigation drawer

openDrawer();
openDrawerWithGravity(Gravity.RIGHT);
closeDrawer();
closeDrawerWithGravity(Gravity.RIGHT);

Interact with SeekBars

setProgressTo(R.id.seek_bar, 5);
setProgressToMin(R.id.seek_bar);
setProgressToMax(R.id.seek_bar);

Close or press the actions on the Keyboard

closeKeyboard()
pressImeActionButton()

And another tricky feature, but try not to use it

sleep(2000);
sleep(2, SECONDS);

Barista’s Assertions API:-

Is this view displayed?

assertDisplayed("Hello world");
assertDisplayed(R.string.hello_world);
assertDisplayed(R.id.button);
assertDisplayed(R.id.button, "Hello world")
assertDisplayed(R.id.button, R.string.hello_world)

// on ListViews and RecyclerViews by position
assertDisplayedAtPosition(R.id.list, 0, "text");
assertDisplayedAtPosition(R.id.list, 0, R.id.text_field, "text");
assertDisplayedAtPosition(R.id.list, 0, R.string.hello_world);
assertDisplayedAtPosition(R.id.list, 0, R.id.text_field, R.string.hello_world);
assertDrawableDisplayedAtPosition(R.id.recycler, 0, R.id.imageview, R.drawable.ic_barista);

// you can also pass custom matchers
assertDisplayed(withTagValue(is("tagName")))

// ...or not?
assertNotDisplayed("Hello world");
assertNotDisplayed(R.string.hello_world);
assertNotDisplayed(R.id.button);
assertNotDisplayed(R.id.button, "Hello world")
assertNotDisplayed(R.id.button, R.string.hello_world)
// you can also pass custom matchers
assertNotDisplayed(withTagValue(is("tagName")))

Is this view enabled?

assertEnabled("Hello world");
assertEnabled(R.string.hello_world);
assertEnabled(R.id.button);

// ...or not?
assertDisabled("Hello world");
assertDisabled(R.string.hello_world);
assertDisabled(R.id.button);

Hope this view doesn’t exist!

assertNotExist("Hello world");
assertNotExist(R.string.hello_world);
assertNotExist(R.id.button);

Is the expected checkbox checked?

assertChecked("Checked checkbox");
assertChecked(R.string.checked_checkbox);
assertChecked(R.id.checkbox);

// ...or not?
assertUnchecked("Unchecked checkbox");
assertUnchecked(R.string.unchecked_checkbox);
assertUnchecked(R.id.checkbox);

Is this view clickable?

assertClickable("Hello world")
assertClickable(R.string.hello_world)
assertClickable(R.id.button)

// ...or not?
assertNotClickable("Hello world")
assertNotClickable(R.string.hello_world)
assertNotClickable(R.id.button)

Does this view have the focus?

assertFocused(R.id.focused_view)
assertFocused("Button")

// ...or not?
assertNotFocused(R.id.focused_view)
assertNotFocused("Button")

Is this ImageView showing a drawable?

assertHasAnyDrawable(R.id.image_view);
assertHasDrawable(R.id.image_view, R.drawable.ic_barista);

// ...or not?
assertHasNoDrawable(R.id.image_view);

Does this View have a background?

assertHasAnyBackground(R.id.view);
assertHasBackground(R.id.view, R.drawable.ic_barista);

// ...or not?
assertHasNoBackground(R.id.view);

Does this View have a content description?

assertHasContentDescription(R.id.anyView);
assertContentDescription(R.id.anyView, R.string.content_description);
assertContentDescription(R.id.anyView, "Some text");

Is this List empty? How many items does it have?

assertListNotEmpty(R.id.list)
assertListItemCount(R.id.list, 5)

// You can also pass custom assertions
assertCustomAssertionAtPosition(R.id.list, 0, customViewAssertion);

Check if the text on-screen contains given text

assertContains("text");
assertContains(R.string.text);
assertContains(R.id.textview, "text");
assertContains(R.id.textview, R.string.text);

// ...or not?
assertNotContains("text");
assertNotContains(R.string.text);
assertNotContains(R.id.textview, "text");
assertNotContains(R.id.textview, R.string.text);

Check text is given color

assertTextColorIs(R.id.some_red_text, R.color.red);
assertTextColorIs(R.id.some_color_list_text, R.color.state_list);
// ...or not?
assertTextColorIsNot(R.id.some_red_text, R.color.blue);
assertTextColorIsNot(R.id.some_color_list_text, R.color.another_state_list);

assertTextColorIs and it's variant assertTextColorIsNot work with:

  • Color int: Color.parse("#ff00ff")
  • Color resource: R.color.green
  • Color attribute: R.attr.colorPrimary

Also, Barista can check colors parsed from declarable-style custom attribute:

assertTextColorIs(R.id.customTextView, R.styleable.SampleCustomView, R.style.SampleCustomStyle, R.styleable.SampleCustomView_customColor);// ...or not?
assertTextColorIsNot(R.id.customTextView, R.styleable.SampleCustomView, R.style.SampleCustomStyle_Green, R.styleable.SampleCustomView_customColor);

Check recycler view item count against expected item count

assertRecyclerViewItemCount(R.id.recycler, 10);

Is this ProgressBar/SeekBar progress?

assertProgress(R.id.seek_bar, 5)
assertProgressIsMin(R.id.seek_bar)
assertProgressIsMax(R.id.seek_bar)

And another tricky feature

assertThatBackButtonClosesTheApp();

Custom assertions

by using custom assertion API you can replace plain Matchers with complex assertions. With Barista, you can match any kind of view by knowing its type and passing its viewId, text, or a Matcher<View>. Once you matched it, you will be able to assert all its properties without adding any complex Matcher to your project.

Mocking the Intent results

Mocking the Android Camera Intent is a tricky thing to do. To accomplish it in no time, Barista gives a way to do it in one line: the method mockAndroidCamera(). This method does all the magic to mock the result of the camera. One more thing to do: you have to call Intents.init() before calling mockAndroidCamera(), and Intents.release() after doing the action that launches the camera. You could also use IntentsTestRule instead of the common ActivityTestRule to skip it, but as we recommend the use of BaristaRule, it's easier to just call both methods manually when needed.

for exm:

try {
Intents.init();
BaristaIntents.mockAndroidCamera();
clickOn(R.id.launch_camera);
} finally {
Intents.release();
}

Useful test rules

Barista includes a set of useful test rules to help you:

Resetting app data

As tests should be isolated, they need to set the environment before running. Espresso doesn’t help achieve it but Barista offers a set of rules to clear the app’s data before running each test.

// Clear all app's SharedPreferences
@Rule public ClearPreferencesRule clearPreferencesRule = new ClearPreferencesRule();
// Delete all tables from all the app's SQLite Databases
@Rule public ClearDatabaseRule clearDatabaseRule = new ClearDatabaseRule();
// Delete all files in getFilesDir() and getCacheDir()
@Rule public ClearFilesRule clearFilesRule = new ClearFilesRule();

One rule to rule them all

All previous rules can be added at the same time by just adding the BaristaRule.

@Rule
public BaristaRule<MyActivity> baristaRule = BaristaRule.create(MyActivity.class);

//...

baristaRule.launchActivity();

https://github.com/AdevintaSpain/Barista GitHub link for detailed information.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Prachi Mishra

Prachi Mishra

I am an Android Developer. Working for BMW group. In my development path if I find something interesting I like to share with you guys. Happy coding…