Espresso is Android UI testing support library. It’s small and easy to use. Here what we can do with Expresso.
https://google.github.io/android-testing-support-library/docs/espresso/cheatsheet/
Create new project
Create simple login screen look like below called LoginActivity.
Here activity_login.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.bananacoding.expressologin.LoginActivity"> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <android.support.design.widget.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <EditText android:id="@+id/tv_email" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/prompt_email" android:inputType="textEmailAddress" android:maxLines="1" android:singleLine="true" /> </android.support.design.widget.TextInputLayout> <android.support.design.widget.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <EditText android:id="@+id/tv_password" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/prompt_password" android:imeActionId="@+id/login" android:imeActionLabel="@string/action_login" android:imeOptions="actionUnspecified" android:inputType="textPassword" android:maxLines="1" android:singleLine="true" /> </android.support.design.widget.TextInputLayout> <Button android:id="@+id/btn_login" style="?android:textAppearanceSmall" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:text="@string/action_login" android:textStyle="bold" /> </LinearLayout> </ScrollView> </LinearLayout>
Setup Expresso
defaultConfig { .... testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } dependencies { ... androidTestCompile 'com.android.support.test:runner:0.5' androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2' }
Create test class called LoginActivityTest and runner annotation.
@RunWith(AndroidJUnit4.class) public class LoginActivity { }
Add activity test rule.
@Rule public ActivityTestRule<LoginActivity> activityRule = new ActivityTestRule<>(LoginActivity.class);
*Note make sure you create the test class at src/androidTest/java not src/test/java
Let’s add the test
When we do not fill anything in email and password then press the login button, it will show the error message.
You will think, Expresso does not have ViewMatchers for error message. How we check the error message of the EditText?
If it does not have, just create it!.
Create new custom view matchers called withError
.
private static Matcher withError(final String expected) { return new TypeSafeMatcher() { @Override protected boolean matchesSafely(View item) { if (item instanceof EditText) { return ((EditText)item).getError().toString().equals(expected); } return false; } @Override public void describeTo(Description description) { description.appendText("Not found error message [" + expected + "]"); } }; }
We need to implement matchesSafely method, to match error message of EditText.
So we can use it write a test like this.
@Test public void emailIsEmpty() { onView(withId(R.id.tv_email)).perform(clearText()); onView(withId(R.id.btn_login)).perform(click()); onView(withId(R.id.tv_email)).check(matches(withError("This field is required"))); }
Also, when password is empty.
@Test public void passwordIsEmpty() { onView(withId(R.id.tv_email)).perform(typeText("email@email.com"), closeSoftKeyboard()); onView(withId(R.id.tv_password)).perform(clearText()); onView(withId(R.id.btn_login)).perform(click()); onView(withId(R.id.tv_email)).check(matches(withError("This field is required"))); }
When email is invalid, it will show the error message.
@Test public void emailIsInvalid() { onView(withId(R.id.tv_email)).perform(typeText("invalid"), closeSoftKeyboard()); onView(withId(R.id.btn_login)).perform(click()); onView(withId(R.id.tv_email)).check(matches(withError("This email address is invalid"))); }
When password is too short, it will show the error message.
@Test public void passwordIsTooShort() { onView(withId(R.id.tv_email)).perform(typeText("email@email.com"), closeSoftKeyboard()); onView(withId(R.id.tv_password)).perform(typeText("1234"), closeSoftKeyboard()); onView(withId(R.id.btn_login)).perform(click()); onView(withId(R.id.tv_password)).check(matches(withError("This password is too short"))); }
When username or password incorrect, will show toast message.
@Test public void loginFailed() { onView(withId(R.id.tv_email)).perform(typeText("incorrect@email.com"), closeSoftKeyboard()); onView(withId(R.id.tv_password)).perform(typeText("123456"), closeSoftKeyboard()); onView(withId(R.id.btn_login)).perform(click()); onView(withText("Your email or password was incorrect. Please try again.")) .inRoot(withDecorView(not(activityTestRule.getActivity().getWindow().getDecorView()))) .check(matches(isDisplayed())); }
When login successfully, will open new activity, show welcome message and show toast message.
My suggestion is split it two tests. First, for check welcome message is display correctly.
@Test public void loginSuccessfully_shouldShowWelcomeMessage() { onView(withId(R.id.tv_email)).perform(typeText("user@email.com"), closeSoftKeyboard()); onView(withId(R.id.tv_password)).perform(typeText("123456"), closeSoftKeyboard()); onView(withId(R.id.btn_login)).perform(click()); onView(withId(R.id.tv_welcome)).check(matches(withText("Hi user@email.com!"))); }
Second, check toast message was shown up.
@Test public void loginSuccessfully_shouldShowToast() { onView(withId(R.id.tv_email)).perform(typeText("user@email.com"), closeSoftKeyboard()); onView(withId(R.id.tv_password)).perform(typeText("123456"), closeSoftKeyboard()); onView(withId(R.id.btn_login)).perform(click()); onView(withText("Login successfully.")) .inRoot(withDecorView(not(activityTestRule.getActivity().getWindow().getDecorView()))) .check(matches(isDisplayed())); }
Run test by click on green arrow in font of test class or execute following command.
./gradlew connectedAndroidTest
*Note we need to use emulator or device to run Expresso test.
Here the result.
Source code: Github
for more information: https://google.github.io/android-testing-support-library/
Comments are closed.