/espresso-page-object

Primary LanguageKotlinApache License 2.0Apache-2.0

Attention! This project is deprecated. Active development has been moved to Ultron. It has much more abilities and power.

Espresso page object

Download Android CI

This library provides access to nice and simple DSL for Espresso framework. It allows you to write simple and stable UI tests for Android application. Moreover, you don't need to learn any new classes or special syntax. All magic actions and assertions are provided from crunch. Library can be easy customised and extended by advanced user. Wish you only stable tests!

Russian README is here

What are the benefits of using the library?

  • Simple and presentative syntax
  • Stability of all actions and assertions
  • Full control under any action and assertion
  • An architectural approach to writing tests

A few words about syntax

The standard Espresso syntax is complex and not intuitive to understand. This is especially evident when interacting with the RecyclerView

Let's look at 2 examples:

1. Click on simple button.

Clear Espresso

onView(withId(R.id.send_button)).perform(click())

Espresso page object

withId(R.id.send_button).click()

2. Click on RecyclerView list item

Clear Espresso

onView(withId(R.id.recycler_friends))
    .perform(
        RecyclerViewActions
            .actionOnItem<RecyclerView.ViewHolder>(
                hasDescendant(withText("Janice")),
                click()
            )
        )

Espresso page object

withRecyclerView(withId(R.id.recycler_friends))
    .atItem(hasDescendant(withText("Janice")))
    .click()

You can get the result of any operation as boolean value

val isButtonDisplayed = withId(R.id.button).isSuccess { isDisplayed() }
if (isButtonDisplayed) {
    //do some reasonable actions
}

You can get the result of any operation and process it by yourself

val isButtonDisplayed = withId(R.id.button).click { result ->
    success = result.success
    exception = result.exception
    description = result.resultDescription
}

Cool features

3 steps to write a test using espresso-page-object

I try to advocate the correct construction of the test framework architecture, the division of responsibilities between the layers and other correct things.

Therefore, I would like to recommend the following approach when your are using the library.

  1. Create a PageObject class and specify screen UI elements Matcher<View>.
object ChatPage : Page<ChatPage>() {
    private val messagesList = withId(R.id.messages_list)
    private val clearHistoryBtn = withText("Clear history")
    private val inputMessageText = withId(R.id.message_input_text)
    private val sendMessageBtn = withId(R.id.send_button)
}

Some elements like chat title could be determined dynamically with application data. In this case you need to add a method in PageObject class which will return Matcher<View> object.

object ChatPage : Page<ChatPage>() {
    private fun getTitle(title: String): Matcher<View> {
        return allOf(withId(R.id.toolbar_title), withText(title))
    }
}

It's recommended to make all PageObject classes as object and descendants of Page class. In this case you will be able to use cool kotlin magic.

  1. Describe user step methods in PageObject class.
object ChatPage : Page<ChatPage>() {
    fun sendMessage(text: String) = apply {
        inputMessageText.typeText(text)
        sendMessageBtn.click()
        this.getListItem(text).text
            .isDisplayed()
            .hasText(text)
    }

    fun clearHistory() = apply {
        openOptionsMenu()
        clearHistoryBtn.click()
    }
}

Full code sample ChatPage.class

  1. Call user steps in test
    @Test
    fun friendsItemCheck(){
        FriendsListPage {
            assertName("Janice")
            assertStatus("Janice","Oh. My. God")
        }
    }
    @Test
    fun sendMessage(){
        FriendsListPage.openChat("Janice")
        ChatPage {
            clearHistory()
            sendMessage("test message")
        }
    }

Full code sample DemoEspressoTest

Use RuleSequence + SetUpTearDownRule to prepare test data.

In general, it all comes down to the fact that the architecture of your project will look like this.

Architecture

Add to your project

Gradle

repositories {
    jcenter()
}

dependencies {
    androidTestImplementation 'com.atiurin.espresso:espressopageobject:0.1.19'
}

Maven

<dependency>
  <groupId>com.atiurin.espresso</groupId>
  <artifactId>espressopageobject</artifactId>
  <version>0.1.19</version>
  <type>pom</type>
</dependency>

Version 0.1.17 has a new internal structure and you need to make minor changes in your project to migrate on it. Read more info Migration to 0.1.17

AndroidX

It is required to use AndroidX libraries. You can get some problems with Android Support ones.