Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Geb for browser automation

1,591 views

Published on

Geb is a great tool for browser automation and functional testing

Published in: Internet
  • Be the first to comment

Geb for browser automation

  1. 1. 1 GEB FOR BROWSER AUTOMATION Jacob Aae Mikkelsen
  2. 2. AGENDA Functional testing Geb - cudos and history How Geb works Geb and Ratpack, Grails 2 and 3 Browser support Tips and Tricks
  3. 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. 4. 2 . 23 . 1 FUNCTIONAL TESTING
  5. 5. 3 . 2 WHY?
  6. 6. 3 . 3
  7. 7. 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.
  8. 8. 3 . 5 BROWSER AUTOMATION
  9. 9. 3 . 64 . 1
  10. 10. 4 . 2 GEB HISTORY Started in November 2009 Created by Luke Daley Current project lead Marcin Erdman
  11. 11. 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
  12. 12. 4 . 3 WEBDRIVER Very active development Stable API and feature set Verbose Low level Not a complete solution
  13. 13. 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
  14. 14. 4 . 5
  15. 15. 5 . 1 USING GEB
  16. 16. 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 > )
  17. 17. 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 )
  18. 18. 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 - " ) )
  19. 19. 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 ' )
  20. 20. 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 " )
  21. 21. 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 " ]
  22. 22. 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 ( ) }
  23. 23. 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 " )
  24. 24. 5 . 10 INTERACTION Using ActionsAPI from WebDriver is possible. But Geb provides the interactclosure
  25. 25. 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 }
  26. 26. 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 ) }
  27. 27. 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 " )
  28. 28. 5 . 13 VARIABLES AVAILABLE title browser currentUrl currentWindow
  29. 29. 5 . 14 MORE POSSIBILITIES Uploading files Downloading files Interacting with javascript js object (Example later)
  30. 30. 5 . 156 . 1 STANDALONE GEB SCRIPT
  31. 31. GEB STANDALONE EXAMPLE Lets try to automate: Searching for Greach Conference Click the first link Hopefully end up on the right homepage
  32. 32. 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 " }
  33. 33. 6 . 37 . 1 STRUCTURING GEB TESTS
  34. 34. SCENARIO Lets test a small todo application Lets test the following 1. Goto list of todos 2. Create new item 3. Delete item again
  35. 35. 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 }
  36. 36. 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 " }
  37. 37. 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 ( ) }
  38. 38. 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 ' ) ) } }
  39. 39. 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
  40. 40. 8 . 28 . 3 SOLUTION Use pages and modules
  41. 41. 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
  42. 42. 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 ) } } }
  43. 43. 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 " ) } }
  44. 44. 8 . 7 MODULES Describes repeated content Across pages Repeated content within the same page
  45. 45. 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 ' ) } } }
  46. 46. 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 ' ) } } }
  47. 47. 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 ) } }
  48. 48. 8 . 11 GEB SPEC - STRUCTURED Lets try to restructure the ugly spec from before
  49. 49. 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 ' }
  50. 50. 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 ( ) }
  51. 51. 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 ' } }
  52. 52. 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 } }
  53. 53. 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 ( ) } }
  54. 54. 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 " ) } }
  55. 55. 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 } }
  56. 56. 8 . 189 . 1 GEB WITH RATPACK AND GRAILS
  57. 57. 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 " ) }
  58. 58. 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 ( ) }
  59. 59. 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.
  60. 60. 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 " ) . . .
  61. 61. 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 ) }
  62. 62. 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 }
  63. 63. 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 " }
  64. 64. 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 :
  65. 65. 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 " }
  66. 66. 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
  67. 67. 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 " } }
  68. 68. 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 "
  69. 69. 9 . 139 . 14 INTERACTING WITH GRAILS 3.0 Application is in same jvm Interaction is possible directly Tests run as integration tests
  70. 70. 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 ( ) } }
  71. 71. 10 . 1 CONFIGURATION AND BROWSER SUPPORT
  72. 72. 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
  73. 73. 10 . 3 DRIVER It is possible to configure the browser used.
  74. 74. SUPPORTED DRIVERS Firefox Chrome InternetExplorer Safari HtmlUnit PhantomJS
  75. 75. 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 '
  76. 76. 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 }
  77. 77. 10 . 610 . 7 CHROME Needs ChromeDriver downloaded Pretty fast and stable
  78. 78. 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 " }
  79. 79. 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 ' ) } }
  80. 80. 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 }
  81. 81. 10 . 1010 . 11 CLOUD BASED TESTING SauceLabs BrowserStack
  82. 82. 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 ) } }
  83. 83. 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 " }
  84. 84. 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 ' ] } }
  85. 85. 10 . 1411 . 1 JAVASCRIPT In case you need to interact using javascript
  86. 86. 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 >
  87. 87. 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 ( ) ; ' )
  88. 88. 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 ( ) ; ' )
  89. 89. 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 ' )
  90. 90. 12 . 1 WAITING AND PAUSING
  91. 91. 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
  92. 92. 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 ? ' }
  93. 93. 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 } }
  94. 94. 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
  95. 95. PAUSING GEB
  96. 96. 12 . 613 . 1 REPORTING
  97. 97. 13 . 2 TEST REPORTS Nicely formatted Spock power-assert format
  98. 98. 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 }
  99. 99. SPOCK REPORTS
  100. 100. SPOCK REPORTS
  101. 101. 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
  102. 102. 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
  103. 103. 14 OTHER USAGES Screenscraping of a site Solving complex problems like 2048
  104. 104. 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
  105. 105. 1516 QUESTIONS?
  106. 106. some text...

×