SlideShare a Scribd company logo
1
A test framework out of the box - Geb for Web
and mobile
Yaroslav Sviatkin
Senior Test Automation Engineer, Consultant
2
3
HtmlElements. Page Object
4
JDI UI Test Automation Framework
@JSite(domain = "https://epam.github.io/JDI/")
public class JDIExampleSite extends WebSite {
public static HomePage homePage;
public static LoginForm loginForm;
@FindBy(css = ".profile-photo")
public static Label profilePhoto;
public static void login() {
profilePhoto.click();
loginForm.loginAs(new User());
}
}
5
Automated Acceptance Testing with Style
http://www.thucydides.info/#/
6
7
Project structure
Page Object classes
Steps implementation
class
Stories classes
Requirements for the
application under test
8
Organizing requirements
First, you create a model of the features and user stories you intend to
implement:
Stories
Features
9
Page Objects
Next you will need to implement your page objects. These are almost just
run-of-the-mill WebDriver page objects, but with a few enhancements:
10
Steps implementation
Now implement the actual test steps using either WebDriver page objects or
other test steps. Here you start thinking about implementation:
A step library
High level steps...
...implemented with
Page Objects
...or with other steps
11
12
Selenide
http://selenide.org
13
14
Geb
http://www.gebish.org
15
Geb is a browser automation solution
What is Geb?
16
• Any web and mobile applications
• App doesn't need to be written in Groovy
What can you test with Geb?
17
go "http://www.google.com"
$("input", name: "q").value("geb")
$("button", name: "btnG").click()
waitFor { $("#search").displayed }
$("h3.r").first().click()
waitFor { title == "Geb - Very Groovy Browser
18
Selector syntax
title { $(By.xpath(".//h4[@class='title ng-
binding']")).text()
$("#by-id")
$(".by-class")
$("div", name: "by-attribute")
$("div", text: "By text")
$(By.id("some-id"))
$(By.className("some-class"))
$(By.xpath('//p[@class="xpath"]'))
…
19
assert $("p", 1..2)*.text() == ["b", "c"]
assert $("p", text: ~/p./).size() == 2
assert $("p", text: startsWith("p")).size() == 2
20
assert $("p.d").previous() == $("p.c")
assert $("p.e").prevAll() == $("p.c").add("p.d")
assert $("p.d").next() == $("p.e")
assert $("p.c").nextAll() == $("p.d").add("p.e")
assert $("p.d").parent() == $("div.b")
assert $("p.c").siblings() ==
$("p.d").add("p.e")
assert $("div.a").children() ==
$("div.b").add("div.f")
21
project { String index -> $(By.xpath("//div[@class=card-item']//h4[@title='${index}']")).click() }
projectPage.project(nameProject)
22
dynamicallyAdded(wait: true) { $("p.dynamic") }
dynamicallyAdded(wait: 5, required: false) {
$("p.dynamic") }
cachedValue(cache: true) { value }
helpLink(to: HelpPage) { $("a", text: "Help") }
23
Page Object Model
24
Page
25
Control modules
• FormElement
• Checkbox
• Select
• MultipleSelect
• TextInput
• Textarea
• FileInput
• RadioButtons
26
class ExamplePage extends Page {
static content = {
theModule { module ExampleModule }
}
}
class ExampleModule extends Module {
static content = {
button { $("input", type: "submit") }
}
}
27
class NotificationModule extends Module {
static content = {
notifocation {
$(By.xpath(".//li[contains(@ng-repeat,'notifications')]")).moduleList(Notification)
}
gotItButton { $(By.xpath(".//button[@ng-click='appCtrl.gotItNotifications()']")) }
}
}
class Notification extends Module {
static content = {
name { $(By.xpath("//h5")).text() }
dete { $(By.xpath("//div[contains(@class,'date')]")).text() }
notification { $(By.xpath("//p")) text() }
}
}
28
searchResult(required: false, wait: 5) { $(By.xpath("//li/a/strong"))*.text() }
notification { $(By.xpath("//ul[contains(@ng-if,'notifications')]")).module(NotificationModule) }
menuLinksModule(wait: 5) {
$(By.xpath("//button[contains(@class,'services')]")).module(MenuLinksModule) }
29
class IdeaCreatePage extends geb.Page {
static at = { $("div#create-idea").displayed }
}
static content = {
createButton(to: IdeaShowPage) { $("input#create") }
}
IdeaCreatePage ideaCreatePage = to(IdeaCreatePage)
isAt(IdeaCreatePage)
30
•
class LoginPage extends Page {
static url = "access/signin"
static at = { browser.currentUrl.startsWith("https://wwwwwwwwww.com") }
static content = {
userName(wait: 5) { $(By.xpath("//input[@type='text']")) }
userPassword { $(By.xpath("//input[@type='password']")) }
loginError(required: false, wait: 3) { $(By.xpath("//div[@class='error']")).text() }
loginSubmit { $("button", text: startsWith("Login")).click() }
heading (to:BasePage){ $(By.xpath("//div[@class='info']/h1")).text() }
}
def login(String login, String password) {
userName.firstElement().clear()
userPassword.firstElement().clear()
userName << login
userPassword << password
loginSubmit
}
}
31
waitFor examples
waitFor {
$("div.alert").displayed
}
waitFor {
$("div.message").text() == "Update
successful"
}
32
Mouse interactions
void moveRatingSlider(Integer rating) {
// Slider is 400 pixels wide and starts at 1,
// so each notch above 1 is 100 pixels
apart
Integer numPixelsX = (rating - 1) * 100
interact {
clickAndHold(ratingSliderHandle)
moveByOffset(numPixelsX, 0)
release()
}
}
WebElement underlyingElement =
$('#myElement').getElement(0)
Action action = new
Actions(browser.driver)
.clickAndHold(underlyingElement)
.moveByOffset(15,15)
.release()
.build()
action.perform()
}
Use keyboard
$(".ui-slider-handle") << Keys.ARROW_RIGHT
33
Already opened windows
withWindow({ title == "Geb - Very Groovy Browser Automation" }) {
assert $("#slogan").text().startsWith("very groovy browser automation…")
}
}
withNewWindow({ $('a').click() }) {
assert title == 'Geb - Very Groovy Browser Automation'
}
34
@Test
void feedBackReferenceTest() {
openMenu
browser.withNewWindow({ basePage.menuLinksModule.feedback }, {
assert browser.currentUrl.startsWith("https://helpdesk.com/")
})
}
@Test
void officeMapReferenceTest() {
openMenu
browser.withWindow({
basePage.menuLinksModule.officeMap }, {
if (browser.currentUrl == signinUrl) {
loginPage.login(userName, userPassword)
}
assert browser.currentUrl == "https://portal.com"
})
browser.to(ProjectPage)
}
35
Show hidden element
void scrollUp() {
js.exec("""window.scrollTo(0,0)""")
}
$("div#a").jquery.mouseov
er()
Browser.drive {
assert js.myGlobalVar ==
1
}
36
Available browsers
37
waiting {
timeout = 2
}
baseUrl = "https://wwwwwwwww.com/"
autoClearCookies = false
atCheckWaiting = true
baseNavigatorWaiting = true
name = ''
password = ''
mail =''
environments {
chrome {
driver = {
def driverInstance = new ChromeDriver()
driverInstance.manage().window().maximize()
driverInstance
}
}
firefox {
driver = {
def driverInstance = new FirefoxDriver()
driverInstance.manage().window().maximize()
driverInstance
}
}
ie {
driver = {
def driverInstance = new InternetExplorerDriver()
driverInstance.manage().window().maximize()
driverInstance
} }}
//Receiving name and password from GebConfig.groovy
final String userName = browser.config.rawConfig.name
final String userPassword =
browser.config.rawConfig.password
38
task chromeTest(type: Test) {
systemProperty "geb.env", "chrome"
systemProperty "webdriver.chrome.driver", "driverschromedriver.exe"
useTestNG {
suites "srctestresourcestestng-suite.xml"
useDefaultListeners = true
}
}
// Drivers
testCompile "org.seleniumhq.selenium:selenium-chrome-driver:$seleniumVersion"
testCompile "org.seleniumhq.selenium:selenium-firefox-driver:$seleniumVersion"
testCompile "org.seleniumhq.selenium:selenium-ie-driver:$seleniumVersion"
39
static String randomString(int count) {
(1..count).inject("") { a, b -> a += ('a'..'z')[new Random().nextFloat() * 26 as int] }.capitalize()
}
def getWanted() {
def result = []
HTTPRequest.request(GET, JSON) { req ->
uri.path = '/wanted'
headers.'Auth' = "${TOKEN}"
response.success = { resp, json ->
println new JsonBuilder( json).toPrettyString()
(json as ArrayList).each {
String name = it.name
def projects = []
(it.projects as ArrayList).each {
projects << [it.projectid.'$oid', it.title]
}
result << [name, projects].flatten()
}
}
}
result
}
40
List getAllIdProject() {
def result = []
GITLAB.get(path: "/gitlab/api/v3/projects/all") { resp, json ->
println new JsonBuilder(json).toPrettyString()
def request = (json as Map)
result = request*.id
}
result
}
assert loginPage.heading == "Welcome"
41
Geb integrates with
42
Geb-mobile
https://github.com/JasonKissinger-MDT/geb-mobile
43
4444
Q & A
45
Yaroslav Sviatkin
Senior Test Automation Engineer,
Consultant
iaroslav.sviatkin@globallogic.com
Thank you

More Related Content

What's hot (20)

PDF
JavaScript para Graficos y Visualizacion de Datos - BogotaJS
philogb
 
PDF
Basic Tutorial of React for Programmers
David Rodenas
 
PDF
Better Bullshit Driven Development [SeleniumCamp 2017]
automician
 
PDF
Awesome State Management for React and Other Virtual-Dom Libraries
FITC
 
PPTX
Performance Optimization In Angular 2
Eyal Vardi
 
PPTX
Présentation et bonnes pratiques du pattern MVVM - MIC Belgique
Denis Voituron
 
PPTX
Javascript 2
pavishkumarsingh
 
PDF
Desenvolvimento web com Ruby on Rails (extras)
Joao Lucas Santana
 
PDF
Building Reusable Custom Elements With Angular
Ilia Idakiev
 
PPTX
Test and profile your Windows Phone 8 App
Michele Capra
 
PDF
Taking Web Apps Offline
Pedro Morais
 
PPTX
Mobile App Development: Primi passi con NativeScript e Angular 2
Filippo Matteo Riggio
 
KEY
Django quickstart
Marconi Moreto
 
PPTX
Angular 2 - Ahead of-time Compilation
Eyal Vardi
 
PDF
A To-do Web App on Google App Engine
Michael Parker
 
PDF
22 j query1
Fajar Baskoro
 
PDF
Introduction to jQuery
Nagaraju Sangam
 
PDF
JQuery UI
Gary Yeh
 
PPT
Yui app-framework
Lucio Grenzi
 
PDF
Reactive Type-safe WebComponents
Martin Hochel
 
JavaScript para Graficos y Visualizacion de Datos - BogotaJS
philogb
 
Basic Tutorial of React for Programmers
David Rodenas
 
Better Bullshit Driven Development [SeleniumCamp 2017]
automician
 
Awesome State Management for React and Other Virtual-Dom Libraries
FITC
 
Performance Optimization In Angular 2
Eyal Vardi
 
Présentation et bonnes pratiques du pattern MVVM - MIC Belgique
Denis Voituron
 
Javascript 2
pavishkumarsingh
 
Desenvolvimento web com Ruby on Rails (extras)
Joao Lucas Santana
 
Building Reusable Custom Elements With Angular
Ilia Idakiev
 
Test and profile your Windows Phone 8 App
Michele Capra
 
Taking Web Apps Offline
Pedro Morais
 
Mobile App Development: Primi passi con NativeScript e Angular 2
Filippo Matteo Riggio
 
Django quickstart
Marconi Moreto
 
Angular 2 - Ahead of-time Compilation
Eyal Vardi
 
A To-do Web App on Google App Engine
Michael Parker
 
22 j query1
Fajar Baskoro
 
Introduction to jQuery
Nagaraju Sangam
 
JQuery UI
Gary Yeh
 
Yui app-framework
Lucio Grenzi
 
Reactive Type-safe WebComponents
Martin Hochel
 

Similar to A test framework out of the box - Geb for Web and mobile (20)

PPTX
QA Fest 2017. Ярослав Святкин. Тестовый фреймворк GEB для тестирования WEB пр...
QAFest
 
PPTX
Agile NCR 2013 - Gaurav Bansal- web_automation
AgileNCR2013
 
PDF
Geb presentation
Ivar Østhus
 
PPT
Comprehensive Browser Automation Solution using Groovy, WebDriver & Obect Model
vodQA
 
PDF
Better Selenium Tests with Geb - Selenium Conf 2014
Naresha K
 
PPTX
End-to-end testing with geb
Jesús L. Domínguez Muriel
 
PDF
Taming Functional Web Testing with Spock and Geb
C4Media
 
PDF
Pragmatic Browser Automation with Geb - GIDS 2015
Naresha K
 
PDF
Web UI test automation instruments
Artem Nagornyi
 
PDF
Geb Best Practices
Marcin Erdmann
 
PPTX
Geb with spock
Monika Gurram
 
PPTX
Мощь переполняет с JDI 2.0 - новая эра UI автоматизации
SQALab
 
PDF
Stanislaw potoczny kra_qa_21.01.20
kraqa
 
PPTX
Automated integration tests for ajax applications (с. карпушин, auriga)
Mobile Developer Day
 
ODP
WebTest - Efficient Functional Web Testing with HtmlUnit and Beyond
mguillem
 
PDF
BDD, ATDD, Page Objects: The Road to Sustainable Web Testing
John Ferguson Smart Limited
 
PDF
Automation Abstraction Layers: Page Objects and Beyond
Alan Richardson
 
PPTX
Taiko presentation
VodqaBLR
 
PPTX
Automated Testing on Web Applications
Samuel Borg
 
PDF
Top100summit 谷歌-scott-improve your automated web application testing
drewz lin
 
QA Fest 2017. Ярослав Святкин. Тестовый фреймворк GEB для тестирования WEB пр...
QAFest
 
Agile NCR 2013 - Gaurav Bansal- web_automation
AgileNCR2013
 
Geb presentation
Ivar Østhus
 
Comprehensive Browser Automation Solution using Groovy, WebDriver & Obect Model
vodQA
 
Better Selenium Tests with Geb - Selenium Conf 2014
Naresha K
 
End-to-end testing with geb
Jesús L. Domínguez Muriel
 
Taming Functional Web Testing with Spock and Geb
C4Media
 
Pragmatic Browser Automation with Geb - GIDS 2015
Naresha K
 
Web UI test automation instruments
Artem Nagornyi
 
Geb Best Practices
Marcin Erdmann
 
Geb with spock
Monika Gurram
 
Мощь переполняет с JDI 2.0 - новая эра UI автоматизации
SQALab
 
Stanislaw potoczny kra_qa_21.01.20
kraqa
 
Automated integration tests for ajax applications (с. карпушин, auriga)
Mobile Developer Day
 
WebTest - Efficient Functional Web Testing with HtmlUnit and Beyond
mguillem
 
BDD, ATDD, Page Objects: The Road to Sustainable Web Testing
John Ferguson Smart Limited
 
Automation Abstraction Layers: Page Objects and Beyond
Alan Richardson
 
Taiko presentation
VodqaBLR
 
Automated Testing on Web Applications
Samuel Borg
 
Top100summit 谷歌-scott-improve your automated web application testing
drewz lin
 
Ad

More from GlobalLogic Ukraine (20)

PDF
GlobalLogic JavaScript Community Webinar #21 “Інтерв’ю без заспокійливих”
GlobalLogic Ukraine
 
PPTX
Deadlocks in SQL - Turning Fear Into Understanding (by Sergii Stets)
GlobalLogic Ukraine
 
PDF
GlobalLogic Java Community Webinar #18 “How to Improve Web Application Perfor...
GlobalLogic Ukraine
 
PDF
GlobalLogic Embedded Community x ROS Ukraine Webinar "Surgical Robots"
GlobalLogic Ukraine
 
PDF
GlobalLogic Java Community Webinar #17 “SpringJDBC vs JDBC. Is Spring a Hero?”
GlobalLogic Ukraine
 
PDF
GlobalLogic JavaScript Community Webinar #18 “Long Story Short: OSI Model”
GlobalLogic Ukraine
 
PPTX
Штучний інтелект як допомога в навчанні, а не замінник.pptx
GlobalLogic Ukraine
 
PPTX
Задачі AI-розробника як застосовується штучний інтелект.pptx
GlobalLogic Ukraine
 
PPTX
Що треба вивчати, щоб стати розробником штучного інтелекту та нейромереж.pptx
GlobalLogic Ukraine
 
PDF
GlobalLogic Java Community Webinar #16 “Zaloni’s Architecture for Data-Driven...
GlobalLogic Ukraine
 
PDF
JavaScript Community Webinar #14 "Why Is Git Rebase?"
GlobalLogic Ukraine
 
PDF
GlobalLogic .NET Community Webinar #3 "Exploring Serverless with Azure Functi...
GlobalLogic Ukraine
 
PPTX
Страх і сила помилок - IT Inside від GlobalLogic Education
GlobalLogic Ukraine
 
PDF
GlobalLogic .NET Webinar #2 “Azure RBAC and Managed Identity”
GlobalLogic Ukraine
 
PDF
GlobalLogic QA Webinar “What does it take to become a Test Engineer”
GlobalLogic Ukraine
 
PDF
“How to Secure Your Applications With a Keycloak?
GlobalLogic Ukraine
 
PDF
GlobalLogic Machine Learning Webinar “Advanced Statistical Methods for Linear...
GlobalLogic Ukraine
 
PPTX
GlobalLogic Machine Learning Webinar “Statistical learning of linear regressi...
GlobalLogic Ukraine
 
PDF
GlobalLogic C++ Webinar “The Minimum Knowledge to Become a C++ Developer”
GlobalLogic Ukraine
 
PDF
Embedded Webinar #17 "Low-level Network Testing in Embedded Devices Development"
GlobalLogic Ukraine
 
GlobalLogic JavaScript Community Webinar #21 “Інтерв’ю без заспокійливих”
GlobalLogic Ukraine
 
Deadlocks in SQL - Turning Fear Into Understanding (by Sergii Stets)
GlobalLogic Ukraine
 
GlobalLogic Java Community Webinar #18 “How to Improve Web Application Perfor...
GlobalLogic Ukraine
 
GlobalLogic Embedded Community x ROS Ukraine Webinar "Surgical Robots"
GlobalLogic Ukraine
 
GlobalLogic Java Community Webinar #17 “SpringJDBC vs JDBC. Is Spring a Hero?”
GlobalLogic Ukraine
 
GlobalLogic JavaScript Community Webinar #18 “Long Story Short: OSI Model”
GlobalLogic Ukraine
 
Штучний інтелект як допомога в навчанні, а не замінник.pptx
GlobalLogic Ukraine
 
Задачі AI-розробника як застосовується штучний інтелект.pptx
GlobalLogic Ukraine
 
Що треба вивчати, щоб стати розробником штучного інтелекту та нейромереж.pptx
GlobalLogic Ukraine
 
GlobalLogic Java Community Webinar #16 “Zaloni’s Architecture for Data-Driven...
GlobalLogic Ukraine
 
JavaScript Community Webinar #14 "Why Is Git Rebase?"
GlobalLogic Ukraine
 
GlobalLogic .NET Community Webinar #3 "Exploring Serverless with Azure Functi...
GlobalLogic Ukraine
 
Страх і сила помилок - IT Inside від GlobalLogic Education
GlobalLogic Ukraine
 
GlobalLogic .NET Webinar #2 “Azure RBAC and Managed Identity”
GlobalLogic Ukraine
 
GlobalLogic QA Webinar “What does it take to become a Test Engineer”
GlobalLogic Ukraine
 
“How to Secure Your Applications With a Keycloak?
GlobalLogic Ukraine
 
GlobalLogic Machine Learning Webinar “Advanced Statistical Methods for Linear...
GlobalLogic Ukraine
 
GlobalLogic Machine Learning Webinar “Statistical learning of linear regressi...
GlobalLogic Ukraine
 
GlobalLogic C++ Webinar “The Minimum Knowledge to Become a C++ Developer”
GlobalLogic Ukraine
 
Embedded Webinar #17 "Low-level Network Testing in Embedded Devices Development"
GlobalLogic Ukraine
 
Ad

Recently uploaded (20)

PDF
Empower Inclusion Through Accessible Java Applications
Ana-Maria Mihalceanu
 
PPTX
From Sci-Fi to Reality: Exploring AI Evolution
Svetlana Meissner
 
PDF
Exolore The Essential AI Tools in 2025.pdf
Srinivasan M
 
PDF
"Beyond English: Navigating the Challenges of Building a Ukrainian-language R...
Fwdays
 
PPTX
Q2 FY26 Tableau User Group Leader Quarterly Call
lward7
 
PPTX
COMPARISON OF RASTER ANALYSIS TOOLS OF QGIS AND ARCGIS
Sharanya Sarkar
 
PPTX
AI Penetration Testing Essentials: A Cybersecurity Guide for 2025
defencerabbit Team
 
PDF
Transcript: New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
PPTX
AUTOMATION AND ROBOTICS IN PHARMA INDUSTRY.pptx
sameeraaabegumm
 
PDF
The Builder’s Playbook - 2025 State of AI Report.pdf
jeroen339954
 
PDF
Presentation - Vibe Coding The Future of Tech
yanuarsinggih1
 
PDF
Complete JavaScript Notes: From Basics to Advanced Concepts.pdf
haydendavispro
 
PDF
Newgen 2022-Forrester Newgen TEI_13 05 2022-The-Total-Economic-Impact-Newgen-...
darshakparmar
 
PDF
Python basic programing language for automation
DanialHabibi2
 
PDF
Achieving Consistent and Reliable AI Code Generation - Medusa AI
medusaaico
 
PDF
Reverse Engineering of Security Products: Developing an Advanced Microsoft De...
nwbxhhcyjv
 
PPTX
UiPath Academic Alliance Educator Panels: Session 2 - Business Analyst Content
DianaGray10
 
PDF
Smart Trailers 2025 Update with History and Overview
Paul Menig
 
PDF
July Patch Tuesday
Ivanti
 
PDF
Chris Elwell Woburn, MA - Passionate About IT Innovation
Chris Elwell Woburn, MA
 
Empower Inclusion Through Accessible Java Applications
Ana-Maria Mihalceanu
 
From Sci-Fi to Reality: Exploring AI Evolution
Svetlana Meissner
 
Exolore The Essential AI Tools in 2025.pdf
Srinivasan M
 
"Beyond English: Navigating the Challenges of Building a Ukrainian-language R...
Fwdays
 
Q2 FY26 Tableau User Group Leader Quarterly Call
lward7
 
COMPARISON OF RASTER ANALYSIS TOOLS OF QGIS AND ARCGIS
Sharanya Sarkar
 
AI Penetration Testing Essentials: A Cybersecurity Guide for 2025
defencerabbit Team
 
Transcript: New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
AUTOMATION AND ROBOTICS IN PHARMA INDUSTRY.pptx
sameeraaabegumm
 
The Builder’s Playbook - 2025 State of AI Report.pdf
jeroen339954
 
Presentation - Vibe Coding The Future of Tech
yanuarsinggih1
 
Complete JavaScript Notes: From Basics to Advanced Concepts.pdf
haydendavispro
 
Newgen 2022-Forrester Newgen TEI_13 05 2022-The-Total-Economic-Impact-Newgen-...
darshakparmar
 
Python basic programing language for automation
DanialHabibi2
 
Achieving Consistent and Reliable AI Code Generation - Medusa AI
medusaaico
 
Reverse Engineering of Security Products: Developing an Advanced Microsoft De...
nwbxhhcyjv
 
UiPath Academic Alliance Educator Panels: Session 2 - Business Analyst Content
DianaGray10
 
Smart Trailers 2025 Update with History and Overview
Paul Menig
 
July Patch Tuesday
Ivanti
 
Chris Elwell Woburn, MA - Passionate About IT Innovation
Chris Elwell Woburn, MA
 

A test framework out of the box - Geb for Web and mobile

  • 1. 1 A test framework out of the box - Geb for Web and mobile Yaroslav Sviatkin Senior Test Automation Engineer, Consultant
  • 2. 2
  • 4. 4 JDI UI Test Automation Framework @JSite(domain = "https://epam.github.io/JDI/") public class JDIExampleSite extends WebSite { public static HomePage homePage; public static LoginForm loginForm; @FindBy(css = ".profile-photo") public static Label profilePhoto; public static void login() { profilePhoto.click(); loginForm.loginAs(new User()); } }
  • 5. 5 Automated Acceptance Testing with Style http://www.thucydides.info/#/
  • 6. 6
  • 7. 7 Project structure Page Object classes Steps implementation class Stories classes Requirements for the application under test
  • 8. 8 Organizing requirements First, you create a model of the features and user stories you intend to implement: Stories Features
  • 9. 9 Page Objects Next you will need to implement your page objects. These are almost just run-of-the-mill WebDriver page objects, but with a few enhancements:
  • 10. 10 Steps implementation Now implement the actual test steps using either WebDriver page objects or other test steps. Here you start thinking about implementation: A step library High level steps... ...implemented with Page Objects ...or with other steps
  • 11. 11
  • 13. 13
  • 15. 15 Geb is a browser automation solution What is Geb?
  • 16. 16 • Any web and mobile applications • App doesn't need to be written in Groovy What can you test with Geb?
  • 17. 17 go "http://www.google.com" $("input", name: "q").value("geb") $("button", name: "btnG").click() waitFor { $("#search").displayed } $("h3.r").first().click() waitFor { title == "Geb - Very Groovy Browser
  • 18. 18 Selector syntax title { $(By.xpath(".//h4[@class='title ng- binding']")).text() $("#by-id") $(".by-class") $("div", name: "by-attribute") $("div", text: "By text") $(By.id("some-id")) $(By.className("some-class")) $(By.xpath('//p[@class="xpath"]')) …
  • 19. 19 assert $("p", 1..2)*.text() == ["b", "c"] assert $("p", text: ~/p./).size() == 2 assert $("p", text: startsWith("p")).size() == 2
  • 20. 20 assert $("p.d").previous() == $("p.c") assert $("p.e").prevAll() == $("p.c").add("p.d") assert $("p.d").next() == $("p.e") assert $("p.c").nextAll() == $("p.d").add("p.e") assert $("p.d").parent() == $("div.b") assert $("p.c").siblings() == $("p.d").add("p.e") assert $("div.a").children() == $("div.b").add("div.f")
  • 21. 21 project { String index -> $(By.xpath("//div[@class=card-item']//h4[@title='${index}']")).click() } projectPage.project(nameProject)
  • 22. 22 dynamicallyAdded(wait: true) { $("p.dynamic") } dynamicallyAdded(wait: 5, required: false) { $("p.dynamic") } cachedValue(cache: true) { value } helpLink(to: HelpPage) { $("a", text: "Help") }
  • 25. 25 Control modules • FormElement • Checkbox • Select • MultipleSelect • TextInput • Textarea • FileInput • RadioButtons
  • 26. 26 class ExamplePage extends Page { static content = { theModule { module ExampleModule } } } class ExampleModule extends Module { static content = { button { $("input", type: "submit") } } }
  • 27. 27 class NotificationModule extends Module { static content = { notifocation { $(By.xpath(".//li[contains(@ng-repeat,'notifications')]")).moduleList(Notification) } gotItButton { $(By.xpath(".//button[@ng-click='appCtrl.gotItNotifications()']")) } } } class Notification extends Module { static content = { name { $(By.xpath("//h5")).text() } dete { $(By.xpath("//div[contains(@class,'date')]")).text() } notification { $(By.xpath("//p")) text() } } }
  • 28. 28 searchResult(required: false, wait: 5) { $(By.xpath("//li/a/strong"))*.text() } notification { $(By.xpath("//ul[contains(@ng-if,'notifications')]")).module(NotificationModule) } menuLinksModule(wait: 5) { $(By.xpath("//button[contains(@class,'services')]")).module(MenuLinksModule) }
  • 29. 29 class IdeaCreatePage extends geb.Page { static at = { $("div#create-idea").displayed } } static content = { createButton(to: IdeaShowPage) { $("input#create") } } IdeaCreatePage ideaCreatePage = to(IdeaCreatePage) isAt(IdeaCreatePage)
  • 30. 30 • class LoginPage extends Page { static url = "access/signin" static at = { browser.currentUrl.startsWith("https://wwwwwwwwww.com") } static content = { userName(wait: 5) { $(By.xpath("//input[@type='text']")) } userPassword { $(By.xpath("//input[@type='password']")) } loginError(required: false, wait: 3) { $(By.xpath("//div[@class='error']")).text() } loginSubmit { $("button", text: startsWith("Login")).click() } heading (to:BasePage){ $(By.xpath("//div[@class='info']/h1")).text() } } def login(String login, String password) { userName.firstElement().clear() userPassword.firstElement().clear() userName << login userPassword << password loginSubmit } }
  • 31. 31 waitFor examples waitFor { $("div.alert").displayed } waitFor { $("div.message").text() == "Update successful" }
  • 32. 32 Mouse interactions void moveRatingSlider(Integer rating) { // Slider is 400 pixels wide and starts at 1, // so each notch above 1 is 100 pixels apart Integer numPixelsX = (rating - 1) * 100 interact { clickAndHold(ratingSliderHandle) moveByOffset(numPixelsX, 0) release() } } WebElement underlyingElement = $('#myElement').getElement(0) Action action = new Actions(browser.driver) .clickAndHold(underlyingElement) .moveByOffset(15,15) .release() .build() action.perform() } Use keyboard $(".ui-slider-handle") << Keys.ARROW_RIGHT
  • 33. 33 Already opened windows withWindow({ title == "Geb - Very Groovy Browser Automation" }) { assert $("#slogan").text().startsWith("very groovy browser automation…") } } withNewWindow({ $('a').click() }) { assert title == 'Geb - Very Groovy Browser Automation' }
  • 34. 34 @Test void feedBackReferenceTest() { openMenu browser.withNewWindow({ basePage.menuLinksModule.feedback }, { assert browser.currentUrl.startsWith("https://helpdesk.com/") }) } @Test void officeMapReferenceTest() { openMenu browser.withWindow({ basePage.menuLinksModule.officeMap }, { if (browser.currentUrl == signinUrl) { loginPage.login(userName, userPassword) } assert browser.currentUrl == "https://portal.com" }) browser.to(ProjectPage) }
  • 35. 35 Show hidden element void scrollUp() { js.exec("""window.scrollTo(0,0)""") } $("div#a").jquery.mouseov er() Browser.drive { assert js.myGlobalVar == 1 }
  • 37. 37 waiting { timeout = 2 } baseUrl = "https://wwwwwwwww.com/" autoClearCookies = false atCheckWaiting = true baseNavigatorWaiting = true name = '' password = '' mail ='' environments { chrome { driver = { def driverInstance = new ChromeDriver() driverInstance.manage().window().maximize() driverInstance } } firefox { driver = { def driverInstance = new FirefoxDriver() driverInstance.manage().window().maximize() driverInstance } } ie { driver = { def driverInstance = new InternetExplorerDriver() driverInstance.manage().window().maximize() driverInstance } }} //Receiving name and password from GebConfig.groovy final String userName = browser.config.rawConfig.name final String userPassword = browser.config.rawConfig.password
  • 38. 38 task chromeTest(type: Test) { systemProperty "geb.env", "chrome" systemProperty "webdriver.chrome.driver", "driverschromedriver.exe" useTestNG { suites "srctestresourcestestng-suite.xml" useDefaultListeners = true } } // Drivers testCompile "org.seleniumhq.selenium:selenium-chrome-driver:$seleniumVersion" testCompile "org.seleniumhq.selenium:selenium-firefox-driver:$seleniumVersion" testCompile "org.seleniumhq.selenium:selenium-ie-driver:$seleniumVersion"
  • 39. 39 static String randomString(int count) { (1..count).inject("") { a, b -> a += ('a'..'z')[new Random().nextFloat() * 26 as int] }.capitalize() } def getWanted() { def result = [] HTTPRequest.request(GET, JSON) { req -> uri.path = '/wanted' headers.'Auth' = "${TOKEN}" response.success = { resp, json -> println new JsonBuilder( json).toPrettyString() (json as ArrayList).each { String name = it.name def projects = [] (it.projects as ArrayList).each { projects << [it.projectid.'$oid', it.title] } result << [name, projects].flatten() } } } result }
  • 40. 40 List getAllIdProject() { def result = [] GITLAB.get(path: "/gitlab/api/v3/projects/all") { resp, json -> println new JsonBuilder(json).toPrettyString() def request = (json as Map) result = request*.id } result } assert loginPage.heading == "Welcome"
  • 43. 43
  • 45. 45 Yaroslav Sviatkin Senior Test Automation Engineer, Consultant [email protected] Thank you