SlideShare ist ein Scribd-Unternehmen logo
1 von 33
Adjusting Page-Object approach
for Web Services Test Automation
by Sergey Poritskiy
Presenter
Sergey Poritskiy
Test automation engineer
in EPAM from 2015
projects: Parallels, Datalex
sergey_poritskiy@epam.com
skype: sergey.poritskiy
What should you know before (or should have heard about)
- Test automation
- Basic TA framework layers
- Page object pattern/approach
- Web services (SOAP/REST)
- XML
- XPath
- BDD approach and Gherkin language (Cucumber, JBehave)
The goals
After this presentation you will have one more (of first one) practical example
of implementing test automation framework for testing web services, that:
- is easy to implement
- is easy to understand by newcomers
- was implemented on practice and have shown good results
Starting conditions
- No test automation on a stream (sub-project)
- Need to test SOAP services, air travel domain
- A LOT of business objects and entities
- Customer wants Cucumber
- Junior newcomers are planned
The questions will TA Engineers have
- How to automate SOAP services testing?
- Let’s google it! Em… SoapUI?.. Is it something else?
- How to operate requests/responses?
- Object model?
- Write all the objects?
- Generate them?
What sounds more familiar for all of us
!!!
’Classic’ test framework structure in UI test automation
Test scripts
Services/steps
Page-objects
WebDriver
Utils
Loggers
Stuff
’Classic’ page-object example
public class LoginPage extends Page {
private static final By INPUT_LOGIN_LOCATOR = By.xpath("//input[@name='login']");
private static final By INPUT_PASSWORD_LOCATOR = By.xpath("//input[@name='passwd']");
private static final By BUTTON_SUBMIT_LOCATOR = By.xpath("//span/button[@type='submit']");
public void open() {
driver.get(URL);
}
public void typeUserName(String userName) {
driver.findElement(INPUT_LOGIN_LOCATOR).sendKeys(userName);
}
public void typePassword(String password) {
driver.findElement(INPUT_PASSWORD_LOCATOR).sendKeys(password);
}
public void clickSubmit() {
driver.findElement(BUTTON_SUBMIT_LOCATOR).click();
}
}
Our test framework layers
Test scripts
Step definitions
Rx-objects
Xml Modifier
Utils
Loggers
Stuff
What is 'RxObject'?
Request / Response
->
Rq / Rs
->
Rx!
Layer 1
Test scripts
Step definitions
Rx-objects
Xml Modifier
Scenarios (Cucumber) – make your own DSL
Scenario Outline: Scenario 1 - AirAvailabilityRQ request can be successfully processed
Given User sends FlightSearchRQ request with following parameters
| Origin | Destination | Date | AdtQty | ChildQty | InfQty | ClientId |
| <Origin> | <Destination> | 15 | <AdtQty> | <ChildQty> | <InfQty> | <ClientId> |
And User gets successful FlightSearchRS response
And Flight results in FlightSearchRS are not empty
When User sends BookingRQ request with OfferId from FlightSearchRS response
Then User gets successful BookingRS response
@smoke
Examples:
| Origin | Destination | AdtQty | ChildQty | InfQty | ClientId |
| NYC | FRA | 1 | 0 | 0 | LH_A-NYC |
@regression
Examples:
| Origin | Destination | AdtQty | ChildQty | InfQty | ClientId |
| NYC | FRA | 1 | 2 | 0 | LH_A-NYC |
| FRA | AMS | 1 | 1 | 1 | LH_A-FRA |
| DXB | NYC | 2 | 1 | 1 | LH_A-DXB |
Layer 2
Test scripts
Step definitions
Rx-objects
Xml Modifier
Step definitions
public class CommonTestSteps {
@Given("^User sends(sw+|)(sw+RQ) request$")
public void userSendsRequest(String rqNumber, String requestType){
Request request = RequestFactory.createRequest(requestType);
store.putRequest(request.getType(), request);
Response response = request.send();
store.putResponse(response.getType(), response, rqNumber);
}
@And("^User gets successful(sw+|) (w+RS)?(?: response|)$")
public void userGetsSuccessResponse(String rsNumber, String responseType) {
Response response = store.getResponse(responseType, rsNumber);
Assert.assertTrue(response.isSuccessful(), response.getType() + "was not successful!");
}
@And("^(w+) results in(sw+)? (w+RS)(?: response|) are not empty$")
public void resultsNotEmpty(String resultsType, String rsNumber, String responseType) {
Response response = store.getResponse(responseType, rsNumber);
Assert.assertTrue(response.isResultPresent(resultsType), resultsType + " results are empty!");
}
Layer 3
Test scripts
Step definitions
Rx-objects
Xml Modifier
Rx objects hierarchy
RxObject
(has type and body)
Request
(modifies its body)
FlightSearchRequest
Response
(read-only)
FlightSearchResponse… … … … …
RxObject
public class RxObject {
private String type;
private Document body;
public RxObject(String type, Document body) {
this.type = type;
this.body = body;
}
public String getType() {
return type;
}
public Document getBody() {
return body;
}
public String getNodeValue(String nodeLocator){
return XmlHelper.getNodeText(body, nodeLocator);
}
public boolean isNodePresent(String nodeLocator){
return XmlHelper.isNodePresent(body, nodeLocator);
}
public int getNodesCount(String nodeLocator) {
return XmlHelper.getCountNodesInDocument(body, nodeLocator);
}
...
}
Request Object
public abstract class Request extends RxObject {
public Request(String requestType) {
super(requestType, XmlHelper.createDocFromFile(NameHelper.getSampleFilePath(requestType)));
}
public abstract void setRequestParameterValue(String nameOfParam, String valueOfParam);
public abstract Response send() throws RequestSendException;
public void changeNodeValue(String locator, String value) {
XmlHelper.changeNodeInDocument(getBody(), locator, value);
}
public void duplicateNode(String locator) {
XmlHelper.duplicateNodeInDocument(getBody(), locator);
}
public void deleteNode(String locator) {
XmlHelper.removeNodeFromDocument(getBody(), locator);
}
...
}
Request Object - example
public class FunctionalCacheRequest extends Request {
private static final String KEY_LOCATOR = "//Key/text()";
private static final String PRICE_LOCATOR = "//PriceOption/@RateTotalAmount";
public void increaseOfferPrice(int priceToAdd) {
double newPrice = priceToAdd + getPrice();
setPrice(String.valueOf(newPrice));
}
public void setPrice(String value) {
changeNodeValue(PRICE_LOCATOR, value);
}
public void setKey(String key) {
changeNodeValue(KEY_LOCATOR, key);
}
public double getPrice() {
return Double.parseDoube(XmlHelper.getNodeText(getBody(), PRICE_LOCATOR));
}
@Override
public FunctionalCacheResponse send() {
return new FunctionalCacheResponse(SoapSender.sendRequest(this));
}
Request body - dummy (sample)
Response Object
public abstract class Response extends RxObject {
public Response(String type, Document body) {
super(type, body);
}
public abstract boolean isSuccessfull();
public abstract boolean isResultPresent(String resultsType);
public abstract String getOfferId();
...
}
Response Object - example
public class FunctionalCacheResponse extends Response implements HavingOfferPrice {
private static final String MESSAGE_LOCATOR = "//Message/text()";
private static final String ERROR_LOCATOR = "//Error/text()";
private static final String PRICE_LOCATOR = "//PriceOption/@RateTotalAmount";
private static final String OFFER_ID_LOCATOR = "//OfferId";
public String getMessageText() {
return getNodeValue(MESSAGE_LOCATOR);
}
public String getErrorText() {
return getNodeValue(ERROR_LOCATOR);
}
public double getOfferPrice() {
return Double.parseDouble(getNodeValue(PRICE_LOCATOR));
}
public String getOfferId() {
return getNodeValue(OFFER_ID_LOCATOR);
}
}
Layer 4
Test scripts
Step definitions
Rx-objects
Xml Modifier
XmlHelper
public class XmlHelper {
private static final String NODE_NAME_REGEX =
"(?<!['"][w/-]{1,255})(?<=[(/[:]|(and|or)s)[a-z_]+b(?![(':-])";
private static final String FORMATTING_PATTERN = "*[local-name()='%s']";
private static String makeXpathLocatorNameSpaceIgnoring(String xpathLocator) {…}
private static NodeList getNodeListByXpath(Document doc, String locator) {…}
private static Node getNodeByXpath(Document doc, String locator) {…}
public static boolean isNodePresent(Document doc, String locator) {…}
public static String getNodeText(Document doc, String locator) {…}
public static void changeNodeInDocument(Document doc, String locator, String value) {…}
public static int countNodesInDocument(Document doc, String locator) {…}
public static void removeNodeFromDocument(Document doc, String locator) {…}
public static void duplicateNodeInDocument(Document doc, String locator) {…}
...
...
...
Benefits of this approach
- very simple to understand, read and write tests (pure KISS principle)
- has lower entrance level
- friendly for automation engineers without experience in web services testing
- can be good option when you have a lot of business objects and entities
- was successfully implemented on real project and shows good results
Can we use RxObject for testing REST services?
In theory – yes.
public class RxObject {
private String type;
private Something body;
private String format;
private String responseFormat;
private String httpMethod;
...
...
...
}
But this will be more complicated.
Also you can take Rest Assured or other rest-automating framework.
Questions, contacts
Questions?
sergey_poritskiy@epam.com
skype: sergey.poritskiy
MY CONTACTS
Sergey_Poritskiy@epam.com
sergey.poritskiy
Thanks!
Thanks!
Thanks!
Secret page

Weitere ähnliche Inhalte

Was ist angesagt?

Javascript variables and datatypes
Javascript variables and datatypesJavascript variables and datatypes
Javascript variables and datatypes
Varun C M
 

Was ist angesagt? (20)

JavaScript - Chapter 4 - Types and Statements
 JavaScript - Chapter 4 - Types and Statements JavaScript - Chapter 4 - Types and Statements
JavaScript - Chapter 4 - Types and Statements
 
A Deeper look into Javascript Basics
A Deeper look into Javascript BasicsA Deeper look into Javascript Basics
A Deeper look into Javascript Basics
 
Scala + WattzOn, sitting in a tree....
Scala + WattzOn, sitting in a tree....Scala + WattzOn, sitting in a tree....
Scala + WattzOn, sitting in a tree....
 
ConFess Vienna 2015 - Metaprogramming with Groovy
ConFess Vienna 2015 - Metaprogramming with GroovyConFess Vienna 2015 - Metaprogramming with Groovy
ConFess Vienna 2015 - Metaprogramming with Groovy
 
Java 8 presentation
Java 8 presentationJava 8 presentation
Java 8 presentation
 
Google Dart
Google DartGoogle Dart
Google Dart
 
JavaScript Data Types
JavaScript Data TypesJavaScript Data Types
JavaScript Data Types
 
Basics of JavaScript
Basics of JavaScriptBasics of JavaScript
Basics of JavaScript
 
JavaScript Basics
JavaScript BasicsJavaScript Basics
JavaScript Basics
 
Javascript variables and datatypes
Javascript variables and datatypesJavascript variables and datatypes
Javascript variables and datatypes
 
Introduction to kotlin for android app development gdg ahmedabad dev fest 2017
Introduction to kotlin for android app development   gdg ahmedabad dev fest 2017Introduction to kotlin for android app development   gdg ahmedabad dev fest 2017
Introduction to kotlin for android app development gdg ahmedabad dev fest 2017
 
Algorithm and Programming (Looping Structure)
Algorithm and Programming (Looping Structure)Algorithm and Programming (Looping Structure)
Algorithm and Programming (Looping Structure)
 
Java 8
Java 8Java 8
Java 8
 
Java 8: the good parts!
Java 8: the good parts!Java 8: the good parts!
Java 8: the good parts!
 
Advanced JavaScript
Advanced JavaScriptAdvanced JavaScript
Advanced JavaScript
 
Few simple-type-tricks in scala
Few simple-type-tricks in scalaFew simple-type-tricks in scala
Few simple-type-tricks in scala
 
javascript objects
javascript objectsjavascript objects
javascript objects
 
Java8
Java8Java8
Java8
 
Amber and beyond: Java language changes
Amber and beyond: Java language changesAmber and beyond: Java language changes
Amber and beyond: Java language changes
 
Jug trojmiasto 2014.04.24 tricky stuff in java grammar and javac
Jug trojmiasto 2014.04.24  tricky stuff in java grammar and javacJug trojmiasto 2014.04.24  tricky stuff in java grammar and javac
Jug trojmiasto 2014.04.24 tricky stuff in java grammar and javac
 

Ähnlich wie Применение паттерна Page Object для автоматизации веб сервисов - новый взгляд

Laurens Van Den Oever Xopus Presentation
Laurens Van Den Oever Xopus PresentationLaurens Van Den Oever Xopus Presentation
Laurens Van Den Oever Xopus Presentation
Ajax Experience 2009
 
Ajax Fundamentals Web Applications
Ajax Fundamentals Web ApplicationsAjax Fundamentals Web Applications
Ajax Fundamentals Web Applications
dominion
 
Is your C# optimized
Is your C# optimizedIs your C# optimized
Is your C# optimized
Woody Pewitt
 

Ähnlich wie Применение паттерна Page Object для автоматизации веб сервисов - новый взгляд (20)

Introduction to Javascript
Introduction to JavascriptIntroduction to Javascript
Introduction to Javascript
 
Laurens Van Den Oever Xopus Presentation
Laurens Van Den Oever Xopus PresentationLaurens Van Den Oever Xopus Presentation
Laurens Van Den Oever Xopus Presentation
 
PHP: GraphQL consistency through code generation
PHP: GraphQL consistency through code generationPHP: GraphQL consistency through code generation
PHP: GraphQL consistency through code generation
 
Reversing JavaScript
Reversing JavaScriptReversing JavaScript
Reversing JavaScript
 
Dynamics 365 CRM Javascript Customization
Dynamics 365 CRM Javascript CustomizationDynamics 365 CRM Javascript Customization
Dynamics 365 CRM Javascript Customization
 
Tk2323 lecture 9 api json
Tk2323 lecture 9   api jsonTk2323 lecture 9   api json
Tk2323 lecture 9 api json
 
PHP 8: Process & Fixing Insanity
PHP 8: Process & Fixing InsanityPHP 8: Process & Fixing Insanity
PHP 8: Process & Fixing Insanity
 
Spring MVC Annotations
Spring MVC AnnotationsSpring MVC Annotations
Spring MVC Annotations
 
What's new in jQuery 1.5
What's new in jQuery 1.5What's new in jQuery 1.5
What's new in jQuery 1.5
 
Reactive programming every day
Reactive programming every dayReactive programming every day
Reactive programming every day
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency Injection
 
Ajax Fundamentals Web Applications
Ajax Fundamentals Web ApplicationsAjax Fundamentals Web Applications
Ajax Fundamentals Web Applications
 
Is your C# optimized
Is your C# optimizedIs your C# optimized
Is your C# optimized
 
Lambda Chops - Recipes for Simpler, More Expressive Code
Lambda Chops - Recipes for Simpler, More Expressive CodeLambda Chops - Recipes for Simpler, More Expressive Code
Lambda Chops - Recipes for Simpler, More Expressive Code
 
Overview of RESTful web services
Overview of RESTful web servicesOverview of RESTful web services
Overview of RESTful web services
 
Google Cloud Endpoints: Building Third-Party APIs on Google AppEngine
Google Cloud Endpoints: Building Third-Party APIs on Google AppEngineGoogle Cloud Endpoints: Building Third-Party APIs on Google AppEngine
Google Cloud Endpoints: Building Third-Party APIs on Google AppEngine
 
jQuery and Rails: Best Friends Forever
jQuery and Rails: Best Friends ForeverjQuery and Rails: Best Friends Forever
jQuery and Rails: Best Friends Forever
 
Spring Web Services: SOAP vs. REST
Spring Web Services: SOAP vs. RESTSpring Web Services: SOAP vs. REST
Spring Web Services: SOAP vs. REST
 
Load Testing with PHP and RedLine13
Load Testing with PHP and RedLine13Load Testing with PHP and RedLine13
Load Testing with PHP and RedLine13
 
Ast transformations
Ast transformationsAst transformations
Ast transformations
 

Mehr von COMAQA.BY

Системный взгляд на параллельный запуск Selenium тестов
Системный взгляд на параллельный запуск Selenium тестовСистемный взгляд на параллельный запуск Selenium тестов
Системный взгляд на параллельный запуск Selenium тестов
COMAQA.BY
 

Mehr von COMAQA.BY (20)

Тестирование аналогов инсталлируемых приложений (Android Instant Apps, Progre...
Тестирование аналогов инсталлируемых приложений (Android Instant Apps, Progre...Тестирование аналогов инсталлируемых приложений (Android Instant Apps, Progre...
Тестирование аналогов инсталлируемых приложений (Android Instant Apps, Progre...
 
Anton semenchenko. Comaqa Spring 2018. Nine circles of hell. Antipatterns in ...
Anton semenchenko. Comaqa Spring 2018. Nine circles of hell. Antipatterns in ...Anton semenchenko. Comaqa Spring 2018. Nine circles of hell. Antipatterns in ...
Anton semenchenko. Comaqa Spring 2018. Nine circles of hell. Antipatterns in ...
 
Vivien Ibironke Ibiyemi. Comaqa Spring 2018. Enhance your Testing Skills With...
Vivien Ibironke Ibiyemi. Comaqa Spring 2018. Enhance your Testing Skills With...Vivien Ibironke Ibiyemi. Comaqa Spring 2018. Enhance your Testing Skills With...
Vivien Ibironke Ibiyemi. Comaqa Spring 2018. Enhance your Testing Skills With...
 
Roman Soroka. Comaqa Spring 2018. Глобальный обзор процесса QA и его важность
Roman Soroka. Comaqa Spring 2018. Глобальный обзор процесса QA и его важностьRoman Soroka. Comaqa Spring 2018. Глобальный обзор процесса QA и его важность
Roman Soroka. Comaqa Spring 2018. Глобальный обзор процесса QA и его важность
 
Roman Iovlev. Comaqa Spring 2018. Архитектура Open Source решений для автомат...
Roman Iovlev. Comaqa Spring 2018. Архитектура Open Source решений для автомат...Roman Iovlev. Comaqa Spring 2018. Архитектура Open Source решений для автомат...
Roman Iovlev. Comaqa Spring 2018. Архитектура Open Source решений для автомат...
 
Vladimir Polyakov. Comaqa Spring 2018. Особенности тестирования ПО в предметн...
Vladimir Polyakov. Comaqa Spring 2018. Особенности тестирования ПО в предметн...Vladimir Polyakov. Comaqa Spring 2018. Особенности тестирования ПО в предметн...
Vladimir Polyakov. Comaqa Spring 2018. Особенности тестирования ПО в предметн...
 
Kimmo Hakala. Comaqa Spring 2018. Challenges and good QA practices in softwar...
Kimmo Hakala. Comaqa Spring 2018. Challenges and good QA practices in softwar...Kimmo Hakala. Comaqa Spring 2018. Challenges and good QA practices in softwar...
Kimmo Hakala. Comaqa Spring 2018. Challenges and good QA practices in softwar...
 
Дмитрий Лемешко. Comaqa Spring 2018. Continuous mobile automation in build pi...
Дмитрий Лемешко. Comaqa Spring 2018. Continuous mobile automation in build pi...Дмитрий Лемешко. Comaqa Spring 2018. Continuous mobile automation in build pi...
Дмитрий Лемешко. Comaqa Spring 2018. Continuous mobile automation in build pi...
 
Ivan Katunov. Comaqa Spring 2018. Test Design and Automation for Rest API.
Ivan Katunov. Comaqa Spring 2018. Test Design and Automation for Rest API.Ivan Katunov. Comaqa Spring 2018. Test Design and Automation for Rest API.
Ivan Katunov. Comaqa Spring 2018. Test Design and Automation for Rest API.
 
Vadim Zubovich. Comaqa Spring 2018. Красивое тестирование производительности.
Vadim Zubovich. Comaqa Spring 2018. Красивое тестирование производительности.Vadim Zubovich. Comaqa Spring 2018. Красивое тестирование производительности.
Vadim Zubovich. Comaqa Spring 2018. Красивое тестирование производительности.
 
Alexander Andelkovic. Comaqa Spring 2018. Using Artificial Intelligence to Te...
Alexander Andelkovic. Comaqa Spring 2018. Using Artificial Intelligence to Te...Alexander Andelkovic. Comaqa Spring 2018. Using Artificial Intelligence to Te...
Alexander Andelkovic. Comaqa Spring 2018. Using Artificial Intelligence to Te...
 
Моя роль в конфликте
Моя роль в конфликтеМоя роль в конфликте
Моя роль в конфликте
 
Организация приемочного тестирования силами матерых тестировщиков
Организация приемочного тестирования силами матерых тестировщиковОрганизация приемочного тестирования силами матерых тестировщиков
Организация приемочного тестирования силами матерых тестировщиков
 
Развитие или смерть
Развитие или смертьРазвитие или смерть
Развитие или смерть
 
Системный взгляд на параллельный запуск Selenium тестов
Системный взгляд на параллельный запуск Selenium тестовСистемный взгляд на параллельный запуск Selenium тестов
Системный взгляд на параллельный запуск Selenium тестов
 
Эффективная работа с рутинными задачами
Эффективная работа с рутинными задачамиЭффективная работа с рутинными задачами
Эффективная работа с рутинными задачами
 
Как стать синьором
Как стать синьоромКак стать синьором
Как стать синьором
 
Open your mind for OpenSource
Open your mind for OpenSourceOpen your mind for OpenSource
Open your mind for OpenSource
 
JDI 2.0. Not only UI testing
JDI 2.0. Not only UI testingJDI 2.0. Not only UI testing
JDI 2.0. Not only UI testing
 
Out of box page object design pattern, java
Out of box page object design pattern, javaOut of box page object design pattern, java
Out of box page object design pattern, java
 

Kürzlich hochgeladen

Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 

Kürzlich hochgeladen (20)

ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 

Применение паттерна Page Object для автоматизации веб сервисов - новый взгляд

  • 1. Adjusting Page-Object approach for Web Services Test Automation by Sergey Poritskiy
  • 2. Presenter Sergey Poritskiy Test automation engineer in EPAM from 2015 projects: Parallels, Datalex sergey_poritskiy@epam.com skype: sergey.poritskiy
  • 3. What should you know before (or should have heard about) - Test automation - Basic TA framework layers - Page object pattern/approach - Web services (SOAP/REST) - XML - XPath - BDD approach and Gherkin language (Cucumber, JBehave)
  • 4. The goals After this presentation you will have one more (of first one) practical example of implementing test automation framework for testing web services, that: - is easy to implement - is easy to understand by newcomers - was implemented on practice and have shown good results
  • 5. Starting conditions - No test automation on a stream (sub-project) - Need to test SOAP services, air travel domain - A LOT of business objects and entities - Customer wants Cucumber - Junior newcomers are planned
  • 6. The questions will TA Engineers have - How to automate SOAP services testing? - Let’s google it! Em… SoapUI?.. Is it something else? - How to operate requests/responses? - Object model? - Write all the objects? - Generate them?
  • 7. What sounds more familiar for all of us !!!
  • 8. ’Classic’ test framework structure in UI test automation Test scripts Services/steps Page-objects WebDriver Utils Loggers Stuff
  • 9. ’Classic’ page-object example public class LoginPage extends Page { private static final By INPUT_LOGIN_LOCATOR = By.xpath("//input[@name='login']"); private static final By INPUT_PASSWORD_LOCATOR = By.xpath("//input[@name='passwd']"); private static final By BUTTON_SUBMIT_LOCATOR = By.xpath("//span/button[@type='submit']"); public void open() { driver.get(URL); } public void typeUserName(String userName) { driver.findElement(INPUT_LOGIN_LOCATOR).sendKeys(userName); } public void typePassword(String password) { driver.findElement(INPUT_PASSWORD_LOCATOR).sendKeys(password); } public void clickSubmit() { driver.findElement(BUTTON_SUBMIT_LOCATOR).click(); } }
  • 10. Our test framework layers Test scripts Step definitions Rx-objects Xml Modifier Utils Loggers Stuff
  • 11. What is 'RxObject'? Request / Response -> Rq / Rs -> Rx!
  • 12. Layer 1 Test scripts Step definitions Rx-objects Xml Modifier
  • 13. Scenarios (Cucumber) – make your own DSL Scenario Outline: Scenario 1 - AirAvailabilityRQ request can be successfully processed Given User sends FlightSearchRQ request with following parameters | Origin | Destination | Date | AdtQty | ChildQty | InfQty | ClientId | | <Origin> | <Destination> | 15 | <AdtQty> | <ChildQty> | <InfQty> | <ClientId> | And User gets successful FlightSearchRS response And Flight results in FlightSearchRS are not empty When User sends BookingRQ request with OfferId from FlightSearchRS response Then User gets successful BookingRS response @smoke Examples: | Origin | Destination | AdtQty | ChildQty | InfQty | ClientId | | NYC | FRA | 1 | 0 | 0 | LH_A-NYC | @regression Examples: | Origin | Destination | AdtQty | ChildQty | InfQty | ClientId | | NYC | FRA | 1 | 2 | 0 | LH_A-NYC | | FRA | AMS | 1 | 1 | 1 | LH_A-FRA | | DXB | NYC | 2 | 1 | 1 | LH_A-DXB |
  • 14. Layer 2 Test scripts Step definitions Rx-objects Xml Modifier
  • 15. Step definitions public class CommonTestSteps { @Given("^User sends(sw+|)(sw+RQ) request$") public void userSendsRequest(String rqNumber, String requestType){ Request request = RequestFactory.createRequest(requestType); store.putRequest(request.getType(), request); Response response = request.send(); store.putResponse(response.getType(), response, rqNumber); } @And("^User gets successful(sw+|) (w+RS)?(?: response|)$") public void userGetsSuccessResponse(String rsNumber, String responseType) { Response response = store.getResponse(responseType, rsNumber); Assert.assertTrue(response.isSuccessful(), response.getType() + "was not successful!"); } @And("^(w+) results in(sw+)? (w+RS)(?: response|) are not empty$") public void resultsNotEmpty(String resultsType, String rsNumber, String responseType) { Response response = store.getResponse(responseType, rsNumber); Assert.assertTrue(response.isResultPresent(resultsType), resultsType + " results are empty!"); }
  • 16. Layer 3 Test scripts Step definitions Rx-objects Xml Modifier
  • 17. Rx objects hierarchy RxObject (has type and body) Request (modifies its body) FlightSearchRequest Response (read-only) FlightSearchResponse… … … … …
  • 18. RxObject public class RxObject { private String type; private Document body; public RxObject(String type, Document body) { this.type = type; this.body = body; } public String getType() { return type; } public Document getBody() { return body; } public String getNodeValue(String nodeLocator){ return XmlHelper.getNodeText(body, nodeLocator); } public boolean isNodePresent(String nodeLocator){ return XmlHelper.isNodePresent(body, nodeLocator); } public int getNodesCount(String nodeLocator) { return XmlHelper.getCountNodesInDocument(body, nodeLocator); } ... }
  • 19. Request Object public abstract class Request extends RxObject { public Request(String requestType) { super(requestType, XmlHelper.createDocFromFile(NameHelper.getSampleFilePath(requestType))); } public abstract void setRequestParameterValue(String nameOfParam, String valueOfParam); public abstract Response send() throws RequestSendException; public void changeNodeValue(String locator, String value) { XmlHelper.changeNodeInDocument(getBody(), locator, value); } public void duplicateNode(String locator) { XmlHelper.duplicateNodeInDocument(getBody(), locator); } public void deleteNode(String locator) { XmlHelper.removeNodeFromDocument(getBody(), locator); } ... }
  • 20. Request Object - example public class FunctionalCacheRequest extends Request { private static final String KEY_LOCATOR = "//Key/text()"; private static final String PRICE_LOCATOR = "//PriceOption/@RateTotalAmount"; public void increaseOfferPrice(int priceToAdd) { double newPrice = priceToAdd + getPrice(); setPrice(String.valueOf(newPrice)); } public void setPrice(String value) { changeNodeValue(PRICE_LOCATOR, value); } public void setKey(String key) { changeNodeValue(KEY_LOCATOR, key); } public double getPrice() { return Double.parseDoube(XmlHelper.getNodeText(getBody(), PRICE_LOCATOR)); } @Override public FunctionalCacheResponse send() { return new FunctionalCacheResponse(SoapSender.sendRequest(this)); }
  • 21. Request body - dummy (sample)
  • 22. Response Object public abstract class Response extends RxObject { public Response(String type, Document body) { super(type, body); } public abstract boolean isSuccessfull(); public abstract boolean isResultPresent(String resultsType); public abstract String getOfferId(); ... }
  • 23. Response Object - example public class FunctionalCacheResponse extends Response implements HavingOfferPrice { private static final String MESSAGE_LOCATOR = "//Message/text()"; private static final String ERROR_LOCATOR = "//Error/text()"; private static final String PRICE_LOCATOR = "//PriceOption/@RateTotalAmount"; private static final String OFFER_ID_LOCATOR = "//OfferId"; public String getMessageText() { return getNodeValue(MESSAGE_LOCATOR); } public String getErrorText() { return getNodeValue(ERROR_LOCATOR); } public double getOfferPrice() { return Double.parseDouble(getNodeValue(PRICE_LOCATOR)); } public String getOfferId() { return getNodeValue(OFFER_ID_LOCATOR); } }
  • 24. Layer 4 Test scripts Step definitions Rx-objects Xml Modifier
  • 25. XmlHelper public class XmlHelper { private static final String NODE_NAME_REGEX = "(?<!['"][w/-]{1,255})(?<=[(/[:]|(and|or)s)[a-z_]+b(?![(':-])"; private static final String FORMATTING_PATTERN = "*[local-name()='%s']"; private static String makeXpathLocatorNameSpaceIgnoring(String xpathLocator) {…} private static NodeList getNodeListByXpath(Document doc, String locator) {…} private static Node getNodeByXpath(Document doc, String locator) {…} public static boolean isNodePresent(Document doc, String locator) {…} public static String getNodeText(Document doc, String locator) {…} public static void changeNodeInDocument(Document doc, String locator, String value) {…} public static int countNodesInDocument(Document doc, String locator) {…} public static void removeNodeFromDocument(Document doc, String locator) {…} public static void duplicateNodeInDocument(Document doc, String locator) {…} ... ... ...
  • 26. Benefits of this approach - very simple to understand, read and write tests (pure KISS principle) - has lower entrance level - friendly for automation engineers without experience in web services testing - can be good option when you have a lot of business objects and entities - was successfully implemented on real project and shows good results
  • 27. Can we use RxObject for testing REST services? In theory – yes. public class RxObject { private String type; private Something body; private String format; private String responseFormat; private String httpMethod; ... ... ... } But this will be more complicated. Also you can take Rest Assured or other rest-automating framework.