SlideShare a Scribd company logo
Тестовый фреймворк GEB
для тестирования WEB
приложений и Mobile
YaroslavSviatkin
email:yariks@i.ua
http://sviatkin.com
QA Fest 2017. Ярослав Святкин. Тестовый фреймворк GEB для тестирования WEB приложений и Mobile
HtmlElements. Page Object
JDI UI Test Automation Framework
@JSite(domain="https://epam.github.io/JDI/")
publicclassJDIExampleSiteextendsWebSite{
publicstaticHomePagehomePage;
publicstaticLoginFormloginForm;
@FindBy(css=".profile-photo")
publicstaticLabelprofilePhoto;
publicstaticvoidlogin(){
profilePhoto.click();
loginForm.loginAs(newUser());
}
}
Automated Acceptance
Testing with Style
http://www.thucydides.info/#/
QA Fest 2017. Ярослав Святкин. Тестовый фреймворк GEB для тестирования WEB приложений и Mobile
Project structure
Page Object classes
Steps implementation class
Stories classes
Requirements for the
application under test
Organizing requirements
First, you create a model of the features and user stories you intend to implement:
Stories
Features
Confidential
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:
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
QA Fest 2017. Ярослав Святкин. Тестовый фреймворк GEB для тестирования WEB приложений и Mobile
Selenide
http://selenide.org
QA Fest 2017. Ярослав Святкин. Тестовый фреймворк GEB для тестирования WEB приложений и Mobile
Geb
http://www.gebish.org
What is Geb?
Geb is a browser automation solution
What can you test with Geb?
• Any web and mobile applications
• App doesn't need to be written in Groovy
go"http://www.google.com"
$("input",name:"q").value("geb")
$("button",name:"btnG").click()
waitFor{$("#search").displayed}
$("h3.r").first().click()
waitFor{title=="Geb-VeryGroovyBrowserAutomation"}
Selector syntax
$("#by-id")
$(".by-class")
$("div",name:"by-attribute")
$("div",text:"Bytext")
$(By.id("some-id"))
$(By.className("some-class"))
$(By.xpath('//p[@class="xpath"]'))
…
title{$(By.xpath(".//h4[@class='titleng-binding']")).text()
assert$("p",1..2)*.text()==["b","c"]
assert$("p",text:~/p./).size()==2
assert$("p",text:startsWith("p")).size()==2
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")
project { String index -> $(By.xpath("//div[@class=card-item']//h4[@title='${index}']")).click() }
projectPage.project(nameProject)
dynamicallyAdded(wait:true){$("p.dynamic")}
dynamicallyAdded(wait:5,required:false){$("p.dynamic")}
cachedValue(cache:true){value}
helpLink(to:HelpPage){$("a",text:"Help")}
Page Object Model
Page
Module
Control modules
• FormElement
• Checkbox
• Select
• MultipleSelect
• TextInput
• Textarea
• FileInput
• RadioButtons
classExamplePageextendsPage{
staticcontent={
theModule{moduleExampleModule}
}
}
classExampleModuleextendsModule{
staticcontent={
button{$("input",type:"submit")}
}
}
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() }
}
}
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) }
Verify test at current page
classIdeaCreatePageextendsgeb.Page{
staticat={$("div#create-idea").displayed}
}
staticcontent={
createButton(to:IdeaShowPage){$("input#create")}
}
IdeaCreatePageideaCreatePage=to(IdeaCreatePage)
isAt(IdeaCreatePage)
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
}
}
LoginPage loginPage = page(LoginPage)
waitFor examples
waitFor{
$("div.alert").displayed
}
waitFor{
$("div.message").text()=="Updatesuccessful"
}
Mouse interactions
voidmoveRatingSlider(Integerrating){
//Slideris400pixelswideandstartsat1,
//soeachnotchabove1is100pixelsapart
IntegernumPixelsX=(rating-1)*100
interact{
clickAndHold(ratingSliderHandle)
moveByOffset(numPixelsX,0)
release()
}
}
WebElementunderlyingElement=
$('#myElement').getElement(0)
Actionaction=newActions(browser.driver)
.clickAndHold(underlyingElement)
.moveByOffset(15,15)
.release()
.build()
action.perform()
}
Use keyboard
$(".ui-slider-handle")<<Keys.ARROW_RIGHT
Already opened windows
withWindow({title=="Geb-VeryGroovyBrowserAutomation"}){
assert$("#slogan").text().startsWith("verygroovybrowserautomation…")
}
}
withNewWindow({$('a').click()}){
asserttitle=='Geb-VeryGroovyBrowserAutomation'
}
@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)
}
Show hidden element
void scrollUp() {
js.exec("""window.scrollTo(0,0)""")
}
$("div#a").jquery.mouseover() Browser.drive{
assertjs.myGlobalVar==1
}
Available browsers
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
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"
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
}
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"
Geb integrates with
Geb-mobile
https://github.com/JasonKissinger-MDT/geb-mobile
QA Fest 2017. Ярослав Святкин. Тестовый фреймворк GEB для тестирования WEB приложений и Mobile
email : yariks@i.ua
http://sviatkin.com

