Creating the Base Scenarios

Introduction

In this section, we will create our base scenarios for simple things like checking the page source contains a given string of text, or checking the context or current activity of our app under test.

Validate a PageSource String on the Android App

Creating the Cucumber Scenario

  1. Open up the ‘BaseScenarios.feature’ file and add the following base test scenario.  We can also add a Cucumber tag either above the ‘Scenario’ (to apply to the specific scenario) or above the ‘Feature’ (to apply to all scenarios within the feature)…

    You should notice that the ‘Given’ and ‘Then’ lines are highlighted.  This is because they do not yet have any step definitions attached to them.

Creating the Undefined Step Definitions

  1. Open up Terminal (or Command Prompt) and ‘cd’ (change directory) in to the root of your Maven or Gradle project…
    cd path/To/ProjectRoot  (change ‘path/To/ProjectRoot’ to local path of your project root)
  2. Enter in  mvn install  or  ./gradlew build
    • The build might give an error but that’s fine for now
  3. Scroll up in the Terminal (or Command Prompt) and you will be able to see the undefined step definition
  4. Copy and paste the undefined ‘Given’ step definition in to the ‘BaseScenariosSteps’ class, it should end up looking like below…
  5. Copy and paste the undefined ‘Then’ step definition in to the ‘ValidationSteps’ class, it should end up looking like below (note that I changed the name of the String parameter to make it more easy to read and understand, this is good practice so you should do the same)…

Creating the Test Methods

We will now create a test method in Java for our step definition that we can then plug in to it ?

First of all, we need to find an element in the Reddit app that we can use to assert that the app has finished loading, by checking if this element is displayed or not. Once it becomes displayed, then we can assume the app has finished loading and continue with the rest of our test.

To view details of elements in an Android app, we can use UIAutomatorViewer.

  1. Open a new Terminal (or Command Prompt) window and change directory (cd) in to your $ANDROID_HOME/tools/bin directory (on Windows it will be %ANDROID_HOME% instead of $ANDROID_HOME)…
    cd $ANDROID_HOME/tools/bin
  2. Launch the UIAutomatorViewer in that /tools/bin directory…
    ./uiautomatorviewer
    It should look similar to below…

    Now let’s launch our Android virtual device (AVD) that we created earlier…
  3. Open up a new Terminal (or Command Prompt) window and change directory (cd) again in to the $ANDROID_HOME/platform-tools directory (again, on Windows it will be %ANDROID_HOME% instead of $ANDROID_HOME)…
    cd $ANDROID_HOME/platform-tools
  4. Type in the following command to launch the emulator…
    emulator -avd yourAvdName (replace ‘yourAvdName’ with whatever you named your AVD, e.g. ‘Nexus5xOreo’)
    The Android Virtual Device should launch and look similar to below…
  5. Drag and drop the Reddit APK file we downloaded earlier on to the Android emulator screen and wait for the app to finish launching, it should look like below when it has…

    Now we can start using UIAutomatorViewer to take a screenshot (so it gets the XML hierarchy of the screen) and then inspect all the elements 🙂
  6. Press the ‘Device Screenshot’ button in the UIAutomatorViewer (as marked below)…

    Once the screenshot is taken, it should look similar to below…

    If you move the mouse around different elements, you can see all the details for them in the right-hand panes 🙂
  7. Click on the “Share, upvote, and discuss the best of the internet” text to see the details for that element…

    If we look at the Node Details for this element, we can see that it has a unique ‘resource-id’, which we can use to find the element by its ID.
  8. Open up the ‘BasePage’ class in the ‘pages’ package and add the following AndroidElement inside the top of the class…

    We will use this element in our test method for ensuring that the app has finished loaded and fully launched.
  9. Open up the ‘BasePage’ class in the ‘pages’ package and add the following method to ensure that the Reddit app has finished loading by waiting until the welcomeMessage Android element is visible…

    Make sure the correct imports exist above the class…
  10. Open up the ‘BasePage’ class in the ‘pages’ package and add the following method to assert that the source of the current app screen contains the given string argument that we passed into the method…

    For the above to work, you will also need to add a getPageSource() method near the top of the class, which returns driver.getPageSource() …

    When we use .getPageSource() method on a native mobile app, it instead gets the XML hierarchy of all the elements on that screen instead of the normal HTML page source given by websites with Selenium etc.

    Additionally, make sure the class contains the following import for the TestNG Assert…

    The whole thing should look similar to below…

