Geb for browser automation

Preview:

Citation preview

1

GEB FOR BROWSERAUTOMATION

Jacob Aae Mikkelsen

AGENDAFunctional testing

Geb - cudos and history

How Geb works

Geb and Ratpack, Grails 2 and 3

Browser support

Tips and Tricks

2 . 1

JACOB AAE MIKKELSENSenior 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 SouthernDenmark

@JacobAae

Blogs The Grails Diary

2 . 23 . 1

FUNCTIONAL TESTING

3 . 2

WHY?

3 . 3

3 . 4

FUNCTIONAL TESTINGIgnores the specifics of the underlying so�warecomponent under test.

Whitebox / Greybox

Merely asserts that providing certain input results incertain output.

Web-application: Programmatically controlling a webbrowser to simulate the actions of a user on a web page.

3 . 5

BROWSER AUTOMATION

3 . 64 . 1

4 . 2

GEB HISTORYStarted in November 2009

Created by Luke Daley

Current project lead Marcin Erdman

GEB IMPLEMENTATIONBuild on top of the WebDriver browser automation library

successor to the Selenium Remote Control (RC) testingframework.

Selenium RC → JavaScript to interact

WebDriver → native browser drivers

Use JUnit or Spock

4 . 3

WEBDRIVERVery active development

Stable API and feature set

Verbose

Low level

Not a complete solution

4 . 4

WHY GEBjQuery 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

4 . 65 . 1

USING GEB

4 . 6

5 . 2

NAVIGATORThe $() 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 Navigator objects

/ / 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 CONTENTclick()

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 INPUTi 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

INTERACTIONUsing Actions API from WebDriver is possible.

But Geb provides the interact closure

5 . 11

CONTROL-CLICKINGi 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-DROPi 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 AVAILABLEtitle

browser

currentUrl

currentWindow

5 . 14

MORE POSSIBILITIESUploading files

Downloading files

Interacting with javascript

js object (Example later)

5 . 156 . 1

STANDALONE GEB SCRIPT

GEB STANDALONE EXAMPLELets try to automate:

Searching for Greach Conference

Click the first link

Hopefully end up on the right homepage

6 . 2

GEB STANDALONE EXAMPLEg 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

SCENARIOLets 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 BASICSi 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 WAYIf we make a few scenarios, there will be

Much duplication

Many places to correct if we change the layout / DOM

8 . 28 . 3

SOLUTIONUse pages and modules

PAGE OBJECTSDescribes 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 OBJECTSp 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 CLOSUREs 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

MODULESDescribes repeated content

Across pages

Repeated content within the same page

MODULES ACROSS PAGESp 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 CONTENTp 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 MODULESs 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 - STRUCTUREDLets try to restructure the ugly spec from before

GEB SPEC - STRUCTURED (1)

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 REVISITEDc 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 REVISITEDc 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 REVISITEDc 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 REVISITEDb 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 RATPACKd 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 RATPACKAPPLICATION

When some functionality is needed that is not exposedthrough the browser, it can be necessary to interact with the

application under test.

9 . 5

INTERACTING WITH RATPACKInclude 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 RATPACKd 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.XMust 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.XTests placed in test/functional folder

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 3Geb 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 3Creating 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.5Tests 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.0Application is in same jvm

Interaction is possible directly

Tests run as integration tests

9 . 15

INTERACTING WITH GRAILS 3.0s 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 BROWSERSUPPORT

10 . 2

GEBCONFIGConfiguration 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

DRIVERIt is possible to configure the browser used.

SUPPORTED DRIVERSFirefox

Chrome

InternetExplorer

Safari

HtmlUnit

PhantomJS

10 . 410 . 5

DRIVERIt 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 '

FIREFOXGebConfig.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

CHROMENeeds 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 TESTINGSauceLabs

BrowserStack

SAUCELABSGebConfig.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

SAUCELABSbuild.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

SAUCELABSs 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

JAVASCRIPTIn case you need to interact using javascript

11 . 2

EXECUTING JAVASCRIPTClicking a button that is hidden will create aElementNotVisibleException

< 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 JAVASCRIPTJ 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 JAVASCRIPTd 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

WAITINGGebConfig.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 GEBp 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 GEBw 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 REPORTSNicely formatted

Spock power-assert format

13 . 3

SPOCK REPORTSTake 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

SCREENSHOTSScreenshots 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 SCREENSHOTSr 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 USAGESScreenscraping of a site

Solving complex problems like 2048

RESOURCEShttp://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...

Recommended