SlideShare ist ein Scribd-Unternehmen logo
1 von 108
Downloaden Sie, um offline zu lesen
1
GEB FOR BROWSER
AUTOMATION
Jacob Aae Mikkelsen
AGENDA
Functional testing
Geb - cudos and history
How Geb works
Geb and Ratpack, Grails 2 and 3
Browser support
Tips and Tricks
2 . 1
JACOB AAE MIKKELSEN
Senior Engineer at LEGO
Microservice based architechture on JVM
Previously 4 years at Gennemtænkt IT
Consultant on Groovy and Grails
External Associate Professor - University of Southern
Denmark
@JacobAae
Blogs The Grails Diary
2 . 23 . 1
FUNCTIONAL TESTING
3 . 2
WHY?
3 . 3
3 . 4
FUNCTIONAL TESTING
Ignores the specifics of the underlying so ware
component under test.
Whitebox / Greybox
Merely asserts that providing certain input results in
certain output.
Web-application: Programmatically controlling a web
browser to simulate the actions of a user on a web page.
3 . 5
BROWSER AUTOMATION
3 . 64 . 1
4 . 2
GEB HISTORY
Started in November 2009
Created by Luke Daley
Current project lead Marcin Erdman
GEB IMPLEMENTATION
Build on top of the WebDriver browser automation library
successor to the Selenium Remote Control (RC) testing
framework.
Selenium RC → JavaScript to interact
WebDriver → native browser drivers
Use JUnit or Spock
4 . 3
WEBDRIVER
Very active development
Stable API and feature set
Verbose
Low level
Not a complete solution
4 . 4
WHY GEB
jQuery like selector syntax
Power of WebDriver (Easier api)
Robustness of Page Object modeling
Expressiveness of the Groovy language
Integrates well with build systems (Gradle/Maven)
Excellent user manual/documentation
4 . 5
5 . 1
USING GEB
4 . 6
5 . 2
NAVIGATOR
The $()method returns a Navigator object
General format - Jquery like selecter syntax
$ ( < c s s s e l e c t o r > , < i n d e x / r a n g e > , < a t t r i b u t e / t e x t m a t c h e r s > )
GEB SELECTORS (1)
/ / m a t c h a l l ' p ' e l e m e n t s o n p a g e
$ ( " p " )
/ / m a t c h t h e f i r s t ' p ' e l e m e n t o n t h e p a g e
$ ( " p " , 0 )
/ / A l l ' d i v ' e l e m e n t s w i t h a t i t l e v a l u e ' s e c t i o n '
$ ( " d i v " , t i t l e : " s e c t i o n " )
/ / m a t c h t h e f i r s t ' d i v ' e l e m e n t t e x t ' s e c t i o n '
$ ( " d i v " , 0 , t e x t : " s e c t i o n " )
/ / m a t c h t h e f i r s t ' d i v ' e l e m e n t w i t h t h e c l a s s ' m a i n '
$ ( " d i v . m a i n " , 0 )
5 . 3
GEB SELECTORS (2)
Text attribute supports regex
/ / A n y d i v w i t h t h e t e x t s t a r t i n g w i h G R 8
$ ( " d i v " , t e x t : ~ / G R 8 . + / )
$ ( " p " , t e x t : s t a r t s W i t h ( " G R 8 " ) )
/ / A n d o t h e r h a n d y p r e d i c a t e s
$ ( " d i v " , c l a s s : c o n t a i n s ( " u i - " ) )
5 . 4
GEB SELECTORS (3)
Selecting returns Navigatorobjects
/ / T h e p a r e n t o f t h e f i r s t d i v
$ ( " d i v " , 0 ) . p a r e n t ( )
/ / A l l t a b l e s w i t h a c e l l s p a c i n g
/ / a t t r i b u t e v a l u e o f 0 t h a t a r e n e s t e d i n a p a r a g r a p h
$ ( " p " ) . f i n d ( " t a b l e " , c e l l s p a c i n g : ' 0 ' )
5 . 55 . 6
CSS SUPPORT
$ ( " t a b l e t r : n t h - c h i l d ( 2 n + 1 ) t d " )
RETRIVING INFORMATION
< p i d = " s a m p l e " c l a s s = " c l a s s - a c l a s s - b " t i t l e = " S a m p l e p e l e m e n t " >
S a m p l e t e x t
< / p >
$ ( " p " ) . t e x t ( ) = = " S a m p l e t e x t "
$ ( " # s a m p l e " ) . t a g ( ) = = " p "
$ ( " p " ) . @ t i t l e = = " S a m p l e p e l e m e n t "
$ ( " p " ) . c l a s s e s ( ) = = [ " c l a s s - a " , " c l a s s - b " ]
5 . 7
INTERACTION WITH CONTENT
click()
isDisplayed()
withConfirm{}
withAlert{}
$ ( " a . b t n " ) . c l i c k ( )
$ ( " d i v " ) . i s D i s p l a y e d ( )
w i t h C o n f i r m {
$ ( " b u t t o n . d e l e t e " ) . c l i c k ( )
}
5 . 85 . 9
SENDING INPUT
i m p o r t o r g . o p e n q a . s e l e n i u m . K e y s
/ / S h o r t h a n d f o r s e n d K e y s ( ) m e t h o d o f W e b D r i v e r .
$ ( " d i v " ) < < " a b c "
$ ( " i n p u t " , n a m e : " f o o " ) < < K e y s . c h o r d ( K e y s . C O N T R O L , " c " )
5 . 10
INTERACTION
Using ActionsAPI from WebDriver is possible.
But Geb provides the interactclosure
5 . 11
CONTROL-CLICKING
i m p o r t o r g . o p e n q a . s e l e n i u m . K e y s
i n t e r a c t {
k e y D o w n K e y s . C T R L
c l i c k $ ( " a . m y L i n k " )
k e y U p K e y s . C T R L
}
SIMULATE DRAG-N-DROP
i n t e r a c t {
c l i c k A n d H o l d ( $ ( ' # d r a g g a b l e ' ) )
m o v e B y O f f s e t ( 1 5 0 , 2 0 0 )
r e l e a s e ( )
}
Or easier
i n t e r a c t {
d r a g A n d D r o p B y ( $ ( " # d r a g g a b l e " ) , 1 5 0 , 2 0 0 )
}
5 . 12
MORE INTERACTION WITH FORMS
< f o r m >
< i n p u t t y p e = " t e x t " n a m e = " g e b " v a l u e = " F u n c t i o n a l " / >
< / f o r m >
The value can be read and written via property notation…
$ ( " f o r m " ) . g e b = = " F u n c t i o n a l "
$ ( " f o r m " ) . g e b = " T e s t i n g "
These are literally shortcuts for…
$ ( " f o r m " ) . f i n d ( " i n p u t " , n a m e : " g e b " ) . v a l u e ( ) = = " F u n c t i o n a l "
$ ( " f o r m " ) . f i n d ( " i n p u t " , n a m e : " g e b " ) . v a l u e ( " T e s t i n g " )
5 . 13
VARIABLES AVAILABLE
title
browser
currentUrl
currentWindow
5 . 14
MORE POSSIBILITIES
Uploading files
Downloading files
Interacting with javascript
js object (Example later)
5 . 156 . 1
STANDALONE GEB SCRIPT
GEB STANDALONE EXAMPLE
Lets try to automate:
Searching for Greach Conference
Click the first link
Hopefully end up on the right homepage
6 . 2
GEB STANDALONE EXAMPLE
g o " h t t p : / / d u c k d u c k g o . c o m "
$ ( ' i n p u t ' , n a m e : ' q ' ) . v a l u e ( " G r e a c h C o n f e r e n c e " )
$ ( ' i n p u t ' , n a m e : ' q ' ) < < K e y s . E N T E R
w a i t F o r ( 1 0 , 1 ) { $ ( " # l i n k s " ) . d i s p l a y e d }
s l e e p ( 3 0 0 0 ) / / F o r d e m o r e a s o n s
$ ( " h 2 . r e s u l t _ _ t i t l e " ) . f i r s t ( ) . c l i c k ( )
w a i t F o r { t i t l e . s t a r t s W i t h " G r e a c h " }
6 . 37 . 1
STRUCTURING GEB TESTS
SCENARIO
Lets test a small todo application
Lets test the following
1. Goto list of todos
2. Create new item
3. Delete item again
7 . 27 . 3
GEB SPEC BASICS
i m p o r t g e b . s p o c k . G e b S p e c
@ S t e p w i s e / / E n s u r e s t h e t e s t s a r e r u n s e q u e n t i a l l y
c l a s s T o d o S p e c e x t e n d s G e b S p e c {
/ / S p o c k s p e c s h e r e
}
GEB SPEC (1)
The naive inmaintainable way!
d e f " G o t o i n d e x p a g e " ( ) {
w h e n : ' G o t o i n d e x u r l '
g o ' / '
t h e n : ' V e r i f y w e a r e t h e r e '
t i t l e = = " T o d o L i s t "
}
7 . 4
GEB SPEC (2)
The naive inmaintainable way!
d e f " C r e a t e n e w t o d o " ( ) {
w h e n : ' I n p u t t e x t a n d s u b m i t '
$ ( " # n e w - t o d o " ) < < " D o t h i s "
$ ( " # c r e a t e - b t n " ) . c l i c k ( )
t h e n : ' V e r i f y n e w i t e m p r e s e n t i n l i s t '
w a i t F o r { $ ( " # c o u n t " ) . t e x t ( ) = = ' 4 ' }
$ ( ' l i . t o d o - i t e m ' ) . a n y { i t . t e x t ( ) . c o n t a i n s ' D o t h i s ' }
a n d : ' V e r i f y i n p u t f i e l d e m p t y '
! $ ( " # n e w - t o d o " ) . t e x t ( )
}
7 . 5
GEB SPEC (3)
The naive inmaintainable way!
d e f " D e l e t e t o d o i t e m " ( ) {
w h e n : ' C l i c k d e l e t e a n d a c c e p t '
w i t h C o n f i r m {
$ ( ' b u t t o n ' , 4 ) . c l i c k ( )
}
t h e n : ' V e r i f y i t e m d e l e t e d '
w a i t F o r { $ ( " # c o u n t " ) . t e x t ( ) = = ' 3 ' }
$ ( ' l i . t o d o - i t e m ' ) . e v e r y { ! ( i t . t e x t ( ) . c o n t a i n s ( ' D o t h i s ' ) ) }
}
7 . 68 . 1
GEB SPEC - THE BETTER WAY
If we make a few scenarios, there will be
Much duplication
Many places to correct if we change the layout / DOM
8 . 28 . 3
SOLUTION
Use pages and modules
PAGE OBJECTS
Describes a web page
Url
How to check if we are at the correct place
Content we wish to interact with
.. and how it is found
Helper methods
8 . 4
PAGE OBJECTS
p a c k a g e n e t . g r y d e s k e . g r e a c h . p a g e s
i m p o r t g e b . P a g e
c l a s s A b o u t P a g e e x t e n d s P a g e {
s t a t i c u r l = " / a b o u t "
s t a t i c a t = {
t i t l e = = " A b o u t "
}
s t a t i c c o n t e n t = {
h e a d e r { $ ( ' h 1 ' , 0 ) }
}
}
8 . 58 . 6
CONTENT CLOSURE
s t a t i c c o n t e n t = {
i n f o ( r e q u i r e d : f a l s e ) { $ ( " d i v . i n f o " ) }
m e s s a g e ( w a i t : f a l s e ) { $ ( " d i v . m e s s a g e " ) }
}
8 . 7
MODULES
Describes repeated content
Across pages
Repeated content within the same page
MODULES ACROSS PAGES
p a c k a g e n e t . g r y d e s k e . g r e a c h . m o d u l e s
i m p o r t g e b . M o d u l e
c l a s s M e n u b a r M o d u l e e x t e n d s M o d u l e {
s t a t i c b a s e = { $ ( " n a v . n a v b a r " ) }
s t a t i c c o n t e n t = {
h o m e { $ ( ' a ' , t e x t : ' T o d o L i s t ' ) }
a b o u t { $ ( ' a ' , t e x t : ' A b o u t ' ) }
}
}
8 . 8
MODULES FOR REPEATED CONTENT
p a c k a g e n e t . g r y d e s k e . g r e a c h . m o d u l e s
i m p o r t g e b . M o d u l e
c l a s s T o d o I t e m M o d u l e e x t e n d s M o d u l e {
s t a t i c c o n t e n t = {
c h e c k b o x { $ ( ' i n p u t ' , t y p e : ' c h e c k b o x ' ) }
l a b e l { $ ( ' l a b e l ' ) . t e x t ( ) }
d e l e t e B t n { $ ( ' b u t t o n ' ) }
}
}
8 . 98 . 10
USING MODULES
s t a t i c c o n t e n t = {
m e n u b a r { m o d u l e M e n u b a r M o d u l e }
t o d o s ( r e q u i r e d : f a l s e ) {
$ ( ' l i . t o d o - i t e m ' ) . m o d u l e L i s t ( T o d o I t e m M o d u l e )
}
}
8 . 11
GEB SPEC - STRUCTURED
Lets try to restructure the ugly spec from before
8 . 12
GEB SPEC - STRUCTURED (1)
d e f " G o t o i n d e x p a g e " ( ) {
w h e n : ' G o t o i n d e x u r l '
t o I n d e x P a g e
t h e n : ' V e r i f y 3 i t e m s p r e s e n t '
a t I n d e x P a g e
c o u n t V a l u e = = ' 3 '
}
GEB SPEC - STRUCTURED (2)
d e f " C r e a t e n e w t o d o " ( ) {
w h e n : ' I n p u t t e x t a n d s u b m i t '
t o d o I n p u t = " D o t h i s "
t o d o S u b m i t . c l i c k ( )
t h e n : ' V e r i f y n e w i t e m p r e s e n t i n l i s t '
w a i t F o r { c o u n t V a l u e = = ' 4 ' }
t o d o s . a n y { i t . l a b e l = = ' D o t h i s ' }
a n d : ' V e r i f y i n p u t f i e l d e m p t y '
! t o d o I n p u t . t e x t ( )
}
8 . 13
GEB SPEC - STRUCTURED (3)
d e f " D e l e t e t o d o i t e m " ( ) {
w h e n : ' C l i c k d e l e t e a n d a c c e p t '
w i t h C o n f i r m {
t o d o s . f i n d { i t . l a b e l = = ' D o t h i s ' } . d e l e t e B t n . c l i c k ( )
}
t h e n : ' V e r i f y i t e m d e l e t e d '
w a i t F o r { c o u n t V a l u e = = ' 3 ' }
t o d o s . e v e r y { i t . l a b e l ! = ' D o t h i s ' }
}
8 . 14
STANDALONE REVISITED
c l a s s D u c k D u c k G o P a g e e x t e n d s g e b . P a g e {
s t a t i c u r l = " h t t p : / / d u c k d u c k g o . c o m "
s t a t i c a t = { t i t l e = = ~ / D u c k D u c k G o / }
s t a t i c c o n t e n t = {
i n p u t F i e l d { $ ( ' i n p u t ' , n a m e : ' q ' ) }
}
d e f s u b m i t ( ) {
i n p u t F i e l d < < K e y s . E N T E R
}
}
8 . 15
STANDALONE REVISITED
c l a s s D u c k D u c k G o R e s u l t P a g e e x t e n d s g e b . P a g e {
s t a t i c u r l = " h t t p : / / d u c k d u c k g o . c o m "
s t a t i c a t = { $ ( " # l i n k s " ) . d i s p l a y e d }
s t a t i c c o n t e n t = {
l i n k s { $ ( " h 2 . r e s u l t _ _ t i t l e " ) }
}
d e f c l i c k L i n k ( i n t l i n k N u m b e r ) {
l i n k s [ l i n k N u m b e r ] . c l i c k ( )
}
}
8 . 168 . 17
STANDALONE REVISITED
c l a s s G r e a c h P a g e e x t e n d s g e b . P a g e {
s t a t i c a t = { t i t l e . s t a r t s W i t h ( " G r e a c h " ) }
}
STANDALONE REVISITED
b r o w s e r . w i t h {
t o D u c k D u c k G o P a g e
i n p u t F i e l d < < " G r e a c h C o n f e r e n c e "
s u b m i t ( )
w a i t F o r ( 1 0 , 0 . 5 ) {
a t D u c k D u c k G o R e s u l t P a g e
}
s l e e p ( 3 0 0 0 ) / / F o r d e m o r e a s o n s
c l i c k L i n k ( 0 )
w a i t F o r {
a t G r e a c h P a g e
}
}
8 . 189 . 1
GEB WITH RATPACK AND GRAILS
GEB WITH RATPACK
d e p e n d e n c i e s {
. . .
/ / I f u s i n g S p o c k , n e e d t o d e p e n d o n g e b - s p o c k
t e s t C o m p i l e " o r g . g e b i s h : g e b - s p o c k : 0 . 1 3 . 1 "
t e s t C o m p i l e " o r g . s p o c k f r a m e w o r k : s p o c k - c o r e : 1 . 0 - g r o o v y - 2 . 4 "
/ / N e e d a d r i v e r i m p l e m e n t a t i o n
t e s t C o m p i l e (
" o r g . s e l e n i u m h q . s e l e n i u m : s e l e n i u m - f i r e f o x - d r i v e r : 2 . 5 3 . 0 "
)
t e s t R u n t i m e (
" o r g . s e l e n i u m h q . s e l e n i u m : s e l e n i u m - s u p p o r t : 2 . 5 3 . 0 "
)
}
9 . 29 . 3
GEB WITH RATPACK
@ S h a r e d
d e f a u t = n e w G r o o v y R a t p a c k M a i n A p p l i c a t i o n U n d e r T e s t ( )
d e f s e t u p ( ) {
U R I b a s e = a u t . a d d r e s s
b r o w s e r . b a s e U r l = b a s e . t o S t r i n g ( )
}
9 . 4
INTERACTING WITH RATPACK
APPLICATION
When some functionality is needed that is not exposed
through the browser, it can be necessary to interact with the
application under test.
9 . 5
INTERACTING WITH RATPACK
Include in build.gradle
d e p e n d e n c i e s {
. . .
c o m p i l e r a t p a c k . d e p e n d e n c y ( " r e m o t e " )
t e s t C o m p i l e r a t p a c k . d e p e n d e n c y ( " r e m o t e - t e s t " )
. . .
INTERACTING WITH RATPACK
@ S h a r e d
d e f a u t = n e w G r o o v y R a t p a c k M a i n A p p l i c a t i o n U n d e r T e s t ( )
R e m o t e C o n t r o l r e m o t e C o n t r o l
d e f s e t u p ( ) {
U R I b a s e = a u t . a d d r e s s
b r o w s e r . b a s e U r l = b a s e . t o S t r i n g ( )
r e m o t e C o n t r o l = n e w R e m o t e C o n t r o l ( a u t )
}
9 . 6
INTERACTING WITH RATPACK
d e f " C o m p l e t e i t e m a n d c h e c k d a t a b a s e " ( ) {
w h e n : ' C h e c k i t e m d o n e '
t o d o s . f i n d { i t . l a b e l = = ' G i v e G e b p r e s e n t a t i o n ' }
. c h e c k b o x . c l i c k ( )
t h e n : ' U s e r e m o t e c o n t r o l t o c h e c k d a t a b a s e '
r e m o t e C o n t r o l . e x e c {
B o o l e a n c o m p l e t e d
T o d o I t e m . w i t h N e w S e s s i o n {
T o d o I t e m t o d o I t e m = T o d o I t e m
. f i n d B y T e x t ( ' G i v e G e b p r e s e n t a t i o n ' )
c o m p l e t e d = t o d o I t e m . c o m p l e t e d
}
c o m p l e t e d
} = = t r u e
}
9 . 7
GEB AND GRAILS 2.X
Must install plugin in BuildConfig.groovy
d e p e n d e n c i e s {
. . .
t e s t ( " o r g . s e l e n i u m h q . s e l e n i u m : s e l e n i u m - s u p p o r t : 2 . 5 3 . 0 " )
t e s t ( " o r g . s e l e n i u m h q . s e l e n i u m : s e l e n i u m - f i r e f o x - d r i v e r : 2 . 5 3 . 0 " )
t e s t " o r g . g e b i s h : g e b - s p o c k : 0 . 1 2 . 1 "
}
p l u g i n s {
. . .
t e s t " o r g . g r a i l s . p l u g i n s : g e b : 0 . 1 2 . 1 "
}
9 . 89 . 9
GEB TESTS IN GRAILS 2.X
Tests placed in test/functionalfolder
Running the tests
g r a i l s t e s t - a p p f u n c t i o n a l :
GEB AND GRAILS 3
Geb is default in build.gradle
d e p e n d e n c i e s {
. . .
t e s t C o m p i l e " o r g . g r a i l s . p l u g i n s : g e b "
t e s t R u n t i m e (
" o r g . s e l e n i u m h q . s e l e n i u m : s e l e n i u m - h t m l u n i t - d r i v e r : 2 . 4 7 . 1 "
)
t e s t R u n t i m e " n e t . s o u r c e f o r g e . h t m l u n i t : h t m l u n i t : 2 . 1 8 "
}
9 . 10
GEB TESTS IN GRAILS 3
Creating Geb Spec
g r a i l s c r e a t e - f u n c t i o n a l - t e s t M y G e b S c e n a r i o
Placing the test in src/integration-test/groovy
Running the tests
g r a i l s t e s t - a p p - i n t e g r a t i o n
9 . 11
GENERATED CLASS
@ I n t e g r a t i o n
@ R o l l b a c k
c l a s s D e m o S p e c e x t e n d s G e b S p e c {
v o i d " t e s t s o m e t h i n g " ( ) {
w h e n : " T h e h o m e p a g e i s v i s i t e d "
g o ' / '
t h e n : " T h e t i t l e i s c o r r e c t "
$ ( ' t i t l e ' ) . t e x t ( ) = = " W e l c o m e t o G r a i l s "
}
}
9 . 12
INTERACTING WITH GRAILS 2.5
Tests not running in same JVM
Done with remote-control plugin
Send a closure for execution in application
c o m p i l e " : r e m o t e - c o n t r o l : 2 . 0 "
9 . 139 . 14
INTERACTING WITH GRAILS 3.0
Application is in same jvm
Interaction is possible directly
Tests run as integration tests
9 . 15
INTERACTING WITH GRAILS 3.0
s e t u p :
A t t e n d e e . w i t h N e w T r a n s a c t i o n {
1 5 . t i m e s {
n e w A t t e n d e e ( n a m e : " N $ i t " , e m a i l : " m $ i t @ t . d k " ) . s a v e ( )
}
}
10 . 1
CONFIGURATION AND BROWSER
SUPPORT
10 . 2
GEBCONFIG
Configuration for Geb is placed in GebConfig.groovy
It must be placed in default package scope
 http://www.gebish.org/manual/current/configuration.html
10 . 3
DRIVER
It is possible to configure the browser used.
SUPPORTED DRIVERS
Firefox
Chrome
InternetExplorer
Safari
HtmlUnit
PhantomJS
10 . 410 . 5
DRIVER
It is possible to configure the browser used.
build.gradle
c o m p i l e ' o r g . s e l e n i u m h q . s e l e n i u m : s e l e n i u m - c h r o m e - d r i v e r : 2 . 4 9 . 0 '
c o m p i l e ' o r g . s e l e n i u m h q . s e l e n i u m : s e l e n i u m - f i r e f o x - d r i v e r : 2 . 4 9 . 0 '
FIREFOX
GebConfig.groovy
i m p o r t o r g . o p e n q a . s e l e n i u m . f i r e f o x . F i r e f o x P r o f i l e
i m p o r t o r g . o p e n q a . s e l e n i u m . f i r e f o x . F i r e f o x D r i v e r
d r i v e r = {
F i r e f o x P r o f i l e p r o f i l e = n e w F i r e f o x P r o f i l e ( )
p r o f i l e . s e t P r e f e r e n c e ( " b r o w s e r . d o w n l o a d . f o l d e r L i s t " , 2 )
p r o f i l e . s e t P r e f e r e n c e ( " b r o w s e r . d o w n l o a d . d i r " , " / t m p " )
p r o f i l e . s e t P r e f e r e n c e (
" b r o w s e r . h e l p e r A p p s . n e v e r A s k . s a v e T o D i s k " , " t e x t / c s v " )
d e f d r i v e r I n s t a n c e = n e w F i r e f o x D r i v e r ( p r o f i l e )
d r i v e r I n s t a n c e . m a n a g e ( ) . w i n d o w ( ) . m a x i m i z e ( )
d r i v e r I n s t a n c e
}
10 . 610 . 7
CHROME
Needs ChromeDriver downloaded
Pretty fast and stable
CHROME (1)
GebConfig.groovy
p r i v a t e S t r i n g d r i v e r L o c a t i o n D e p e n d i n g O n O p e r a t i n g S y s t e m ( ) {
S t r i n g o s = S y s t e m . g e t P r o p e r t y ( " o s . n a m e " ) . t o L o w e r C a s e ( ) ;
d e f l o c = " h t t p : / / c h r o m e d r i v e r . s t o r a g e . g o o g l e a p i s . c o m / 2 . 2 0 "
i f ( o s . c o n t a i n s ( ' m a c ' ) ) {
r e t u r n " $ { l o c } / c h r o m e d r i v e r _ m a c 3 2 . z i p "
}
i f ( o s . c o n t a i n s ( ' w i n ' ) ) {
r e t u r n " $ { l o c } / c h r o m e d r i v e r _ w i n 3 2 . z i p "
}
r e t u r n " $ { l o c } / c h r o m e d r i v e r _ l i n u x 6 4 . z i p "
}
10 . 8
CHROME (2)
GebConfig.groovy
p r i v a t e v o i d d o w n l o a d D r i v e r ( F i l e f i l e , S t r i n g p a t h ) {
i f ( ! f i l e . e x i s t s ( ) ) {
d e f a n t = n e w A n t B u i l d e r ( )
a n t . g e t ( s r c : p a t h , d e s t : ' d r i v e r . z i p ' )
a n t . u n z i p ( s r c : ' d r i v e r . z i p ' , d e s t : f i l e . p a r e n t )
a n t . d e l e t e ( f i l e : ' d r i v e r . z i p ' )
a n t . c h m o d ( f i l e : f i l e , p e r m : ' 7 0 0 ' )
}
}
10 . 9
CHROME (3)
GebConfig.groovy
d e f c h r o m e D r i v e r = n e w F i l e ( ' b u i l d / d r i v e r s / c h r o m e / c h r o m e d r i v e r ' )
d o w n l o a d D r i v e r ( c h r o m e D r i v e r ,
d r i v e r L o c a t i o n D e p e n d i n g O n O p e r a t i n g S y s t e m ( ) )
S y s t e m . s e t P r o p e r t y ( ' w e b d r i v e r . c h r o m e . d r i v e r ' ,
c h r o m e D r i v e r . a b s o l u t e P a t h )
d r i v e r = {
d e f d r i v e r I n s t a n c e = n e w C h r o m e D r i v e r ( )
d e f b r o w s e r W i n d o w = d r i v e r I n s t a n c e . m a n a g e ( ) . w i n d o w ( )
/ / w i d t h , h e i g h t
b r o w s e r W i n d o w . s i z e = n e w D i m e n s i o n ( 1 0 0 0 , 2 5 0 0 )
b r o w s e r W i n d o w . p o s i t i o n = n e w P o i n t ( 0 , 0 )
d r i v e r I n s t a n c e
}
10 . 1010 . 11
CLOUD BASED TESTING
SauceLabs
BrowserStack
SAUCELABS
GebConfig.groovy
i m p o r t g e b . d r i v e r . S a u c e L a b s D r i v e r F a c t o r y
d e f s l B r o w s e r = S y s t e m . g e t P r o p e r t y ( " g e b . s a u c e l a b s . b r o w s e r " )
i f ( s l B r o w s e r ) {
d r i v e r = {
d e f u s e r n a m e = S y s t e m . g e t e n v (
" G E B _ S A U C E _ L A B S _ U S E R " )
a s s e r t u s e r n a m e
d e f a c c e s s K e y = S y s t e m . g e t e n v (
" G E B _ S A U C E _ L A B S _ A C C E S S _ P A S S W O R D " )
a s s e r t a c c e s s K e y
n e w S a u c e L a b s D r i v e r F a c t o r y ( ) . c r e a t e (
s a u c e L a b s B r o w s e r , u s e r n a m e , a c c e s s K e y )
}
}
10 . 12
SAUCELABS
build.gradle
a p p l y p l u g i n : " g e b - s a u c e l a b s "
r e p o s i t o r i e s {
. . .
m a v e n C e n t r a l ( )
}
d e p e n d e n c i e s {
. . .
s a u c e C o n n e c t " c o m . s a u c e l a b s : c i - s a u c e : 1 . 1 1 3 "
}
10 . 13
SAUCELABS
s a u c e L a b s {
b r o w s e r s {
f i r e f o x _ l i n u x _ 1 9
d e l e g a t e . " i n t e r n e t e x p l o r e r _ v i s t a _ 9 "
n e x u s 4 {
c a p a b i l i t i e s (
b r o w s e r N a m e : " a n d r o i d " , p l a t f o r m : " L i n u x " ,
v e r s i o n : " 4 . 4 " , d e v i c e N a m e : " L G N e x u s 4 "
)
} }
t a s k {
t e s t C l a s s e s D i r = t e s t . t e s t C l a s s e s D i r
t e s t S r c D i r s = t e s t . t e s t S r c D i r s
c l a s s p a t h = t e s t . c l a s s p a t h
}
a c c o u n t {
u s e r n a m e = " u s e r n a m e "
a c c e s s K e y = " a p i - k e y "
}
c o n n e c t {
/ / p o r t = 4 4 4 4
/ / a d d i t i o n a l O p t i o n s = [ ' - - p r o x y ' , ' p r o x y . e x a m p l e . c o m : 8 0 8 0 ' ]
} }
10 . 1411 . 1
JAVASCRIPT
In case you need to interact using javascript
11 . 2
EXECUTING JAVASCRIPT
Clicking a button that is hidden will create a
ElementNotVisibleException
< f i e l d s e t c l a s s = " w e l l " s t y l e = " d i s p l a y : n o n e " >
< a h r e f = " / l i s t " c l a s s = " b t n " > L i s t < / a >
< / f i e l d s e t >
11 . 3
EXECUTING JAVASCRIPT
J a v a s c r i p t E x e c u t o r e x e c u t o r = ( J a v a s c r i p t E x e c u t o r ) d r i v e r
e x e c u t o r . e x e c u t e S c r i p t ( ' j Q u e r y ( " . w e l l " ) . s h o w ( ) ; ' )
11 . 4
WRAPPING JAVASCRIPT
d e f j s ( S t r i n g s c r i p t ) {
( d r i v e r a s J a v a s c r i p t E x e c u t o r ) . e x e c u t e S c r i p t ( s c r i p t )
}
j s ( ' j Q u e r y ( " . w e l l " ) . s h o w ( ) ; ' )
11 . 5
JQUERY SHORTHAND
$ ( " d i v # a " ) . j q u e r y . m o u s e o v e r ( )
$ ( " # a " ) . j q u e r y . t r i g g e r ( ' m o u s e o v e r ' )
12 . 1
WAITING AND PAUSING
WAITING
GebConfig.groovy
w a i t i n g {
t i m e o u t = 1 0
r e t r y I n t e r v a l = 0 . 5
}
b a s e N a v i g a t o r W a i t i n g = t r u e
a t C h e c k W a i t i n g = t r u e
12 . 2
USING WAITING
< d i v c l a s s = " f a d e - m e - i n " s t y l e = " d i s p l a y : n o n e " >
H i - a r e y o w a i t i n g f o r m e ?
< / d i v >
< s c r i p t >
$ ( ' d i v . f a d e - m e - i n ' ) . d e l a y ( 3 0 0 0 ) . s l i d e D o w n ( ) ;
< / s c r i p t >
s t a t i c c o n t e n t = {
f a d e I n M e s s a g e { $ ( ' d i v . f a d e - m e - i n ' ) }
}
t h e n :
w a i t F o r {
f a d e I n M e s s a g e . t e x t ( ) = = ' H i - a r e y o w a i t i n g f o r m e ? '
}
12 . 3
PAUSING GEB
p r i v a t e v o i d p a u s e ( ) {
j s . e x e c " " " ( f u n c t i o n ( ) {
w i n d o w . _ _ g e b P a u s e d = t r u e ;
v a r d i v = d o c u m e n t . c r e a t e E l e m e n t ( " d i v " ) ;
d i v . s e t A t t r i b u t e ( ' s t y l e ' ,
" p o s i t i o n : a b s o l u t e ; t o p : 0 p x ; r i g h t : 0 p x ; z - i n d e x : 3 0 0 0 ;  
p a d d i n g : 1 0 p x ; b a c k g r o u n d - c o l o r : r e d ; " ) ;
v a r b u t t o n = d o c u m e n t . c r e a t e E l e m e n t ( " b u t t o n " ) ;
b u t t o n . i n n e r H T M L = " U n p a u s e G e b " ;
b u t t o n . o n c l i c k = f u n c t i o n ( ) {
w i n d o w . _ _ g e b P a u s e d = f a l s e ;
}
d i v . a p p e n d C h i l d ( b u t t o n ) ;
d o c u m e n t . g e t E l e m e n t s B y T a g N a m e ( " b o d y " ) [ 0 ] . a p p e n d C h i l d ( d i v ) ;
} ) ( ) ; " " "
w a i t F o r ( 3 0 0 ) { ! j s . _ _ g e b P a u s e d }
}
12 . 412 . 5
PAUSING GEB
w h e n : ' D e m o i n g p a u s e '
p a u s e ( ) / / P a u s e G e b u n t i l b u t t o n p r e s s e d
PAUSING GEB
12 . 613 . 1
REPORTING
13 . 2
TEST REPORTS
Nicely formatted
Spock power-assert format
13 . 3
SPOCK REPORTS
Take a look at pluginSpock Reports
t e s t C o m p i l e ( ' c o m . a t h a y d e s : s p o c k - r e p o r t s : 1 . 2 . 1 0 ' ) {
/ / t h i s a v o i d s a f f e c t i n g y o u r v e r s i o n o f G r o o v y / S p o c k
t r a n s i t i v e = f a l s e
}
SPOCK REPORTS
SPOCK REPORTS
13 . 4
SCREENSHOTS
Screenshots and HTML from end of each test:
Extend from GebReportingSpec
c l a s s A t t e n d e e F u n c t i o n a l S p e c e x t e n d s G e b R e p o r t i n g S p e c
GebConfig.groovy
r e p o r t s D i r = n e w F i l e ( " b u i l d / g e b - r e p o r t s " )
r e p o r t O n T e s t F a i l u r e O n l y = t r u e
13 . 513 . 613 . 7
AD-HOC SCREENSHOTS
r e p o r t " W h e n - f o r m - i s - j u s t - f i l l e d "
Saves a report in reportsDir
Numbered in increasing order
14
OTHER USAGES
Screenscraping of a site
Solving complex problems like 2048
RESOURCES
http://gebish.org
https://groups.google.com/forum/#!forum/geb-user
https://github.com/geb
https://gist.github.com/melix/9619800
https://github.com/tomaslin/grails-test-recipes
https://fbflex.wordpress.com/2010/08/25/geb-and-grails-
tips-tricks-and-gotchas/
https://github.com/JacobAae/gr8conf-in-2016-geb-for-
grails
1516
QUESTIONS?
some text...

