Mastering UI automation at Scale: Key Lessons and Best Practices (By Fernando Martin)

Post on 14-Apr-2017

384 views 1 download

Transcript of Mastering UI automation at Scale: Key Lessons and Best Practices (By Fernando Martin)

UI Automation at ScaleAugmented Driver

fernando@split.io

A little bit about me● Started working @Google in late 2006.

A little bit about me● Started working @Google in late 2006. ● Selenium/Webdriver started becoming a “thing” sometime in 2007.

A little bit about me● In 2010 I joined Medallia.

A little bit about me● In 2010 I joined Medallia.● Super excited about building UI automation from scratch.

A little bit about me● In 2014 moved to RelateIQ (Now SalesforceIQ)

A little bit about me● In 2014 moved to RelateIQ (Now SalesforceIQ)● Again a Start Up, being part of a small team that wanted to have a big

impact in the company.

A little bit about me● Finally a couple of months ago I joined Split.IO.

A little bit about me● Finally a couple of months ago I joined Split.IO● Being one of the first Software Engineers, again with the role of shipping

code as fast as we can with the best Customer Experience as we can.

Episode IWebDriver tests are inherently slow. If you want throughput, you need to focus on parallelism, leading us to the first lesson in this saga.

Episode I: Data Independent TestsIf each test creates its own data that is not shared with anyone else, then all of your tests can run in parallel.

To the code!@Path(“/test”)public class TestResource {

@Post@Path(“create”)public Response create(String uniqueUser) {

If (isProd()) { throw new NotAllowedException(“NOT ALLOWED”); }//… create unique user, organization, etc...//...

}@Post@Path(“clean”)public Response clean(String uniqueUser) {

If (isProd()) { throw new NotAllowedException(“NOT ALLOWED”);}//…clean unique user, organization, etc...//...

}}

To the code!public class DataCreatorRule implements TestRule {

public Statement apply(Statement statement, Description description) {return new Statement() {

@Overridepublic void evaluate() throws Throwable {

String uniqueUser = "uniqueuser";client

.test()

.create(uniqueUser);statement.evaluate();client

.test()

.clean(uniqueUser);}

}}

}

To the code!public abstract class BaseTestCase {

@Rulepublic DataCreatorRule dataCreatorRule = new DataCreatorRule();

}

Alternatives● @BeforeMethod and @AfterMethod in TestNG.● @Before and @After in JUnit < 4.● beforeEach() and afterEach() in Jasmine JS.● setUp(self) and tearDown(self) in Python.

Episode I Code Example

Episode IIThroughput is achieved with Parallelism. With that in mind, you need to build reliable tests in all possible Environments.

Local != Staging != SauceLabs.

This leads to the second lesson...

Episode II: Slow and Steady Wins the RaceFailures are caused by elements not showing up in time. In general, when the element has an unexpected transient state when the action is being performed.

To the code!private final Webdriver driver;

public void ohWhy(By identifier) {

Thread.sleep(3000);

WebElement element = driver.findElement(identifier);

element.click();

}

To the code!private final Webdriver driver;

public void better(By identifier) {

WebDriverWait wait = new WebDriverWait(driver, 10);

WebElement element = wait.until(ExpectedConditions.elementToBeClickable(identifier);

element.click();

}

To the code!private final AugmentedWebDriver driver;

public void augmentedWay(By identifier) {

driver

.augmented()

.findElementClickable(identifier)

.click();

}

More...driver.augmented().findElementVisible(id);

driver.augmented().findElementsVisible(id).get(0)

.augmented().findElementClickable(id2).click();

driver().augmented().clickAndSendKeys(id, “text”);

driver().augmented().swipeDown(id);

Episode II Code Example

Episode III.● Your tests can run in parallel...● You can wait until elements are on a desired state...

Time to encapsulate you tests in business logic to maximize reusability and maintainability.

This leads to the third lesson...

Episode III: Follow the Page Object ModelNeed to encapsulate the logic of the UI areas that your tests performs actions, for maintainability and for many other reasons.

To the code!public class MainPage extends WebPageObject {

@Override

public Optional<By> visibleBy() {

return Optional.of(Bys.INPUT);

}

public static class Bys {

public static class By INPUT = By.id("searchInput");

}

}

To the Code!public class BaseCase extends AugmentedWebTestCase {

public MainPage mainPage() {

driver().get(“https://www.wikipedia.org”);

Return get(MainPage.class);

}

}

Episode III Code Example

Episode IV● Your tests can run in parallel...● You can wait until elements are on a desired state...● You have your framework encapsulated on business logic…

The next level is to wait and expect certain business logic to take place when actions are performed.

That leads to…

Episode IV: Wait and Expect for business logicThis is an extension of the Episode 2 but at a much higher level that each app defines.

Episode IV: Wait and Expect for business logicSince now we have Page Objects that encapsulate business logic, we can perform “waiters” that will wait until certain condition is fulfilled.

To the Code!public class MainPage extends WebPageObject {

public int numberOfSuggestions() {

return driver()

.augmented()

.findElementSSSSVisible(Bys.SUGGESTION)

.size();

}

public static class Bys {

public static final By SUGGESTION = By.className("suggestion-link");

}

}

To the Code! @Test

public void test() {

mainPage

.search("WebDriver");

waiter().waitUntil(mainPage, page -> page.numberOfSuggestions() > 3);

}

Episode IV Code Example

Episode V● Your tests can run in parallel...● You can wait until elements are on a desired state...● Your business logic is encapsulated...● You can wait for business logic to be fulfilled…

Now each test has maintainability and reliability in mind. It’s time to consolidate each individual piece into something that the rest of the team can easily digest it.

Episode V: Reporting Reporting ReportingThis has one basic lesson learned:

Episode V

DON’T

Episode V Code Example

Episode VI● Your tests can run in parallel...● You can wait until elements are on a desired state...● Your business logic is encapsulated...● You can wait for business logic to be fulfilled…● You have a way to have visibility and transparency

Finally the last step is to provide easy configuration and integrations so it can be plugged into CI systems

Episode VI: Integrations and Easy ConfigurationIt should be easy and straightforward to integrate into different tools.

Episode VI Code Example

Thanks!Augmented Driver: https://github.com/relateiq/AugmentedDriver

Split.IO: http://www.split.io/

Special offer by Applitools:

50-page guidebook to visual testing (including tips, tricks and code examples), written by Selenium expert Dave Haeffner.

Claim your free copy by sending an email to webinars@applitools.com