More Related Content

PDF
QA Fest 2017. Яков Крамаренко. Minimum Usable Framework
QAFest
 
PPT
jQuery for beginners
Divakar Gu
 
PPTX
Hack Day EU 2011 YQL
Jonathan LeBlanc
 
PPTX
Hack with YUI
Luke Smith
 
PPTX
Adding a modern twist to legacy web applications
Jeff Durta
 
PDF
A Journey with React
FITC
 
PDF
Getting Started with React
Nathan Smith
 
KEY
SproutCore is Awesome - HTML5 Summer DevFest
tomdale
 
QA Fest 2017. Яков Крамаренко. Minimum Usable Framework
QAFest
 
jQuery for beginners
Divakar Gu
 
Hack Day EU 2011 YQL
Jonathan LeBlanc
 
Hack with YUI
Luke Smith
 
Adding a modern twist to legacy web applications
Jeff Durta
 
A Journey with React
FITC
 
Getting Started with React
Nathan Smith
 
SproutCore is Awesome - HTML5 Summer DevFest
tomdale
 

What's hot (20)

PPTX
jQuery Presentation
Rod Johnson
 
PDF
Discover React
Massimo Iacolare
 
PDF
jQuery Presentation to Rails Developers
Yehuda Katz
 
PDF
Merb jQuery
Yehuda Katz
 
PPT
Asynchronous JavaScript & XML (AJAX)
Adnan Sohail
 
PPTX
jQuery
i.omar
 
PDF
Simplify AJAX using jQuery
Siva Arunachalam
 
PDF
Introduction to Jquery
Tajendar Arora
 
PPT
jQuery Ajax
Anand Kumar Rajana
 
PDF
React.js & Om: A hands-on walkthrough of better ways to build web UIs
Adam Solove
 
PDF
Speed is a feature - Django Meetup Buenos Aires June 2014
Pablo Mouzo
 
PDF
How to write easy-to-test JavaScript
Ynon Perek
 
PPTX
The Real Story Behind JavaScript Performance on Mobile... Because Science!
Ryan J. Salva
 
PPTX
Ajax and Jquery
People Strategists
 
PDF
The Django Web Framework (EuroPython 2006)
Simon Willison
 
PPTX
Testable Javascript
Mark Trostler
 
PDF
Cheap tricks for startups
Simon Willison
 
PDF
Pushing the Web: Interesting things to Know
n|u - The Open Security Community
 
PPTX
How to identify bad third parties on your page
Charles Vazac
 
PPT
Ajax Fundamentals Web Applications
dominion
 
jQuery Presentation
Rod Johnson
 
Discover React
Massimo Iacolare
 
jQuery Presentation to Rails Developers
Yehuda Katz
 
Merb jQuery
Yehuda Katz
 
Asynchronous JavaScript & XML (AJAX)
Adnan Sohail
 
jQuery
i.omar
 
Simplify AJAX using jQuery
Siva Arunachalam
 
Introduction to Jquery
Tajendar Arora
 
jQuery Ajax
Anand Kumar Rajana
 
React.js & Om: A hands-on walkthrough of better ways to build web UIs
Adam Solove
 