Weitere ähnliche Inhalte

Was ist angesagt?

Effective codereview | Dave Liddament | CODEiD
Effective codereview | Dave Liddament | CODEiDEffective codereview | Dave Liddament | CODEiD
Effective codereview | Dave Liddament | CODEiD
CODEiD PHP Community
 

Was ist angesagt? (20)

GitGot: The Swiss Army Chainsaw of Git Repo Management
GitGot: The Swiss Army Chainsaw of Git Repo ManagementGitGot: The Swiss Army Chainsaw of Git Repo Management
GitGot: The Swiss Army Chainsaw of Git Repo Management
 
Reading Other Peoples Code (NDC Copenhagen 2019)
Reading Other Peoples Code (NDC Copenhagen 2019)Reading Other Peoples Code (NDC Copenhagen 2019)
Reading Other Peoples Code (NDC Copenhagen 2019)
 
LetSwift 2017 - 토스 iOS 앱의 개발/배포 환경
LetSwift 2017 - 토스 iOS 앱의 개발/배포 환경LetSwift 2017 - 토스 iOS 앱의 개발/배포 환경
LetSwift 2017 - 토스 iOS 앱의 개발/배포 환경
 
Challenging Your Assumptions
Challenging Your AssumptionsChallenging Your Assumptions
Challenging Your Assumptions
 
