Part 7: Search Results test on Android

Now, we want to have the same search results related test on Android.

We can start by creating page classes for Android specific Home and SearchResults page.

Create Android specific page classes

We can create a new folder pages/android and add the home.page.ts and search-results.page.ts files in it.

Similar to the web specific pages, the android HomePage would extends the parent HomePage and the android SearchResultsPage would extend the parent SearchResultsPage.

Finding Locators

To find the element locators for Android, we could make use of Appium Inspector. The setup instructions are present in the readme file.

We can find the locators from the element hierarchy as shown below.

The search box locator is id:book_name, the search button locator is id:search_books and the search result title locator is id:title.

Method implementation in Android page classes

The android specific home page will implement the searchBooks method.

On the web, we enter search term and press Enter.
On Android, we need to enter search term and then click on the search books button. We can handle this difference in the android specific method.

The class looks like this.

import { findElement } from '../../helpers/element.helper';
import BaseHomePage from '../parent/home.page';

const searchBoxLocator = 'id:book_name';
const searchButtonLocator = 'id:search_books';

export default class HomePage extends BaseHomePage {
  async searchBooks(searchTerm: string): Promise<void> {
    const searchBox = await findElement(searchBoxLocator);
    await searchBox.setValue(searchTerm);

    const searchButton = await findElement(searchButtonLocator);
    await searchButton.click();
  }
}

Similarly, the Android search-results.page.ts looks like this. Note that the search results take longer to load on Android as compared to web. So, we can mention the wait time to be Medium instead of the default value of Small while waiting for the titles to be displayed.

import { WaitTime } from '../../constants/wait-time';
import { findElements } from '../../helpers/element.helper';
import BaseSearchResultsPage from '../parent/search-results.page';

const bookTitleLocator = 'id:title';

export default class SearchResultsPage extends BaseSearchResultsPage {
  async getSearchResultTitles(): Promise<string[]> {
    const titleElements: WebdriverIO.Element[] = await findElements(bookTitleLocator, WaitTime.Medium);
    const titlePromises = titleElements.map(async element => element.getText());
    return Promise.all(titlePromises);
  }
}

Handling of these kind of differences between different platforms is possible easily because we have platform specific page classes.

Running the Android test

We can run the android test by passing the correct app path in the test run command:

npm run test:app:android -- --app_path=/Users/lavanya/projects/demo/book-info-e2e-tests/resources/book-info.apk --devices='emulator-5554'

If the tests run successfully, we'll get a report like this:

Current Code Structure

  • We have features and corresponding step definitions.

  • The step-definitions use page factory to get the required page objects. The type of the object is always the parent type.

  • Features and step-definitions are platform agnostic i.e. they do not contain platform-specific logic and can be used by all platforms.

  • Pages are platform specific and contain details of "how" to perform actions on that platform.

A simplistic view of the code structure is below:

Recap