Speed is a feature - Django Meetup Buenos Aires June 2014
Pablo Mouzo
 
How to write easy-to-test JavaScript
Ynon Perek
 
The Real Story Behind JavaScript Performance on Mobile... Because Science!
Ryan J. Salva
 
Ajax and Jquery
People Strategists
 
The Django Web Framework (EuroPython 2006)
Simon Willison
 
Testable Javascript
Mark Trostler
 
Cheap tricks for startups
Simon Willison
 
Pushing the Web: Interesting things to Know
n|u - The Open Security Community
 
How to identify bad third parties on your page
Charles Vazac
 
Ajax Fundamentals Web Applications
dominion
 
Ad

Similar to QA Fest 2017. Ярослав Святкин. Тестовый фреймворк GEB для тестирования WEB приложений и Mobile (20)

PPTX
Geb qa fest2017
Sviatkin Yaroslav
 
PPTX
A test framework out of the box - Geb for Web and mobile
GlobalLogic Ukraine
 
PPTX
A Rich Web Experience with jQuery, Ajax and .NET
James Johnson
 
PPTX
A Rich Web experience with jQuery, Ajax and .NET
James Johnson
 
PDF
Building iPhone Web Apps using "classic" Domino
Rob Bontekoe
 
PDF
jQuery
Ivano Malavolta
 
PDF
jQuery secrets
Bastian Feder
 
KEY
Week 4 - jQuery + Ajax
baygross
 
PPTX
jQuery for web development
iFour Institute - Sustainable Learning
 
ODP
JQuery introduction
Pradeep Saraswathi
 
PPTX
Continuous integration using thucydides(bdd) with selenium
Khyati Sehgal
 
PDF
jQuery in the [Aol.] Enterprise
Dave Artz
 
PDF
jQuery Rescue Adventure
Allegient
 
PPTX
jQuery
Dileep Mishra
 
PPTX
Unit3.pptx
AnamikaRai59
 
PDF
international PHP2011_Bastian Feder_jQuery's Secrets
smueller_sandsmedia
 
PPTX
Jquery Basics
Umeshwaran V
 
PPTX
Jquery Complete Presentation along with Javascript Basics
EPAM Systems
 
PPT
Kick start with j query
Md. Ziaul Haq
 
Geb qa fest2017
Sviatkin Yaroslav
 
A test framework out of the box - Geb for Web and mobile
GlobalLogic Ukraine
 
A Rich Web Experience with jQuery, Ajax and .NET
James Johnson
 
A Rich Web experience with jQuery, Ajax and .NET
James Johnson
 
Building iPhone Web Apps using "classic" Domino
Rob Bontekoe
 
jQuery secrets
Bastian Feder
 
Week 4 - jQuery + Ajax
baygross
 
jQuery for web development
iFour Institute - Sustainable Learning
 
JQuery introduction
Pradeep Saraswathi
 
Continuous integration using thucydides(bdd) with selenium
Khyati Sehgal
 
jQuery in the [Aol.] Enterprise
Dave Artz
 
jQuery Rescue Adventure
Allegient
 
Unit3.pptx
AnamikaRai59
 
international PHP2011_Bastian Feder_jQuery's Secrets
smueller_sandsmedia
 
Jquery Basics
Umeshwaran V
 
Jquery Complete Presentation along with Javascript Basics
EPAM Systems
 
Kick start with j query
Md. Ziaul Haq
 
Ad

More from QAFest (20)

PDF
QA Fest 2019. Сергій Короленко. Топ веб вразливостей за 40 хвилин
QAFest
 
PPTX
QA Fest 2019. Анна Чернышова. Self-healing test automation 2.0. The Future
QAFest
 
PPTX
QA Fest 2019. Doug Sillars. It's just too Slow: Testing Mobile application pe...
QAFest
 
PDF
QA Fest 2019. Катерина Спринсян. Параллельное покрытие автотестами и другие и...
QAFest
 
PDF
QA Fest 2019. Никита Галкин. Как зарабатывать больше
QAFest
 
PDF
QA Fest 2019. Сергей Пирогов. Why everything is spoiled
QAFest
 
