NAV
java

What is Augmented Driver?

Augmented Driver is a framework for writing E2E Tests in JAVA, based on WebDriver/Appium.

Augmented Driver in Github
Detailed Wiki
Web Example

Why Augmented Driver?

The whole framework aims to simplify 3 aspects of writing JAVA E2E tests using WebDriver/Appium:

Where is Augmented Driver?

To import it:

compile 'com.salesforceiq.augmenteddriver:AugmentedDriver:1.0.+'

Augmented Driver is in Maven Central

Augmented Driver in 5 minutes

Configuration - The Properties file

augmented.properties:

LOCAL_ADDRESS=http://127.0.0.1:7777/wd/hub  
WAIT_TIME_IN_SECONDS=30  
MAX_RETRIES=2  

You need to define a properties file (by default should reside in conf/augmented.properties, but it can be set with the -conf parameter).

Later in this conf file you will enable the integrations, and set the properties needed to run it in SauceLabs.

WAIT_TIME_IN_SECONDS defines how much time it will be waited until an element is present|visible|clickable. If you do not set it, it defaults to 30.

MAX_RETRIES defines how many times a test of a suite will be retried in case of failiure. if it is set to 2, the first failure will be ignored. If it fails again, then the test is considered failed. This helps since WebDriver will have the eventual crash or eventual lagginess of the application. If you do not set it in the properties file, it defaults to 2.

Configuration - Desired Capabilities

capabilities/chrome.yaml:

capabilities: "chrome"  

The other piece of configuration is a yaml with the capabilites:

Later in this yaml file you will set the browser/device properties, for running it in saucelabs.

Web Page Object for the Test.

This tutorial is based on this Web Example, that it performs a basic search in WikiPedia.

Search.java:

public class Search extends WebPageObject {
    @Override
    public Optional<By> visibleBy() {
        return Optional.of(Bys.INPUT);
    }

    public WikiPage searchAndGo(String searchText) {
        augmented().findElementClickable(Bys.INPUT).sendKeys(searchText);
        augmented().findElementClickable(Bys.BUTTON).click();
        return get(WikiPage.class);
    }

    private static class Bys {
        private static final By INPUT = By.id("searchInput");
        private static final By BUTTON = By.name("go");
    }
}

A Page Object in the framework is defined by extending WebPageObject.

This example is about Search, that is the main page of www.wikipedia.org.

Basically, we assert that we are on the Main Search Page if the Search input is visible (defined in visibleBy()). It has one functionality, searchAndGo(String), that types the input parameter in the search box, clicks on the search button and goes to the WikiPage Page Object.

If visibleBy() returns Optional.empty() there will be no checks when going from one PageObject to another.

The WebPageObject has the driver() that has all the functionality of a WebDriver and it has augmented() that contains extra functionality on top of WebDriver, in this case, finds an element, but wait until it is clickable. (Augmented Web Functionality).

Whether it is for Web, for IOS or Android, there are different augmented functionalities that help you making your tests less prone to sporadic failures.

The Actual Test.

@Suites(WebSuites.SMOKE)
public class ExampleTest extends AugmentedWebTestCase {

    @Test
    public void searchForSalesforceIQInWiki() {
        driver().get("https://www.wikipedia.org/");
        WikiPage wiki = get(Search.class)
                                    .searchAndGo("SalesforceIq");
        Assert.assertEquals("SalesforceIQ", wiki.getTitle());
        assertElementContains(WikiPage.Bys.HEADING, "SalesforceIQ");
    }

    @Test
    public void searchForSalesforceInWiki() {
        driver().get("https://www.wikipedia.org/");
        WikiPage wiki = get(Search.class)
                                    .searchAndGo("Salesforce.com");
        Assert.assertEquals("Salesforce.com", wiki.getTitle());
        assertElementContains(WikiPage.Bys.HEADING, "Salesforce.com");
    }
}

get(<? extends WebPageObject>) is the preferred methodology for traversing from one PageObject to another, internally it makes sure that the element defined in visibleBy() is present, ensuring the page is in the right place.

Run One Test

To run the example test:

com.salesforceiq.augmenteddriver.runners.TestMethodRunner 
-clazz com.salesforceiq.example.ExampleTest -test searchForSalesforceIQInWiki  
-capabilities capabilities/chrome.yaml -quantity 3 -parallel 3  

To run one test, you need to run the class com.salesforceiq.augmenteddriver.runners.TestSuiteRunner with parameters:
* -clazz: the class name of the test.
* -test: the test name.
* -capabilities: path to the yaml file.
* -quantity: (Defaults to 1) how many times to run the test.
* -parallel: (Defaults to 1) how many tests in parallel will be run.
* -conf: (Defaults to conf/augmented.properties) the properties file.

In the Web Example Repo, there are shell scripts for unix based systems that are capable of running a test

Run a Suite

To run the example suite:

com.salesforceiq.augmenteddriver.runners.TestSuiteRunner  
-suites SMOKE -suitesPackage com.salesforceiq.example  
-capabilities capabilities/chrome.yaml

To run a sute you need to run the class com.salesforceiq.augmenteddriver.runners.TestSuiteRunner with parameters:
* -suites: comma separated list of suites to run.
* -suitesPackage: the base package where the suites reside.
* -capabilities: path to the yaml file.
* -parallel: (Defaults to 1) how many tests in parallel will be run.
* -conf: (Defaults to conf/augmented.properties) the properties file.

In the Web Example Repo, there are shell scripts for unix based systems that are capable of running a suite

Run it in Saucelabs.

Add the parameter -sauce to TestMethodRunner or TestSuiteRunner and some simple configuration and that is all!.

Properties File.

conf/augmented.properteis:

SAUCE_ADDRESS=http://ondemand.saucelabs.com:80/wd/hub  
LOCAL_ADDRESS=http://127.0.0.1:7777/wd/hub  
MAX_RETRIES=2  
WAIT_TIME_IN_SECONDS=30  
SAUCE_USER=yourUser
SAUCE_KEY=yourPassword

For running in saucelabs, you only need to set SAUCE_USER, SAUCE_KEY in augmented.properties.

SAUCE_ADDRESS defaults to http://ondemand.saucelabs.com:80/wd/hub if not set.

Desired Capabilities

capabilities/chrome.yaml:

capabilities: "chrome"
platform: "OS X 10.10"
version: "46.0"
screenResolution: "1280x1024"

Set the desired capabilities as explained in Platform Configuration in the yaml file:

Last thoughts

Here at SalesforceIQ, using this framework we are currently running 250+ tests (Web, IOS and Android) in parallel, in less than 15 minutes.
The process we follow is that each new test before it is sumbitted, it has to run and pass 10 times in our CI system. With that in mind, and making sure we follow the Page Object Model (and with help from SauceLabs), we have been able to scale our E2E coverage for Web, IOS and Android.

Integrations

The framework integrates with SauceLabs (explained above) and with the CI TeamCity. To get the reports in TeamCity, simple set TEAM_CITY_INTEGRATION=true in the conf properties files. We have plans to provide more integrations. Also there is an idea of extending a JUnit Runner so it might automatically integrate with any CI system.

Dependency Injection

The framework uses Guice for Dependency Injection. It is highly encouraged to keep using it. Extra Guice Modules can be injeced with the @ExtraModules annotation.