C++ The Principles of Most Surprise
C++ The Principles of Most SurpriseC++ The Principles of Most Surprise
C++ The Principles of Most Surprise
 
第7回 ECMA-262 Edition5.1読書会
第7回 ECMA-262 Edition5.1読書会第7回 ECMA-262 Edition5.1読書会
第7回 ECMA-262 Edition5.1読書会
 
Testing Grails 3, the goob (unit), the bad (integration) and the ugly (functi...
Testing Grails 3, the goob (unit), the bad (integration) and the ugly (functi...Testing Grails 3, the goob (unit), the bad (integration) and the ugly (functi...
Testing Grails 3, the goob (unit), the bad (integration) and the ugly (functi...
 
Software Vulnerabilities in C and C++ (CppCon 2018)
Software Vulnerabilities in C and C++ (CppCon 2018)Software Vulnerabilities in C and C++ (CppCon 2018)
Software Vulnerabilities in C and C++ (CppCon 2018)
 
Trying to learn C# (NDC Oslo 2019)
Trying to learn C# (NDC Oslo 2019)Trying to learn C# (NDC Oslo 2019)
Trying to learn C# (NDC Oslo 2019)
 
톰캣 #05+a-배치-parallel deployment
톰캣 #05+a-배치-parallel deployment톰캣 #05+a-배치-parallel deployment
톰캣 #05+a-배치-parallel deployment
 
Reading Other Peoples Code (NDC Sydney 2018)
Reading Other Peoples Code (NDC Sydney 2018)Reading Other Peoples Code (NDC Sydney 2018)
Reading Other Peoples Code (NDC Sydney 2018)
 
Monitoring using Sensu
Monitoring using SensuMonitoring using Sensu
Monitoring using Sensu
 
Effective codereview | Dave Liddament | CODEiD
Effective codereview | Dave Liddament | CODEiDEffective codereview | Dave Liddament | CODEiD
Effective codereview | Dave Liddament | CODEiD
 
Geb for Testing Your Grails Application GR8Conf India 2016
Geb for Testing Your Grails Application  GR8Conf India 2016Geb for Testing Your Grails Application  GR8Conf India 2016
Geb for Testing Your Grails Application GR8Conf India 2016
 
Tools Bringing Happiness
Tools Bringing HappinessTools Bringing Happiness
Tools Bringing Happiness
 
Testing Java Microservices Devoxx be 2017
Testing Java Microservices Devoxx be 2017Testing Java Microservices Devoxx be 2017
Testing Java Microservices Devoxx be 2017
 
The Anatomy of an Exploit (CPPP 2019)
The Anatomy of an Exploit (CPPP 2019)The Anatomy of an Exploit (CPPP 2019)
The Anatomy of an Exploit (CPPP 2019)
 
Thoughts On Learning A New Programming Language
Thoughts On Learning A New Programming LanguageThoughts On Learning A New Programming Language
Thoughts On Learning A New Programming Language
 
The Anatomy of an Exploit (NDC TechTown 2019)
The Anatomy of an Exploit (NDC TechTown 2019)The Anatomy of an Exploit (NDC TechTown 2019)
The Anatomy of an Exploit (NDC TechTown 2019)
 
Yes, you can git!
Yes, you can git!Yes, you can git!
Yes, you can git!
 

Andere mochten auch

Andere mochten auch (9)

From Grails to Android: A Simple Journey
From Grails to Android: A Simple JourneyFrom Grails to Android: A Simple Journey
From Grails to Android: A Simple Journey
 
Geb for testing your grails application
Geb for testing your grails applicationGeb for testing your grails application
Geb for testing your grails application
 
Spock and Geb in Action
Spock and Geb in ActionSpock and Geb in Action
Spock and Geb in Action
 
Creating ASTTs The painful truth
Creating ASTTs The painful truthCreating ASTTs The painful truth
Creating ASTTs The painful truth
 
Greach 2016 dockerize your grails
Greach 2016   dockerize your grailsGreach 2016   dockerize your grails
Greach 2016 dockerize your grails
 
Mastering Grails 3 Plugins - Greach 2016
Mastering Grails 3 Plugins - Greach 2016Mastering Grails 3 Plugins - Greach 2016
Mastering Grails 3 Plugins - Greach 2016
 
Reactive Streams and the Wide World of Groovy
Reactive Streams and the Wide World of GroovyReactive Streams and the Wide World of Groovy
Reactive Streams and the Wide World of Groovy
 
Grooscript and Grails 3
Grooscript and Grails 3Grooscript and Grails 3
Grooscript and Grails 3
 
Geb with spock
Geb with spockGeb with spock
Geb with spock
 

Ähnlich wie Geb for browser automation

Spring scala - Sneaking Scala into your corporation
Spring scala  - Sneaking Scala into your corporationSpring scala  - Sneaking Scala into your corporation
Spring scala - Sneaking Scala into your corporation
Henryk Konsek
 
Modeling avengers – open source technology mix for saving the world
Modeling avengers – open source technology mix for saving the worldModeling avengers – open source technology mix for saving the world
Modeling avengers – open source technology mix for saving the world
Cédric Brun
 
R57php 1231677414471772-2
R57php 1231677414471772-2R57php 1231677414471772-2
R57php 1231677414471772-2
ady36
 
Modeling avengers – open source technology mix for saving the world econ fr
Modeling avengers – open source technology mix for saving the world econ frModeling avengers – open source technology mix for saving the world econ fr
Modeling avengers – open source technology mix for saving the world econ fr
Cédric Brun
 
Continuous delivery with Gradle
Continuous delivery with GradleContinuous delivery with Gradle
Continuous delivery with Gradle
Bob Paulin
 
Tong Hop Bai Tap C
Tong Hop Bai Tap CTong Hop Bai Tap C
Tong Hop Bai Tap C
SamQuiDaiBo
 

Ähnlich wie Geb for browser automation (20)

PyLadies Talk: Learn to love the command line!
PyLadies Talk: Learn to love the command line!PyLadies Talk: Learn to love the command line!
PyLadies Talk: Learn to love the command line!
 
GraphQL Relay Introduction
GraphQL Relay IntroductionGraphQL Relay Introduction
GraphQL Relay Introduction
 
Social Network Analysis With R
Social Network Analysis With RSocial Network Analysis With R
Social Network Analysis With R
 
Spring scala - Sneaking Scala into your corporation
Spring scala  - Sneaking Scala into your corporationSpring scala  - Sneaking Scala into your corporation
Spring scala - Sneaking Scala into your corporation
 
Top 10 php classic traps
Top 10 php classic trapsTop 10 php classic traps
Top 10 php classic traps
 
PostgreSQL Day italy 2016 Unit Test
PostgreSQL Day italy 2016 Unit TestPostgreSQL Day italy 2016 Unit Test
PostgreSQL Day italy 2016 Unit Test
 
Awesome Traefik - Ingress Controller for Kubernetes - Swapnasagar Pradhan
Awesome Traefik - Ingress Controller for Kubernetes - Swapnasagar PradhanAwesome Traefik - Ingress Controller for Kubernetes - Swapnasagar Pradhan
Awesome Traefik - Ingress Controller for Kubernetes - Swapnasagar Pradhan
 
The Backside of the Class (CSS Day 2015)
The Backside of the Class (CSS Day 2015)The Backside of the Class (CSS Day 2015)
The Backside of the Class (CSS Day 2015)
 
Using Phing for Fun and Profit
Using Phing for Fun and ProfitUsing Phing for Fun and Profit
Using Phing for Fun and Profit
 
Automated tests - facts and myths
Automated tests - facts and mythsAutomated tests - facts and myths
Automated tests - facts and myths
 
Top 10 php classic traps DPC 2020
Top 10 php classic traps DPC 2020Top 10 php classic traps DPC 2020
Top 10 php classic traps DPC 2020
 
Top 10 php classic traps confoo
Top 10 php classic traps confooTop 10 php classic traps confoo
Top 10 php classic traps confoo
 
Modeling avengers – open source technology mix for saving the world
Modeling avengers – open source technology mix for saving the worldModeling avengers – open source technology mix for saving the world
Modeling avengers – open source technology mix for saving the world
 
R57php 1231677414471772-2
R57php 1231677414471772-2R57php 1231677414471772-2
R57php 1231677414471772-2
 
PHP Tips & Tricks
PHP Tips & TricksPHP Tips & Tricks
PHP Tips & Tricks
 
Modeling avengers – open source technology mix for saving the world econ fr
Modeling avengers – open source technology mix for saving the world econ frModeling avengers – open source technology mix for saving the world econ fr
Modeling avengers – open source technology mix for saving the world econ fr
 
JavaFX, because you're worth it
JavaFX, because you're worth itJavaFX, because you're worth it
JavaFX, because you're worth it
 
No Flex Zone: Empathy Driven Development
No Flex Zone: Empathy Driven DevelopmentNo Flex Zone: Empathy Driven Development
No Flex Zone: Empathy Driven Development
 
Continuous delivery with Gradle
Continuous delivery with GradleContinuous delivery with Gradle
Continuous delivery with Gradle
 
Tong Hop Bai Tap C
Tong Hop Bai Tap CTong Hop Bai Tap C
Tong Hop Bai Tap C
 

Kürzlich hochgeladen

call girls in Anand Vihar (delhi) call me [🔝9953056974🔝] escort service 24X7
call girls in Anand Vihar (delhi) call me [🔝9953056974🔝] escort service 24X7call girls in Anand Vihar (delhi) call me [🔝9953056974🔝] escort service 24X7
call girls in Anand Vihar (delhi) call me [🔝9953056974🔝] escort service 24X7
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
一比一原版(Curtin毕业证书)科廷大学毕业证原件一模一样
一比一原版(Curtin毕业证书)科廷大学毕业证原件一模一样一比一原版(Curtin毕业证书)科廷大学毕业证原件一模一样
一比一原版(Curtin毕业证书)科廷大学毕业证原件一模一样
ayvbos
 
在线制作约克大学毕业证(yu毕业证)在读证明认证可查
在线制作约克大学毕业证(yu毕业证)在读证明认证可查在线制作约克大学毕业证(yu毕业证)在读证明认证可查
在线制作约克大学毕业证(yu毕业证)在读证明认证可查
ydyuyu
 
原版制作美国爱荷华大学毕业证(iowa毕业证书)学位证网上存档可查
原版制作美国爱荷华大学毕业证(iowa毕业证书)学位证网上存档可查原版制作美国爱荷华大学毕业证(iowa毕业证书)学位证网上存档可查
原版制作美国爱荷华大学毕业证(iowa毕业证书)学位证网上存档可查
ydyuyu
 
Russian Escort Abu Dhabi 0503464457 Abu DHabi Escorts
Russian Escort Abu Dhabi 0503464457 Abu DHabi EscortsRussian Escort Abu Dhabi 0503464457 Abu DHabi Escorts
Russian Escort Abu Dhabi 0503464457 Abu DHabi Escorts
Monica Sydney
 
Abu Dhabi Escorts Service 0508644382 Escorts in Abu Dhabi
Abu Dhabi Escorts Service 0508644382 Escorts in Abu DhabiAbu Dhabi Escorts Service 0508644382 Escorts in Abu Dhabi
Abu Dhabi Escorts Service 0508644382 Escorts in Abu Dhabi
Monica Sydney
 
Indian Escort in Abu DHabi 0508644382 Abu Dhabi Escorts
Indian Escort in Abu DHabi 0508644382 Abu Dhabi EscortsIndian Escort in Abu DHabi 0508644382 Abu Dhabi Escorts
Indian Escort in Abu DHabi 0508644382 Abu Dhabi Escorts
Monica Sydney
 

Kürzlich hochgeladen (20)

Nagercoil Escorts Service Girl ^ 9332606886, WhatsApp Anytime Nagercoil
Nagercoil Escorts Service Girl ^ 9332606886, WhatsApp Anytime NagercoilNagercoil Escorts Service Girl ^ 9332606886, WhatsApp Anytime Nagercoil
Nagercoil Escorts Service Girl ^ 9332606886, WhatsApp Anytime Nagercoil
 
call girls in Anand Vihar (delhi) call me [🔝9953056974🔝] escort service 24X7
call girls in Anand Vihar (delhi) call me [🔝9953056974🔝] escort service 24X7call girls in Anand Vihar (delhi) call me [🔝9953056974🔝] escort service 24X7
call girls in Anand Vihar (delhi) call me [🔝9953056974🔝] escort service 24X7
 
一比一原版(Curtin毕业证书)科廷大学毕业证原件一模一样
一比一原版(Curtin毕业证书)科廷大学毕业证原件一模一样一比一原版(Curtin毕业证书)科廷大学毕业证原件一模一样
一比一原版(Curtin毕业证书)科廷大学毕业证原件一模一样
 
在线制作约克大学毕业证(yu毕业证)在读证明认证可查
在线制作约克大学毕业证(yu毕业证)在读证明认证可查在线制作约克大学毕业证(yu毕业证)在读证明认证可查
在线制作约克大学毕业证(yu毕业证)在读证明认证可查
 
20240508 QFM014 Elixir Reading List April 2024.pdf
20240508 QFM014 Elixir Reading List April 2024.pdf20240508 QFM014 Elixir Reading List April 2024.pdf
20240508 QFM014 Elixir Reading List April 2024.pdf
 
Trump Diapers Over Dems t shirts Sweatshirt
Trump Diapers Over Dems t shirts SweatshirtTrump Diapers Over Dems t shirts Sweatshirt
Trump Diapers Over Dems t shirts Sweatshirt
 
20240507 QFM013 Machine Intelligence Reading List April 2024.pdf
20240507 QFM013 Machine Intelligence Reading List April 2024.pdf20240507 QFM013 Machine Intelligence Reading List April 2024.pdf
20240507 QFM013 Machine Intelligence Reading List April 2024.pdf
 
Best SEO Services Company in Dallas | Best SEO Agency Dallas
Best SEO Services Company in Dallas | Best SEO Agency DallasBest SEO Services Company in Dallas | Best SEO Agency Dallas
Best SEO Services Company in Dallas | Best SEO Agency Dallas
 
Ballia Escorts Service Girl ^ 9332606886, WhatsApp Anytime Ballia
Ballia Escorts Service Girl ^ 9332606886, WhatsApp Anytime BalliaBallia Escorts Service Girl ^ 9332606886, WhatsApp Anytime Ballia
Ballia Escorts Service Girl ^ 9332606886, WhatsApp Anytime Ballia
 
Mira Road Housewife Call Girls 07506202331, Nalasopara Call Girls
Mira Road Housewife Call Girls 07506202331, Nalasopara Call GirlsMira Road Housewife Call Girls 07506202331, Nalasopara Call Girls
Mira Road Housewife Call Girls 07506202331, Nalasopara Call Girls
 
原版制作美国爱荷华大学毕业证(iowa毕业证书)学位证网上存档可查
原版制作美国爱荷华大学毕业证(iowa毕业证书)学位证网上存档可查原版制作美国爱荷华大学毕业证(iowa毕业证书)学位证网上存档可查
原版制作美国爱荷华大学毕业证(iowa毕业证书)学位证网上存档可查
 
APNIC Policy Roundup, presented by Sunny Chendi at the 5th ICANN APAC-TWNIC E...
APNIC Policy Roundup, presented by Sunny Chendi at the 5th ICANN APAC-TWNIC E...APNIC Policy Roundup, presented by Sunny Chendi at the 5th ICANN APAC-TWNIC E...
APNIC Policy Roundup, presented by Sunny Chendi at the 5th ICANN APAC-TWNIC E...
 
best call girls in Hyderabad Finest Escorts Service 📞 9352988975 📞 Available ...
best call girls in Hyderabad Finest Escorts Service 📞 9352988975 📞 Available ...best call girls in Hyderabad Finest Escorts Service 📞 9352988975 📞 Available ...
best call girls in Hyderabad Finest Escorts Service 📞 9352988975 📞 Available ...
 
Russian Escort Abu Dhabi 0503464457 Abu DHabi Escorts
Russian Escort Abu Dhabi 0503464457 Abu DHabi EscortsRussian Escort Abu Dhabi 0503464457 Abu DHabi Escorts
Russian Escort Abu Dhabi 0503464457 Abu DHabi Escorts
 
Real Men Wear Diapers T Shirts sweatshirt
Real Men Wear Diapers T Shirts sweatshirtReal Men Wear Diapers T Shirts sweatshirt
Real Men Wear Diapers T Shirts sweatshirt
 
Call girls Service in Ajman 0505086370 Ajman call girls
Call girls Service in Ajman 0505086370 Ajman call girlsCall girls Service in Ajman 0505086370 Ajman call girls
Call girls Service in Ajman 0505086370 Ajman call girls
 
Abu Dhabi Escorts Service 0508644382 Escorts in Abu Dhabi
Abu Dhabi Escorts Service 0508644382 Escorts in Abu DhabiAbu Dhabi Escorts Service 0508644382 Escorts in Abu Dhabi
Abu Dhabi Escorts Service 0508644382 Escorts in Abu Dhabi
 
20240510 QFM016 Irresponsible AI Reading List April 2024.pdf
20240510 QFM016 Irresponsible AI Reading List April 2024.pdf20240510 QFM016 Irresponsible AI Reading List April 2024.pdf
20240510 QFM016 Irresponsible AI Reading List April 2024.pdf
 
APNIC Updates presented by Paul Wilson at ARIN 53
APNIC Updates presented by Paul Wilson at ARIN 53APNIC Updates presented by Paul Wilson at ARIN 53
APNIC Updates presented by Paul Wilson at ARIN 53
 
Indian Escort in Abu DHabi 0508644382 Abu Dhabi Escorts
Indian Escort in Abu DHabi 0508644382 Abu Dhabi EscortsIndian Escort in Abu DHabi 0508644382 Abu Dhabi Escorts
Indian Escort in Abu DHabi 0508644382 Abu Dhabi Escorts
 

Geb for browser automation

  • 2. AGENDA Functional testing Geb - cudos and history How Geb works Geb and Ratpack, Grails 2 and 3 Browser support Tips and Tricks
  • 3. 2 . 1 JACOB AAE MIKKELSEN Senior Engineer at LEGO Microservice based architechture on JVM Previously 4 years at Gennemtænkt IT Consultant on Groovy and Grails External Associate Professor - University of Southern Denmark @JacobAae Blogs The Grails Diary
  • 4. 2 . 23 . 1 FUNCTIONAL TESTING
  • 5.
  • 8. 3 . 4 FUNCTIONAL TESTING Ignores the specifics of the underlying so ware component under test. Whitebox / Greybox Merely asserts that providing certain input results in certain output. Web-application: Programmatically controlling a web browser to simulate the actions of a user on a web page.
  • 9. 3 . 5 BROWSER AUTOMATION
  • 10. 3 . 64 . 1
  • 11. 4 . 2 GEB HISTORY Started in November 2009 Created by Luke Daley Current project lead Marcin Erdman
  • 12. GEB IMPLEMENTATION Build on top of the WebDriver browser automation library successor to the Selenium Remote Control (RC) testing framework. Selenium RC → JavaScript to interact WebDriver → native browser drivers Use JUnit or Spock
  • 13. 4 . 3 WEBDRIVER Very active development Stable API and feature set Verbose Low level Not a complete solution
  • 14. 4 . 4 WHY GEB jQuery like selector syntax Power of WebDriver (Easier api) Robustness of Page Object modeling Expressiveness of the Groovy language Integrates well with build systems (Gradle/Maven) Excellent user manual/documentation
  • 15. 4 . 5
  • 16. 5 . 1 USING GEB
  • 17. 4 . 6 5 . 2 NAVIGATOR The $()method returns a Navigator object General format - Jquery like selecter syntax $ ( < c s s s e l e c t o r > , < i n d e x / r a n g e > , < a t t r i b u t e / t e x t m a t c h e r s > )
  • 18. GEB SELECTORS (1) / / m a t c h a l l ' p ' e l e m e n t s o n p a g e $ ( " p " ) / / m a t c h t h e f i r s t ' p ' e l e m e n t o n t h e p a g e $ ( " p " , 0 ) / / A l l ' d i v ' e l e m e n t s w i t h a t i t l e v a l u e ' s e c t i o n ' $ ( " d i v " , t i t l e : " s e c t i o n " ) / / m a t c h t h e f i r s t ' d i v ' e l e m e n t t e x t ' s e c t i o n ' $ ( " d i v " , 0 , t e x t : " s e c t i o n " ) / / m a t c h t h e f i r s t ' d i v ' e l e m e n t w i t h t h e c l a s s ' m a i n ' $ ( " d i v . m a i n " , 0 )
  • 19. 5 . 3 GEB SELECTORS (2) Text attribute supports regex / / A n y d i v w i t h t h e t e x t s t a r t i n g w i h G R 8 $ ( " d i v " , t e x t : ~ / G R 8 . + / ) $ ( " p " , t e x t : s t a r t s W i t h ( " G R 8 " ) ) / / A n d o t h e r h a n d y p r e d i c a t e s $ ( " d i v " , c l a s s : c o n t a i n s ( " u i - " ) )
  • 20. 5 . 4 GEB SELECTORS (3) Selecting returns Navigatorobjects / / T h e p a r e n t o f t h e f i r s t d i v $ ( " d i v " , 0 ) . p a r e n t ( ) / / A l l t a b l e s w i t h a c e l l s p a c i n g / / a t t r i b u t e v a l u e o f 0 t h a t a r e n e s t e d i n a p a r a g r a p h $ ( " p " ) . f i n d ( " t a b l e " , c e l l s p a c i n g : ' 0 ' )
  • 21. 5 . 55 . 6 CSS SUPPORT $ ( " t a b l e t r : n t h - c h i l d ( 2 n + 1 ) t d " )
  • 22. RETRIVING INFORMATION < p i d = " s a m p l e " c l a s s = " c l a s s - a c l a s s - b " t i t l e = " S a m p l e p e l e m e n t " > S a m p l e t e x t < / p > $ ( " p " ) . t e x t ( ) = = " S a m p l e t e x t " $ ( " # s a m p l e " ) . t a g ( ) = = " p " $ ( " p " ) . @ t i t l e = = " S a m p l e p e l e m e n t " $ ( " p " ) . c l a s s e s ( ) = = [ " c l a s s - a " , " c l a s s - b " ]
  • 23. 5 . 7 INTERACTION WITH CONTENT click() isDisplayed() withConfirm{} withAlert{} $ ( " a . b t n " ) . c l i c k ( ) $ ( " d i v " ) . i s D i s p l a y e d ( ) w i t h C o n f i r m { $ ( " b u t t o n . d e l e t e " ) . c l i c k ( ) }
  • 24. 5 . 85 . 9 SENDING INPUT i m p o r t o r g . o p e n q a . s e l e n i u m . K e y s / / S h o r t h a n d f o r s e n d K e y s ( ) m e t h o d o f W e b D r i v e r . $ ( " d i v " ) < < " a b c " $ ( " i n p u t " , n a m e : " f o o " ) < < K e y s . c h o r d ( K e y s . C O N T R O L , " c " )
  • 25. 5 . 10 INTERACTION Using ActionsAPI from WebDriver is possible. But Geb provides the interactclosure
  • 26. 5 . 11 CONTROL-CLICKING i m p o r t o r g . o p e n q a . s e l e n i u m . K e y s i n t e r a c t { k e y D o w n K e y s . C T R L c l i c k $ ( " a . m y L i n k " ) k e y U p K e y s . C T R L }
  • 27. SIMULATE DRAG-N-DROP i n t e r a c t { c l i c k A n d H o l d ( $ ( ' # d r a g g a b l e ' ) ) m o v e B y O f f s e t ( 1 5 0 , 2 0 0 ) r e l e a s e ( ) } Or easier i n t e r a c t { d r a g A n d D r o p B y ( $ ( " # d r a g g a b l e " ) , 1 5 0 , 2 0 0 ) }
  • 28. 5 . 12 MORE INTERACTION WITH FORMS < f o r m > < i n p u t t y p e = " t e x t " n a m e = " g e b " v a l u e = " F u n c t i o n a l " / > < / f o r m > The value can be read and written via property notation… $ ( " f o r m " ) . g e b = = " F u n c t i o n a l " $ ( " f o r m " ) . g e b = " T e s t i n g " These are literally shortcuts for… $ ( " f o r m " ) . f i n d ( " i n p u t " , n a m e : " g e b " ) . v a l u e ( ) = = " F u n c t i o n a l " $ ( " f o r m " ) . f i n d ( " i n p u t " , n a m e : " g e b " ) . v a l u e ( " T e s t i n g " )
  • 29. 5 . 13 VARIABLES AVAILABLE title browser currentUrl currentWindow
  • 30. 5 . 14 MORE POSSIBILITIES Uploading files Downloading files Interacting with javascript js object (Example later)
  • 31. 5 . 156 . 1 STANDALONE GEB SCRIPT
  • 32. GEB STANDALONE EXAMPLE Lets try to automate: Searching for Greach Conference Click the first link Hopefully end up on the right homepage
  • 33. 6 . 2 GEB STANDALONE EXAMPLE g o " h t t p : / / d u c k d u c k g o . c o m " $ ( ' i n p u t ' , n a m e : ' q ' ) . v a l u e ( " G r e a c h C o n f e r e n c e " ) $ ( ' i n p u t ' , n a m e : ' q ' ) < < K e y s . E N T E R w a i t F o r ( 1 0 , 1 ) { $ ( " # l i n k s " ) . d i s p l a y e d } s l e e p ( 3 0 0 0 ) / / F o r d e m o r e a s o n s $ ( " h 2 . r e s u l t _ _ t i t l e " ) . f i r s t ( ) . c l i c k ( ) w a i t F o r { t i t l e . s t a r t s W i t h " G r e a c h " }
  • 34. 6 . 37 . 1 STRUCTURING GEB TESTS
  • 35. SCENARIO Lets test a small todo application Lets test the following 1. Goto list of todos 2. Create new item 3. Delete item again
  • 36. 7 . 27 . 3 GEB SPEC BASICS i m p o r t g e b . s p o c k . G e b S p e c @ S t e p w i s e / / E n s u r e s t h e t e s t s a r e r u n s e q u e n t i a l l y c l a s s T o d o S p e c e x t e n d s G e b S p e c { / / S p o c k s p e c s h e r e }
  • 37. GEB SPEC (1) The naive inmaintainable way! d e f " G o t o i n d e x p a g e " ( ) { w h e n : ' G o t o i n d e x u r l ' g o ' / ' t h e n : ' V e r i f y w e a r e t h e r e ' t i t l e = = " T o d o L i s t " }
  • 38. 7 . 4 GEB SPEC (2) The naive inmaintainable way! d e f " C r e a t e n e w t o d o " ( ) { w h e n : ' I n p u t t e x t a n d s u b m i t ' $ ( " # n e w - t o d o " ) < < " D o t h i s " $ ( " # c r e a t e - b t n " ) . c l i c k ( ) t h e n : ' V e r i f y n e w i t e m p r e s e n t i n l i s t ' w a i t F o r { $ ( " # c o u n t " ) . t e x t ( ) = = ' 4 ' } $ ( ' l i . t o d o - i t e m ' ) . a n y { i t . t e x t ( ) . c o n t a i n s ' D o t h i s ' } a n d : ' V e r i f y i n p u t f i e l d e m p t y ' ! $ ( " # n e w - t o d o " ) . t e x t ( ) }
  • 39. 7 . 5 GEB SPEC (3) The naive inmaintainable way! d e f " D e l e t e t o d o i t e m " ( ) { w h e n : ' C l i c k d e l e t e a n d a c c e p t ' w i t h C o n f i r m { $ ( ' b u t t o n ' , 4 ) . c l i c k ( ) } t h e n : ' V e r i f y i t e m d e l e t e d ' w a i t F o r { $ ( " # c o u n t " ) . t e x t ( ) = = ' 3 ' } $ ( ' l i . t o d o - i t e m ' ) . e v e r y { ! ( i t . t e x t ( ) . c o n t a i n s ( ' D o t h i s ' ) ) } }
  • 40. 7 . 68 . 1 GEB SPEC - THE BETTER WAY If we make a few scenarios, there will be Much duplication Many places to correct if we change the layout / DOM
  • 41.
  • 42. 8 . 28 . 3 SOLUTION Use pages and modules
  • 43. PAGE OBJECTS Describes a web page Url How to check if we are at the correct place Content we wish to interact with .. and how it is found Helper methods
  • 44. 8 . 4 PAGE OBJECTS p a c k a g e n e t . g r y d e s k e . g r e a c h . p a g e s i m p o r t g e b . P a g e c l a s s A b o u t P a g e e x t e n d s P a g e { s t a t i c u r l = " / a b o u t " s t a t i c a t = { t i t l e = = " A b o u t " } s t a t i c c o n t e n t = { h e a d e r { $ ( ' h 1 ' , 0 ) } } }
  • 45. 8 . 58 . 6 CONTENT CLOSURE s t a t i c c o n t e n t = { i n f o ( r e q u i r e d : f a l s e ) { $ ( " d i v . i n f o " ) } m e s s a g e ( w a i t : f a l s e ) { $ ( " d i v . m e s s a g e " ) } }
  • 46. 8 . 7 MODULES Describes repeated content Across pages Repeated content within the same page
  • 47. MODULES ACROSS PAGES p a c k a g e n e t . g r y d e s k e . g r e a c h . m o d u l e s i m p o r t g e b . M o d u l e c l a s s M e n u b a r M o d u l e e x t e n d s M o d u l e { s t a t i c b a s e = { $ ( " n a v . n a v b a r " ) } s t a t i c c o n t e n t = { h o m e { $ ( ' a ' , t e x t : ' T o d o L i s t ' ) } a b o u t { $ ( ' a ' , t e x t : ' A b o u t ' ) } } }
  • 48. 8 . 8 MODULES FOR REPEATED CONTENT p a c k a g e n e t . g r y d e s k e . g r e a c h . m o d u l e s i m p o r t g e b . M o d u l e c l a s s T o d o I t e m M o d u l e e x t e n d s M o d u l e { s t a t i c c o n t e n t = { c h e c k b o x { $ ( ' i n p u t ' , t y p e : ' c h e c k b o x ' ) } l a b e l { $ ( ' l a b e l ' ) . t e x t ( ) } d e l e t e B t n { $ ( ' b u t t o n ' ) } } }
  • 49. 8 . 98 . 10 USING MODULES s t a t i c c o n t e n t = { m e n u b a r { m o d u l e M e n u b a r M o d u l e } t o d o s ( r e q u i r e d : f a l s e ) { $ ( ' l i . t o d o - i t e m ' ) . m o d u l e L i s t ( T o d o I t e m M o d u l e ) } }
  • 50. 8 . 11 GEB SPEC - STRUCTURED Lets try to restructure the ugly spec from before
  • 51. 8 . 12 GEB SPEC - STRUCTURED (1) d e f " G o t o i n d e x p a g e " ( ) { w h e n : ' G o t o i n d e x u r l ' t o I n d e x P a g e t h e n : ' V e r i f y 3 i t e m s p r e s e n t ' a t I n d e x P a g e c o u n t V a l u e = = ' 3 ' }
  • 52. GEB SPEC - STRUCTURED (2) d e f " C r e a t e n e w t o d o " ( ) { w h e n : ' I n p u t t e x t a n d s u b m i t ' t o d o I n p u t = " D o t h i s " t o d o S u b m i t . c l i c k ( ) t h e n : ' V e r i f y n e w i t e m p r e s e n t i n l i s t ' w a i t F o r { c o u n t V a l u e = = ' 4 ' } t o d o s . a n y { i t . l a b e l = = ' D o t h i s ' } a n d : ' V e r i f y i n p u t f i e l d e m p t y ' ! t o d o I n p u t . t e x t ( ) }
  • 53. 8 . 13 GEB SPEC - STRUCTURED (3) d e f " D e l e t e t o d o i t e m " ( ) { w h e n : ' C l i c k d e l e t e a n d a c c e p t ' w i t h C o n f i r m { t o d o s . f i n d { i t . l a b e l = = ' D o t h i s ' } . d e l e t e B t n . c l i c k ( ) } t h e n : ' V e r i f y i t e m d e l e t e d ' w a i t F o r { c o u n t V a l u e = = ' 3 ' } t o d o s . e v e r y { i t . l a b e l ! = ' D o t h i s ' } }
  • 54. 8 . 14 STANDALONE REVISITED c l a s s D u c k D u c k G o P a g e e x t e n d s g e b . P a g e { s t a t i c u r l = " h t t p : / / d u c k d u c k g o . c o m " s t a t i c a t = { t i t l e = = ~ / D u c k D u c k G o / } s t a t i c c o n t e n t = { i n p u t F i e l d { $ ( ' i n p u t ' , n a m e : ' q ' ) } } d e f s u b m i t ( ) { i n p u t F i e l d < < K e y s . E N T E R } }
  • 55. 8 . 15 STANDALONE REVISITED c l a s s D u c k D u c k G o R e s u l t P a g e e x t e n d s g e b . P a g e { s t a t i c u r l = " h t t p : / / d u c k d u c k g o . c o m " s t a t i c a t = { $ ( " # l i n k s " ) . d i s p l a y e d } s t a t i c c o n t e n t = { l i n k s { $ ( " h 2 . r e s u l t _ _ t i t l e " ) } } d e f c l i c k L i n k ( i n t l i n k N u m b e r ) { l i n k s [ l i n k N u m b e r ] . c l i c k ( ) } }
  • 56. 8 . 168 . 17 STANDALONE REVISITED c l a s s G r e a c h P a g e e x t e n d s g e b . P a g e { s t a t i c a t = { t i t l e . s t a r t s W i t h ( " G r e a c h " ) } }
  • 57. STANDALONE REVISITED b r o w s e r . w i t h { t o D u c k D u c k G o P a g e i n p u t F i e l d < < " G r e a c h C o n f e r e n c e " s u b m i t ( ) w a i t F o r ( 1 0 , 0 . 5 ) { a t D u c k D u c k G o R e s u l t P a g e } s l e e p ( 3 0 0 0 ) / / F o r d e m o r e a s o n s c l i c k L i n k ( 0 ) w a i t F o r { a t G r e a c h P a g e } }
  • 58. 8 . 189 . 1 GEB WITH RATPACK AND GRAILS
  • 59. GEB WITH RATPACK d e p e n d e n c i e s { . . . / / I f u s i n g S p o c k , n e e d t o d e p e n d o n g e b - s p o c k t e s t C o m p i l e " o r g . g e b i s h : g e b - s p o c k : 0 . 1 3 . 1 " t e s t C o m p i l e " o r g . s p o c k f r a m e w o r k : s p o c k - c o r e : 1 . 0 - g r o o v y - 2 . 4 " / / N e e d a d r i v e r i m p l e m e n t a t i o n t e s t C o m p i l e ( " o r g . s e l e n i u m h q . s e l e n i u m : s e l e n i u m - f i r e f o x - d r i v e r : 2 . 5 3 . 0 " ) t e s t R u n t i m e ( " o r g . s e l e n i u m h q . s e l e n i u m : s e l e n i u m - s u p p o r t : 2 . 5 3 . 0 " ) }
  • 60. 9 . 29 . 3 GEB WITH RATPACK @ S h a r e d d e f a u t = n e w G r o o v y R a t p a c k M a i n A p p l i c a t i o n U n d e r T e s t ( ) d e f s e t u p ( ) { U R I b a s e = a u t . a d d r e s s b r o w s e r . b a s e U r l = b a s e . t o S t r i n g ( ) }
  • 61. 9 . 4 INTERACTING WITH RATPACK APPLICATION When some functionality is needed that is not exposed through the browser, it can be necessary to interact with the application under test.
  • 62. 9 . 5 INTERACTING WITH RATPACK Include in build.gradle d e p e n d e n c i e s { . . . c o m p i l e r a t p a c k . d e p e n d e n c y ( " r e m o t e " ) t e s t C o m p i l e r a t p a c k . d e p e n d e n c y ( " r e m o t e - t e s t " ) . . .
  • 63. INTERACTING WITH RATPACK @ S h a r e d d e f a u t = n e w G r o o v y R a t p a c k M a i n A p p l i c a t i o n U n d e r T e s t ( ) R e m o t e C o n t r o l r e m o t e C o n t r o l d e f s e t u p ( ) { U R I b a s e = a u t . a d d r e s s b r o w s e r . b a s e U r l = b a s e . t o S t r i n g ( ) r e m o t e C o n t r o l = n e w R e m o t e C o n t r o l ( a u t ) }
  • 64. 9 . 6 INTERACTING WITH RATPACK d e f " C o m p l e t e i t e m a n d c h e c k d a t a b a s e " ( ) { w h e n : ' C h e c k i t e m d o n e ' t o d o s . f i n d { i t . l a b e l = = ' G i v e G e b p r e s e n t a t i o n ' } . c h e c k b o x . c l i c k ( ) t h e n : ' U s e r e m o t e c o n t r o l t o c h e c k d a t a b a s e ' r e m o t e C o n t r o l . e x e c { B o o l e a n c o m p l e t e d T o d o I t e m . w i t h N e w S e s s i o n { T o d o I t e m t o d o I t e m = T o d o I t e m . f i n d B y T e x t ( ' G i v e G e b p r e s e n t a t i o n ' ) c o m p l e t e d = t o d o I t e m . c o m p l e t e d } c o m p l e t e d } = = t r u e }
  • 65. 9 . 7 GEB AND GRAILS 2.X Must install plugin in BuildConfig.groovy d e p e n d e n c i e s { . . . t e s t ( " o r g . s e l e n i u m h q . s e l e n i u m : s e l e n i u m - s u p p o r t : 2 . 5 3 . 0 " ) t e s t ( " o r g . s e l e n i u m h q . s e l e n i u m : s e l e n i u m - f i r e f o x - d r i v e r : 2 . 5 3 . 0 " ) t e s t " o r g . g e b i s h : g e b - s p o c k : 0 . 1 2 . 1 " } p l u g i n s { . . . t e s t " o r g . g r a i l s . p l u g i n s : g e b : 0 . 1 2 . 1 " }
  • 66. 9 . 89 . 9 GEB TESTS IN GRAILS 2.X Tests placed in test/functionalfolder Running the tests g r a i l s t e s t - a p p f u n c t i o n a l :
  • 67. GEB AND GRAILS 3 Geb is default in build.gradle d e p e n d e n c i e s { . . . t e s t C o m p i l e " o r g . g r a i l s . p l u g i n s : g e b " t e s t R u n t i m e ( " o r g . s e l e n i u m h q . s e l e n i u m : s e l e n i u m - h t m l u n i t - d r i v e r : 2 . 4 7 . 1 " ) t e s t R u n t i m e " n e t . s o u r c e f o r g e . h t m l u n i t : h t m l u n i t : 2 . 1 8 " }
  • 68. 9 . 10 GEB TESTS IN GRAILS 3 Creating Geb Spec g r a i l s c r e a t e - f u n c t i o n a l - t e s t M y G e b S c e n a r i o Placing the test in src/integration-test/groovy Running the tests g r a i l s t e s t - a p p - i n t e g r a t i o n
  • 69. 9 . 11 GENERATED CLASS @ I n t e g r a t i o n @ R o l l b a c k c l a s s D e m o S p e c e x t e n d s G e b S p e c { v o i d " t e s t s o m e t h i n g " ( ) { w h e n : " T h e h o m e p a g e i s v i s i t e d " g o ' / ' t h e n : " T h e t i t l e i s c o r r e c t " $ ( ' t i t l e ' ) . t e x t ( ) = = " W e l c o m e t o G r a i l s " } }
  • 70. 9 . 12 INTERACTING WITH GRAILS 2.5 Tests not running in same JVM Done with remote-control plugin Send a closure for execution in application c o m p i l e " : r e m o t e - c o n t r o l : 2 . 0 "
  • 71. 9 . 139 . 14 INTERACTING WITH GRAILS 3.0 Application is in same jvm Interaction is possible directly Tests run as integration tests
  • 72. 9 . 15 INTERACTING WITH GRAILS 3.0 s e t u p : A t t e n d e e . w i t h N e w T r a n s a c t i o n { 1 5 . t i m e s { n e w A t t e n d e e ( n a m e : " N $ i t " , e m a i l : " m $ i t @ t . d k " ) . s a v e ( ) } }
  • 73. 10 . 1 CONFIGURATION AND BROWSER SUPPORT
  • 74. 10 . 2 GEBCONFIG Configuration for Geb is placed in GebConfig.groovy It must be placed in default package scope  http://www.gebish.org/manual/current/configuration.html
  • 75. 10 . 3 DRIVER It is possible to configure the browser used.
  • 77. 10 . 410 . 5 DRIVER It is possible to configure the browser used. build.gradle c o m p i l e ' o r g . s e l e n i u m h q . s e l e n i u m : s e l e n i u m - c h r o m e - d r i v e r : 2 . 4 9 . 0 ' c o m p i l e ' o r g . s e l e n i u m h q . s e l e n i u m : s e l e n i u m - f i r e f o x - d r i v e r : 2 . 4 9 . 0 '
  • 78. FIREFOX GebConfig.groovy i m p o r t o r g . o p e n q a . s e l e n i u m . f i r e f o x . F i r e f o x P r o f i l e i m p o r t o r g . o p e n q a . s e l e n i u m . f i r e f o x . F i r e f o x D r i v e r d r i v e r = { F i r e f o x P r o f i l e p r o f i l e = n e w F i r e f o x P r o f i l e ( ) p r o f i l e . s e t P r e f e r e n c e ( " b r o w s e r . d o w n l o a d . f o l d e r L i s t " , 2 ) p r o f i l e . s e t P r e f e r e n c e ( " b r o w s e r . d o w n l o a d . d i r " , " / t m p " ) p r o f i l e . s e t P r e f e r e n c e ( " b r o w s e r . h e l p e r A p p s . n e v e r A s k . s a v e T o D i s k " , " t e x t / c s v " ) d e f d r i v e r I n s t a n c e = n e w F i r e f o x D r i v e r ( p r o f i l e ) d r i v e r I n s t a n c e . m a n a g e ( ) . w i n d o w ( ) . m a x i m i z e ( ) d r i v e r I n s t a n c e }
  • 79. 10 . 610 . 7 CHROME Needs ChromeDriver downloaded Pretty fast and stable
  • 80. CHROME (1) GebConfig.groovy p r i v a t e S t r i n g d r i v e r L o c a t i o n D e p e n d i n g O n O p e r a t i n g S y s t e m ( ) { S t r i n g o s = S y s t e m . g e t P r o p e r t y ( " o s . n a m e " ) . t o L o w e r C a s e ( ) ; d e f l o c = " h t t p : / / c h r o m e d r i v e r . s t o r a g e . g o o g l e a p i s . c o m / 2 . 2 0 " i f ( o s . c o n t a i n s ( ' m a c ' ) ) { r e t u r n " $ { l o c } / c h r o m e d r i v e r _ m a c 3 2 . z i p " } i f ( o s . c o n t a i n s ( ' w i n ' ) ) { r e t u r n " $ { l o c } / c h r o m e d r i v e r _ w i n 3 2 . z i p " } r e t u r n " $ { l o c } / c h r o m e d r i v e r _ l i n u x 6 4 . z i p " }
  • 81. 10 . 8 CHROME (2) GebConfig.groovy p r i v a t e v o i d d o w n l o a d D r i v e r ( F i l e f i l e , S t r i n g p a t h ) { i f ( ! f i l e . e x i s t s ( ) ) { d e f a n t = n e w A n t B u i l d e r ( ) a n t . g e t ( s r c : p a t h , d e s t : ' d r i v e r . z i p ' ) a n t . u n z i p ( s r c : ' d r i v e r . z i p ' , d e s t : f i l e . p a r e n t ) a n t . d e l e t e ( f i l e : ' d r i v e r . z i p ' ) a n t . c h m o d ( f i l e : f i l e , p e r m : ' 7 0 0 ' ) } }
  • 82. 10 . 9 CHROME (3) GebConfig.groovy d e f c h r o m e D r i v e r = n e w F i l e ( ' b u i l d / d r i v e r s / c h r o m e / c h r o m e d r i v e r ' ) d o w n l o a d D r i v e r ( c h r o m e D r i v e r , d r i v e r L o c a t i o n D e p e n d i n g O n O p e r a t i n g S y s t e m ( ) ) S y s t e m . s e t P r o p e r t y ( ' w e b d r i v e r . c h r o m e . d r i v e r ' , c h r o m e D r i v e r . a b s o l u t e P a t h ) d r i v e r = { d e f d r i v e r I n s t a n c e = n e w C h r o m e D r i v e r ( ) d e f b r o w s e r W i n d o w = d r i v e r I n s t a n c e . m a n a g e ( ) . w i n d o w ( ) / / w i d t h , h e i g h t b r o w s e r W i n d o w . s i z e = n e w D i m e n s i o n ( 1 0 0 0 , 2 5 0 0 ) b r o w s e r W i n d o w . p o s i t i o n = n e w P o i n t ( 0 , 0 ) d r i v e r I n s t a n c e }
  • 83. 10 . 1010 . 11 CLOUD BASED TESTING SauceLabs BrowserStack
  • 84. SAUCELABS GebConfig.groovy i m p o r t g e b . d r i v e r . S a u c e L a b s D r i v e r F a c t o r y d e f s l B r o w s e r = S y s t e m . g e t P r o p e r t y ( " g e b . s a u c e l a b s . b r o w s e r " ) i f ( s l B r o w s e r ) { d r i v e r = { d e f u s e r n a m e = S y s t e m . g e t e n v ( " G E B _ S A U C E _ L A B S _ U S E R " ) a s s e r t u s e r n a m e d e f a c c e s s K e y = S y s t e m . g e t e n v ( " G E B _ S A U C E _ L A B S _ A C C E S S _ P A S S W O R D " ) a s s e r t a c c e s s K e y n e w S a u c e L a b s D r i v e r F a c t o r y ( ) . c r e a t e ( s a u c e L a b s B r o w s e r , u s e r n a m e , a c c e s s K e y ) } }
  • 85. 10 . 12 SAUCELABS build.gradle a p p l y p l u g i n : " g e b - s a u c e l a b s " r e p o s i t o r i e s { . . . m a v e n C e n t r a l ( ) } d e p e n d e n c i e s { . . . s a u c e C o n n e c t " c o m . s a u c e l a b s : c i - s a u c e : 1 . 1 1 3 " }
  • 86. 10 . 13 SAUCELABS s a u c e L a b s { b r o w s e r s { f i r e f o x _ l i n u x _ 1 9 d e l e g a t e . " i n t e r n e t e x p l o r e r _ v i s t a _ 9 " n e x u s 4 { c a p a b i l i t i e s ( b r o w s e r N a m e : " a n d r o i d " , p l a t f o r m : " L i n u x " , v e r s i o n : " 4 . 4 " , d e v i c e N a m e : " L G N e x u s 4 " ) } } t a s k { t e s t C l a s s e s D i r = t e s t . t e s t C l a s s e s D i r t e s t S r c D i r s = t e s t . t e s t S r c D i r s c l a s s p a t h = t e s t . c l a s s p a t h } a c c o u n t { u s e r n a m e = " u s e r n a m e " a c c e s s K e y = " a p i - k e y " } c o n n e c t { / / p o r t = 4 4 4 4 / / a d d i t i o n a l O p t i o n s = [ ' - - p r o x y ' , ' p r o x y . e x a m p l e . c o m : 8 0 8 0 ' ] } }
  • 87. 10 . 1411 . 1 JAVASCRIPT In case you need to interact using javascript
  • 88. 11 . 2 EXECUTING JAVASCRIPT Clicking a button that is hidden will create a ElementNotVisibleException < f i e l d s e t c l a s s = " w e l l " s t y l e = " d i s p l a y : n o n e " > < a h r e f = " / l i s t " c l a s s = " b t n " > L i s t < / a > < / f i e l d s e t >
  • 89. 11 . 3 EXECUTING JAVASCRIPT J a v a s c r i p t E x e c u t o r e x e c u t o r = ( J a v a s c r i p t E x e c u t o r ) d r i v e r e x e c u t o r . e x e c u t e S c r i p t ( ' j Q u e r y ( " . w e l l " ) . s h o w ( ) ; ' )
  • 90. 11 . 4 WRAPPING JAVASCRIPT d e f j s ( S t r i n g s c r i p t ) { ( d r i v e r a s J a v a s c r i p t E x e c u t o r ) . e x e c u t e S c r i p t ( s c r i p t ) } j s ( ' j Q u e r y ( " . w e l l " ) . s h o w ( ) ; ' )
  • 91. 11 . 5 JQUERY SHORTHAND $ ( " d i v # a " ) . j q u e r y . m o u s e o v e r ( ) $ ( " # a " ) . j q u e r y . t r i g g e r ( ' m o u s e o v e r ' )
  • 92. 12 . 1 WAITING AND PAUSING
  • 93. WAITING GebConfig.groovy w a i t i n g { t i m e o u t = 1 0 r e t r y I n t e r v a l = 0 . 5 } b a s e N a v i g a t o r W a i t i n g = t r u e a t C h e c k W a i t i n g = t r u e
  • 94. 12 . 2 USING WAITING < d i v c l a s s = " f a d e - m e - i n " s t y l e = " d i s p l a y : n o n e " > H i - a r e y o w a i t i n g f o r m e ? < / d i v > < s c r i p t > $ ( ' d i v . f a d e - m e - i n ' ) . d e l a y ( 3 0 0 0 ) . s l i d e D o w n ( ) ; < / s c r i p t > s t a t i c c o n t e n t = { f a d e I n M e s s a g e { $ ( ' d i v . f a d e - m e - i n ' ) } } t h e n : w a i t F o r { f a d e I n M e s s a g e . t e x t ( ) = = ' H i - a r e y o w a i t i n g f o r m e ? ' }
  • 95. 12 . 3 PAUSING GEB p r i v a t e v o i d p a u s e ( ) { j s . e x e c " " " ( f u n c t i o n ( ) { w i n d o w . _ _ g e b P a u s e d = t r u e ; v a r d i v = d o c u m e n t . c r e a t e E l e m e n t ( " d i v " ) ; d i v . s e t A t t r i b u t e ( ' s t y l e ' , " p o s i t i o n : a b s o l u t e ; t o p : 0 p x ; r i g h t : 0 p x ; z - i n d e x : 3 0 0 0 ; p a d d i n g : 1 0 p x ; b a c k g r o u n d - c o l o r : r e d ; " ) ; v a r b u t t o n = d o c u m e n t . c r e a t e E l e m e n t ( " b u t t o n " ) ; b u t t o n . i n n e r H T M L = " U n p a u s e G e b " ; b u t t o n . o n c l i c k = f u n c t i o n ( ) { w i n d o w . _ _ g e b P a u s e d = f a l s e ; } d i v . a p p e n d C h i l d ( b u t t o n ) ; d o c u m e n t . g e t E l e m e n t s B y T a g N a m e ( " b o d y " ) [ 0 ] . a p p e n d C h i l d ( d i v ) ; } ) ( ) ; " " " w a i t F o r ( 3 0 0 ) { ! j s . _ _ g e b P a u s e d } }
  • 96. 12 . 412 . 5 PAUSING GEB w h e n : ' D e m o i n g p a u s e ' p a u s e ( ) / / P a u s e G e b u n t i l b u t t o n p r e s s e d
  • 98. 12 . 613 . 1 REPORTING
  • 99. 13 . 2 TEST REPORTS Nicely formatted Spock power-assert format
  • 100. 13 . 3 SPOCK REPORTS Take a look at pluginSpock Reports t e s t C o m p i l e ( ' c o m . a t h a y d e s : s p o c k - r e p o r t s : 1 . 2 . 1 0 ' ) { / / t h i s a v o i d s a f f e c t i n g y o u r v e r s i o n o f G r o o v y / S p o c k t r a n s i t i v e = f a l s e }
  • 103. 13 . 4 SCREENSHOTS Screenshots and HTML from end of each test: Extend from GebReportingSpec c l a s s A t t e n d e e F u n c t i o n a l S p e c e x t e n d s G e b R e p o r t i n g S p e c GebConfig.groovy r e p o r t s D i r = n e w F i l e ( " b u i l d / g e b - r e p o r t s " ) r e p o r t O n T e s t F a i l u r e O n l y = t r u e
  • 104. 13 . 513 . 613 . 7 AD-HOC SCREENSHOTS r e p o r t " W h e n - f o r m - i s - j u s t - f i l l e d " Saves a report in reportsDir Numbered in increasing order
  • 105. 14 OTHER USAGES Screenscraping of a site Solving complex problems like 2048