PDF
QA Fest 2019. Сергей Новик. Между мотивацией и выгоранием
QAFest
 
PPTX
QA Fest 2019. Владимир Никонов. Код Шредингера или зачем и как мы тестируем н...
QAFest
 
PPTX
QA Fest 2019. Владимир Трандафилов. GUI automation of WEB application with SV...
QAFest
 
PDF
QA Fest 2019. Иван Крутов. Bulletproof Selenium Cluster
QAFest
 
PPTX
QA Fest 2019. Николай Мижигурский. Миссия /*не*/выполнима: гуманитарий собесе...
QAFest
 
PDF
QA Fest 2019. Володимир Стиран. Чим раніше – тим вигідніше, але ніколи не піз...
QAFest
 
PPTX
QA Fest 2019. Дмитрий Прокопук. Mocks and network tricks in UI automation
QAFest
 
PDF
QA Fest 2019. Екатерина Дядечко. Тестирование медицинского софта — вызовы и в...
QAFest
 
PDF
QA Fest 2019. Катерина Черникова. Tune your P’s: the pop-art of keeping testa...
QAFest
 
PDF
QA Fest 2019. Алиса Бойко. Какнезапутаться в коммуникативных сетях IT
QAFest
 
PPTX
QA Fest 2019. Святослав Логин. Как найти уязвимости в мобильном приложении
QAFest
 
PPTX
QA Fest 2019. Катерина Шепелєва та Інна Оснач. Що українцям потрібно знати пр...
QAFest
 
PDF
QA Fest 2019. Антон Серпутько. Нагрузочное тестирование распределенных асинхр...
QAFest
 
PPTX
QA Fest 2019. Петр Тарасенко. QA Hackathon - The Cookbook 22
QAFest
 
QA Fest 2019. Сергій Короленко. Топ веб вразливостей за 40 хвилин
QAFest
 
QA Fest 2019. Анна Чернышова. Self-healing test automation 2.0. The Future
QAFest
 
QA Fest 2019. Doug Sillars. It's just too Slow: Testing Mobile application pe...
QAFest
 
QA Fest 2019. Катерина Спринсян. Параллельное покрытие автотестами и другие и...
QAFest
 
QA Fest 2019. Никита Галкин. Как зарабатывать больше
QAFest
 
QA Fest 2019. Сергей Пирогов. Why everything is spoiled
QAFest
 
QA Fest 2019. Сергей Новик. Между мотивацией и выгоранием
QAFest
 
QA Fest 2019. Владимир Никонов. Код Шредингера или зачем и как мы тестируем н...
QAFest
 
QA Fest 2019. Владимир Трандафилов. GUI automation of WEB application with SV...
QAFest
 
QA Fest 2019. Иван Крутов. Bulletproof Selenium Cluster
QAFest
 
QA Fest 2019. Николай Мижигурский. Миссия /*не*/выполнима: гуманитарий собесе...
QAFest
 
QA Fest 2019. Володимир Стиран. Чим раніше – тим вигідніше, але ніколи не піз...
QAFest
 
QA Fest 2019. Дмитрий Прокопук. Mocks and network tricks in UI automation
QAFest
 
QA Fest 2019. Екатерина Дядечко. Тестирование медицинского софта — вызовы и в...
QAFest
 
QA Fest 2019. Катерина Черникова. Tune your P’s: the pop-art of keeping testa...
QAFest
 
QA Fest 2019. Алиса Бойко. Какнезапутаться в коммуникативных сетях IT
QAFest
 
QA Fest 2019. Святослав Логин. Как найти уязвимости в мобильном приложении
QAFest
 
QA Fest 2019. Катерина Шепелєва та Інна Оснач. Що українцям потрібно знати пр...
QAFest
 
QA Fest 2019. Антон Серпутько. Нагрузочное тестирование распределенных асинхр...
QAFest
 
QA Fest 2019. Петр Тарасенко. QA Hackathon - The Cookbook 22
QAFest
 

Recently uploaded (20)

PPTX
A Smarter Way to Think About Choosing a College
Cyndy McDonald
 
