my test automation journey

33
My Test Automation Journey 2015 Vera Djakova & Vaidas Pilkauskas

Upload: vaidas-pilkauskas

Post on 16-Apr-2017

289 views

Category:

Technology


3 download

TRANSCRIPT

My Test Automation Journey

2015 Vera Djakova & Vaidas Pilkauskas

Agenda

● How to make a big mess● And then clean the campground● Using Driver Pattern

My experience

New Life

Let’s start!

● Dream team● Dream tools

○ Selenium○ Java○ Maven

Even requirement to use IE is

OK

So I have started!

After three months...

//Add new document, click button "New"click (//button[contains(@value, 'New')]);Thread.sleep(2000);

//Check new formshouldHaveText("New document");

//Click button "Add" and check errorsclick("//button[contains(@value, 'Add')]");Thread.sleep(1000);shouldHaveText(labelFromProperties("document.properties", "document.message.document-name-empty"));

//Type document name, select type, add activation dateinsert("//input[contains(@name, 'name')]", "doc_1");selectById("//select[contains(@name, 'type')]", 1);insert("//input[contains(@name, 'start-date')]", "2015-10-15");

//Click button "Add"click("//button[contains(@value, 'Add')]");

//Check new documentThread.sleep(5000);shouldHaveText(labelFromProperties("document.properties", "document.message.successfully-add"));shouldHaveText("doc_1");

Complicated test logic

xpath

// Click button "Yes"

click(".//body/table/dir/dir[6]/button[2]");

Technical debt

Manual dependencies

Help me

• Static analysis (Sonar) -> refactoring• sleep -> wait

Help me vol2

• Project build structure• Page Object

Driver pattern in tests

Testing REST APIs

What is an API?

{ “item”: “flower”}

{ “status”: “accepted”}

@Test shouldRetrieveUserByLogin() {

String userJson = "{\"username\": \"vaidas\"}";

HttpRequest post = new Post("https://localhost:8080/users", userJson);

HttpResponse postResp = HttpClient().execute(post);

assertThat(postResp.status, is(200));

HttpRequest get = new Get("https://localhost:8080/users/vaidas");

HttpResponse getResp = HttpClient().execute(get);

User user = mapper.readValue(getResp, User.class);

assertThat(username, is("vaidas"));

}

Few problems with such test

● Business requirements are mixed within implementation

● URLs are hardcoded● Payload format is hardcoded● Test exposes use of HTTP protocol

Improved version

@Test shouldRetrieveUserByUsername() {

givenUserExists("vaidas");

GetUserResponse getResp = usersDriver.aGetUserRequest()

.withUsername("vaidas").execute();

assertThat(getResp, allOf(hasStatus(OK), hasUsername("vaidas")));

}

Driver pattern

● Abstracts implementation from business logic● Removes duplication● Test specification becomes reusable

So, what if there’s a need to...

● Add another protocol (http + https)● Another input format● Test with different configuration● Customize for different clients

InternetBankApiTest extends BankApiTest

with InternetBankDriver

with InternetBankApiMatchers

AtmApiTest extends BankApiTest

with AtmDriver

with AtmMatchers

Depending on your programming language:● Use inheritance or composition● Java 8 has default method in interfaces● Consider using another language - JavaScript, Groovy,

Scala, etc

What if there is difference between two implementations?

● Override tests by extending the contract class● Use class hierarchy to group tests into

reusable test suites

Page Object pattern

● Is a variant of Driver pattern● Selenium best practice● encapsulates selector logic● Solves the same problem as using drivers with

API testing● Does not have to be per page, but per

component

Test patterns summary

● Use Driver Pattern for Microservice/API● Use Page Object for graphical interface

Lessons learnt• Testers should not work separately from

programmers• Quality matters• Allocate time to maintain tests• Or later it will cost €

Summary

● Do more pairing● Treat automation as a craft● Regular feedback is a must

Thanks!

Q&A