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

PDF
OpenCms Days 2014 - User Generated Content in OpenCms 9.5
PPTX
Geb qa fest2017
PDF
Databinding and Performance-Tuning in Angular 2
PDF
Building a Windows Store App for SharePoint 2013
PPTX
Angular 2 Architecture (Bucharest 26/10/2016)
PDF
Prototype UI
PPT
PPTX
Windows Store app using XAML and C#: Enterprise Product Development
OpenCms Days 2014 - User Generated Content in OpenCms 9.5
Geb qa fest2017
Databinding and Performance-Tuning in Angular 2
Building a Windows Store App for SharePoint 2013
Angular 2 Architecture (Bucharest 26/10/2016)
Prototype UI
Windows Store app using XAML and C#: Enterprise Product Development

What's hot (20)

PDF
JavaScript para Graficos y Visualizacion de Datos - BogotaJS
PDF
Basic Tutorial of React for Programmers
PDF
Better Bullshit Driven Development [SeleniumCamp 2017]
PDF
Awesome State Management for React and Other Virtual-Dom Libraries
PPTX
Performance Optimization In Angular 2
PPTX
Présentation et bonnes pratiques du pattern MVVM - MIC Belgique
PPTX
Javascript 2
PDF
Desenvolvimento web com Ruby on Rails (extras)
PDF
Building Reusable Custom Elements With Angular
PPTX
Test and profile your Windows Phone 8 App
PDF
Taking Web Apps Offline
PPTX
Mobile App Development: Primi passi con NativeScript e Angular 2
KEY
Django quickstart
PPTX
Angular 2 - Ahead of-time Compilation
PDF
A To-do Web App on Google App Engine
PDF
22 j query1
PDF
Introduction to jQuery
PDF
JQuery UI
PPT
Yui app-framework
PDF
Reactive Type-safe WebComponents
JavaScript para Graficos y Visualizacion de Datos - BogotaJS
Basic Tutorial of React for Programmers
Better Bullshit Driven Development [SeleniumCamp 2017]
Awesome State Management for React and Other Virtual-Dom Libraries
Performance Optimization In Angular 2
Présentation et bonnes pratiques du pattern MVVM - MIC Belgique
Javascript 2
Desenvolvimento web com Ruby on Rails (extras)
Building Reusable Custom Elements With Angular
Test and profile your Windows Phone 8 App
Taking Web Apps Offline
Mobile App Development: Primi passi con NativeScript e Angular 2
Django quickstart
Angular 2 - Ahead of-time Compilation
A To-do Web App on Google App Engine
22 j query1
Introduction to jQuery
JQuery UI
Yui app-framework
Reactive Type-safe WebComponents
Ad

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

PPTX
QA Fest 2017. Ярослав Святкин. Тестовый фреймворк GEB для тестирования WEB пр...
PDF
Continuous integration using thucydides(bdd) with selenium
PDF
Google App Engine in 40 minutes (the absolute essentials)
PPTX
Continuous integration using thucydides(bdd) with selenium
PDF
Three Simple Chords of Alternative PageObjects and Hardcore of LoadableCompon...
PDF
Workshop: Building Vaadin add-ons
PDF
Prototype UI Intro
PDF
Hybrid App using WordPress
PDF
OSGi and Spring Data for simple (Web) Application Development - Christian Bar...
PDF
OSGi and Spring Data for simple (Web) Application Development
PDF
Java Web Programming [8/9] : JSF and AJAX
PDF
Aplicacoes dinamicas Rails com Backbone
PPTX
01 Introduction - JavaScript Development
PDF
jQuery in the [Aol.] Enterprise
PDF
Building iPhone Web Apps using "classic" Domino
PDF
Gae Meets Django
PDF
Breaking the limits_of_page_objects
PDF
Building a Pyramid: Symfony Testing Strategies
PDF
Geb presentation
PDF
Django at the Disco
QA Fest 2017. Ярослав Святкин. Тестовый фреймворк GEB для тестирования WEB пр...
Continuous integration using thucydides(bdd) with selenium
Google App Engine in 40 minutes (the absolute essentials)
Continuous integration using thucydides(bdd) with selenium
Three Simple Chords of Alternative PageObjects and Hardcore of LoadableCompon...
Workshop: Building Vaadin add-ons
Prototype UI Intro
Hybrid App using WordPress
OSGi and Spring Data for simple (Web) Application Development - Christian Bar...
OSGi and Spring Data for simple (Web) Application Development
Java Web Programming [8/9] : JSF and AJAX
Aplicacoes dinamicas Rails com Backbone
01 Introduction - JavaScript Development
jQuery in the [Aol.] Enterprise
Building iPhone Web Apps using "classic" Domino
Gae Meets Django
Breaking the limits_of_page_objects
Building a Pyramid: Symfony Testing Strategies
Geb presentation
Django at the Disco
Ad

More from GlobalLogic Ukraine (20)

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

Recently uploaded (20)

PPTX
A Presentation on Artificial Intelligence
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...
PDF
Assigned Numbers - 2025 - Bluetooth® Document
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
August Patch Tuesday
PPTX
TechTalks-8-2019-Service-Management-ITIL-Refresh-ITIL-4-Framework-Supports-Ou...
PDF
Empathic Computing: Creating Shared Understanding
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PDF
Accuracy of neural networks in brain wave diagnosis of schizophrenia
PPTX
Tartificialntelligence_presentation.pptx
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
A comparative study of natural language inference in Swahili using monolingua...
PDF
Machine learning based COVID-19 study performance prediction
PDF
A comparative analysis of optical character recognition models for extracting...
A Presentation on Artificial Intelligence
Advanced methodologies resolving dimensionality complications for autism neur...
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...
Assigned Numbers - 2025 - Bluetooth® Document
Mobile App Security Testing_ A Comprehensive Guide.pdf
Network Security Unit 5.pdf for BCA BBA.
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
Digital-Transformation-Roadmap-for-Companies.pptx
August Patch Tuesday
TechTalks-8-2019-Service-Management-ITIL-Refresh-ITIL-4-Framework-Supports-Ou...
Empathic Computing: Creating Shared Understanding
Agricultural_Statistics_at_a_Glance_2022_0.pdf
Diabetes mellitus diagnosis method based random forest with bat algorithm
Accuracy of neural networks in brain wave diagnosis of schizophrenia
Tartificialntelligence_presentation.pptx
Building Integrated photovoltaic BIPV_UPV.pdf
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
A comparative study of natural language inference in Swahili using monolingua...
Machine learning based COVID-19 study performance prediction
A comparative analysis of optical character recognition models for extracting...

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