PPTX
INTESTINALPARASITES OR WORM INFESTATIONS.pptx
PRADEEP ABOTHU
 
PDF
BÀI TẬP TEST BỔ TRỢ THEO TỪNG CHỦ ĐỀ CỦA TỪNG UNIT KÈM BÀI TẬP NGHE - TIẾNG A...
Nguyen Thanh Tu Collection
 
PPTX
Sonnet 130_ My Mistress’ Eyes Are Nothing Like the Sun By William Shakespear...
DhatriParmar
 
PDF
Review of Related Literature & Studies.pdf
Thelma Villaflores
 
PPTX
Gupta Art & Architecture Temple and Sculptures.pptx
Virag Sontakke
 
PDF
Virat Kohli- the Pride of Indian cricket
kushpar147
 
PPTX
Information Texts_Infographic on Forgetting Curve.pptx
Tata Sevilla
 
PDF
The Minister of Tourism, Culture and Creative Arts, Abla Dzifa Gomashie has e...
nservice241
 
DOCX
SAROCES Action-Plan FOR ARAL PROGRAM IN DEPED
Levenmartlacuna1
 
PPTX
Tips Management in Odoo 18 POS - Odoo Slides
Celine George
 
DOCX
Modul Ajar Deep Learning Bahasa Inggris Kelas 11 Terbaru 2025
wahyurestu63
 
PPTX
How to Close Subscription in Odoo 18 - Odoo Slides
Celine George
 
PPTX
Care of patients with elImination deviation.pptx
AneetaSharma15
 
PPTX
Artificial Intelligence in Gastroentrology: Advancements and Future Presprec...
AyanHossain
 
PPTX
CDH. pptx
AneetaSharma15
 
PDF
What is CFA?? Complete Guide to the Chartered Financial Analyst Program
sp4989653
 
PPTX
Kanban Cards _ Mass Action in Odoo 18.2 - Odoo Slides
Celine George
 
PPTX
CONCEPT OF CHILD CARE. pptx
AneetaSharma15
 
PPTX
An introduction to Dialogue writing.pptx
drsiddhantnagine
 
A Smarter Way to Think About Choosing a College
Cyndy McDonald
 
INTESTINALPARASITES OR WORM INFESTATIONS.pptx
PRADEEP ABOTHU
 
BÀI TẬP TEST BỔ TRỢ THEO TỪNG CHỦ ĐỀ CỦA TỪNG UNIT KÈM BÀI TẬP NGHE - TIẾNG A...
Nguyen Thanh Tu Collection
 
Sonnet 130_ My Mistress’ Eyes Are Nothing Like the Sun By William Shakespear...
DhatriParmar
 
Review of Related Literature & Studies.pdf
Thelma Villaflores
 
Gupta Art & Architecture Temple and Sculptures.pptx
Virag Sontakke
 
Virat Kohli- the Pride of Indian cricket
kushpar147
 
Information Texts_Infographic on Forgetting Curve.pptx
Tata Sevilla
 
The Minister of Tourism, Culture and Creative Arts, Abla Dzifa Gomashie has e...
nservice241
 
SAROCES Action-Plan FOR ARAL PROGRAM IN DEPED
Levenmartlacuna1
 
Tips Management in Odoo 18 POS - Odoo Slides
Celine George
 
Modul Ajar Deep Learning Bahasa Inggris Kelas 11 Terbaru 2025
wahyurestu63
 
How to Close Subscription in Odoo 18 - Odoo Slides
Celine George
 
Care of patients with elImination deviation.pptx
AneetaSharma15
 
Artificial Intelligence in Gastroentrology: Advancements and Future Presprec...
AyanHossain
 
CDH. pptx
AneetaSharma15
 
What is CFA?? Complete Guide to the Chartered Financial Analyst Program
sp4989653
 
Kanban Cards _ Mass Action in Odoo 18.2 - Odoo Slides
Celine George
 
CONCEPT OF CHILD CARE. pptx
AneetaSharma15
 
An introduction to Dialogue writing.pptx
drsiddhantnagine
 

QA Fest 2017. Ярослав Святкин. Тестовый фреймворк GEB для тестирования WEB приложений и Mobile