Connecting the Step Definitions to the Test Methods

We will now call the test method from the appropriate step definition. This whole Page Objects Model (POM) approach is nice as we have suitable layers of abstraction, which helps the code be easier to read.  It also allows the step definitions to simply contain one line of code calling the test methods.

Due to the method we created earlier in the ‘Page’ class, where we made a generic method called instanceOf<T>() that takes the same generic class and initialises a new object from PageFactory with the correct elements for the page (as well as decorating our elements with the required AppiumFieldDecorator), we can now use that when calling our test methods to always make sure the elements of that page class are initialised first ?

  1. Open up the ‘BaseScenariosSteps’ class again, and refactor the ‘Given’ step definition so it initialises the pages via the instanceOf() method (in this case ‘BasePage’) with the correct elements and then calls the appFullyLaunched() method, like below (also tidy up the method and get rid of the exception that will never be thrown)…

    The whole thing should look like below…
  2. Open up the ‘ValidationSteps’ class again, and refactor the ‘Then’ step definition so it initialises the page (in this case ‘BasePage’) with the correct elements and then calls the validatePageSource() method, like below (also tidy up the method again and get rid of the exception that will never be thrown)…

    The whole thing should look like below…

Validate Existence of Multiple Text in PageSource

Creating the Cucumber Scenario

  1. Open up the ‘BaseScenarios.feature’ file and add the following test scenario…

    You should notice that only the ‘Then’ line is highlighted.  This is because it does not yet have any step definition attached to it, but the ‘Given’ line does, as we have already added code for that scenario line and are simply reusing it in this scenario.

Creating the Undefined Step Definition

  1. Highlight some of the undefined ‘Then’ line in IntelliJ until a yellow lightbulb icon appears next to it
  2. Click the yellow lightbulb icon and select ‘Create step definition’ –> ‘ValidationSteps (steps)’
    • An undefined step definition should be automatically added to ‘ValidationSteps’ like below…

      Edit the undefined step definition so it has a List<String> argument that is passed in to it called ‘existsInPageSource’, it should look similar to below (make sure to add an import java.util.List; at the top)…

Creating the Test Method

We will now create the test method in Java for our undefined ‘Then’ step

  1. Open up the ‘BasePage’ class in the ‘pages’ package and add the following method to assert the PageSource contains the multiple expected strings…

    Ensure the  import java.util.List;  has been added. The whole thing should look like below…

Connecting the Step Definition to the Test Method

  1. Open up the ‘ValidationSteps’ class again, and refactor the ‘Then’ step definition so it initialises the page (in this case ‘BasePage’ again) with the correct elements and then calls the validateMultipleInPageSource() method, like below…

    The whole thing should look like below…

Validate The Current Activity of the App

An activity represents a single screen with a user interface just like window or frame of Java.  Android activity is the subclass of ContextThemeWrapper class.

Getting the Current Activity

  1. Open up the Android Virtual Device and open the Reddit app to the welcome screen again like below…
  2. Open up a new Terminal (or Command Prompt) window and start an ADB shell…
    adb shell
  3. In the ADB shell, enter the following to get a dump of the current foreground activity on your connected Android device…
    dumpsys window windows | grep -E 'mCurrentFocus'

    • You should see text output like  com.reddit.frontpage/com.reddit.frontpage.IntroductionActivity
      • The “.IntroductionActivity” is therefore the current activity for that welcome screen

It is worth noting that Appium actually has a Desired Capability for Android called ‘appActivity‘ which when specified, can start the Android app on the specified activity. In this example, we could specify MainActivity and skip the whole introduction bit. I won’t be doing that in this blog series but thought that it’s at least worth mentioning 😀

With the name of our current activity at hand, let’s begin writing our next test scenario.

