Espresso automation framework meant to replicate MVVM pattern (https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93viewmodel), where framework is compotentized in
Helpers(for locators interaction)
Screens (containing the locators with other methods)
Test scripts (performing and validating the e2e flow)
Tools needed to be installed on the machine
Java 11 (Other version of Java might not work)
Maven
Android Studio
Setup Steps
Clone the Espresso branch from repo
Open the project in Android studio
Open the terminal
Run command `./gradlew build`
It will take some time to install all dependencies, based on your network bandwidth and processing power
To run all UI tests use command `./gradlew connectedAndroidTest`
Understanding framework components
Now this `automation` package contains our Espresso based framework
In `tests` package, we are having all our UI tests
We have BaseTest class to setup the `Before` hook, to clean DB
All UI test classes inherit this class
The `screens` package contains all Screen class replicating each screen of the app. Screen class initializes all helper class, which can be used in derived screen class or test
The Helper package contains helper classes to provide method to deal with UI, DB and other utilities
The `annotations` package to create custom annotation for the test
Getting locators (In Espresso terms, views)
Android Studio has a inbuilt tool, Layout Manager for detecting view on app layout
Working with Layout Manager - got to the Tools menu and click the `Layout Manager` menu item. Start an emulator and open the debuggable app for which you want to capture views
On one side of layout manager component can be observed while other side we can view properties
Now, here is the cheat sheet using we can create view matcher (please see user properties) from the properties of the view https://developer.android.com/training/testing/espresso/cheat-sheet
Writing Screen classes -
Any screen will inherit Screen class, so that Locator, Action and Validators becomes available to them and it has two essential parts described below
Label property object, which will be formatted as
companion object {
// Labels locator
const val EXPANDED_VIEW_BUTTON_TEXT = "Expanded View - ButtonText"
const val REDUCED_VIEW_BUTTON_TEXT = "Reduced View - ButtonText"
const val LEFT_MENU_BUTTON = "Left Menu - Button"
}The label vale format should be “<App identifier view name> - <Type of view>”
Two component with initializing the label map
init {
locators.put(EXPANDED_VIEW_BUTTON_TEXT,
Locator(EXPANDED_VIEW_BUTTON_TEXT,
ViewMatchers.withText(R.string.expanded_view)))
locators.put(REDUCED_VIEW_BUTTON_TEXT,
Locator(REDUCED_VIEW_BUTTON_TEXT,
ViewMatchers.withText(R.string.contracted_view)))
locators[LEFT_MENU_BUTTON] = Locator(LEFT_MENU_BUTTON,
Matchers.allOf(ViewMatchers.withContentDescription("drawer open"),
ViewHelper.getChildAtPosition(Matchers.allOf(ViewMatchers.
withId(R.id.toolbar),
ViewHelper.getChildAtPosition(ViewMatchers.withClassName
(Matchers.`is`("android.widget.RelativeLayout")), 0)), 1), ViewMatchers.isDisplayed()))
}Where we are adding new entries in `locator` map
Locator map use `Label` as key view as key value
Now we can define page object methods in page class
private fun openDrawer() {
Action.perform(LEFT_MENU_BUTTON)
}
Writing the Test script
Test script would be automated steps to replicate the manual test case and feature, Every Test class will be inheriting Basetest
Example class -
class NotesListTest : BaseTest() {
@Test
fun switchExpandedCollapsedNoteLayoutTest() {
sharedPreferences?.edit()?.putBoolean(Constants.PREF_EXPANDED_
VIEW, true)?.apply()
createNote()
noteListView?.Menu?.clickOverflowMenuButton()
noteListView?.Menu?.Validator?.validate("Reducedview",
StateType.DISPLAYED)
noteListView?.Menu?.Action?.perform(NoteListMenuViewScreen.
REDUCED_VIEW_BUTTON_TEXT)
noteListView?.Menu?.clickOverflowMenuButton()
noteListView?.Menu?.Validator?.validate("Expanded view"
, StateType.DISPLAYED)
}
}
Validate will be done via Validator class methods
Execution -
To run all connected android test use `./gradlew connectedAndroidTest`
To run one test class `./gradlew connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=<Class-Reference>`
You can also, mark your tests with annotations, `./gradlew connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=<path-to-annotation>