Creating the Cucumber Scenario

  1. Open up the ‘BaseScenarios.feature’ file and add the following test scenario…

    You should again notice that only the ‘Then’ line is highlighted.  This is again because it does not yet have any step definition attached to it, but the ‘Given’ line does, as we have already added code for that scenario line and are simply reusing it in this scenario.

Creating the Undefined Step Definition

  1. Highlight some of the undefined ‘Then’ line in IntelliJ until a yellow lightbulb icon appears next to it
  2. Click the yellow lightbulb icon and select ‘Create step definition’ –> ‘ValidationSteps (steps)’
    • An undefined step definition should be automatically added to ‘ValidationSteps’ like below…

      Let’s also rename the String argument to something that makes sense, such as ‘currentActivity’ and get rid of the Throwable which will never be thrown…

      The whole thing should look like below…

Creating the Test Method

We will now create the test method in Java for our undefined ‘Then’ step

  1. Open up the ‘BasePage’ class in the ‘pages’ package and add the following method to assert that the current activity displayed in the foreground of our Android device is the string we pass into the method (e.g. “.IntroductionActivity”)…

    For the above to work, we also need to add a getCurrentActivity() method which returns a String at the top of the class, like below…

    The whole thing should look similar to below…

Connecting the Step Definition to the Test Method

  1. Open up the ‘ValidationSteps’ class again, and refactor the ‘Then’ step definition so it initialises the page (in this case ‘BasePage’ again) with the correct elements and then calls the validateCurrentActivity() method, like below…

    The whole thing should look like below…

Validate The Current Context of the App

The current context of an app screen can either be the native app or it can be a webView. This test will validate that the current context is equal to the string value we pass to it (e.g. ‘NATIVE_APP’ or ‘WEBVIEW_<package name>’)

  1. Open up the ‘BaseScenarios.feature’ file and add the following test scenario…

    You should again notice that only the ‘Then’ line is highlighted.  This is again because it does not yet have any step definition attached to it, but the ‘Given’ line does, as we have already added code for that scenario line and are simply reusing it in this scenario.

Creating the Undefined Step Definition

  1. Highlight some of the undefined ‘Then’ line in IntelliJ until a yellow lightbulb icon appears next to it
  2. Click the yellow lightbulb icon and select ‘Create step definition’ –> ‘ValidationSteps (steps)’
    • An undefined step definition should be automatically added to ‘ValidationSteps’ like below (change the name of the String argument to something more readable too, and get rid of the Throwable that will never be thrown)…

      The whole thing should look like below…

Creating the Test Method

We will now create the test method in Java for our undefined ‘Then’ step

  1. Open up the ‘BasePage’ class in the ‘pages’ package and add the following method to assert the current context is the same as the string value we pass in to the method…

    For the above to work, we also need to add a getCurrentContext() method which returns a String at the top of the class, like below…

    The whole thing should look similar to below…

Connecting the Step Definition to the Test Method

  1. Open up the ‘ValidationSteps’ class again, and refactor the ‘Then’ step definition so it initialises the page (in this case ‘BasePage’ again) with the correct elements and then calls the validateCurrentContext() method, like below…

    The whole thing should look like below…

Running the Base Scenarios

Running the Tests

  1. Open up ‘BaseScenarios.feature’ file and make sure you have the ‘@Nexus5xOreo’ tag at the top of the feature file or above each test scenario you want to run
  2. Right-click on a test scenario and run it

They should all run in your Android Virtual Device and pass 😀

Launching the Reddit app Before each test scenario

If you look at the four base scenarios in your ‘BaseScenarios.feature’ file, you will see that every scenario shares the step of ‘Given the Reddit app has launched’.  Because of this, we can clean up the Feature file a bit by calling the appFullyLaunched() method in our ‘Before’ cucumber hook

  1. Open up the ‘CucumberHooks’ class and edit the ‘Before(@Nexus5xOreo)’ hook to call the ‘appFullyLaunched’ method, after first launching the Android Virtual Device (AVD), like below…
  2. Now we can go back to our ‘BaseScenarios.feature’ file and remove the Given step from all our scenarios…

In the next section, we will create our first proper test and navigate between Page Objects.

Digiprove sealCopyright secured by Digiprove © 2018
Liked it? Take a second to support Thomas on Patreon!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.