SlideShare une entreprise Scribd logo
1  sur  54
Télécharger pour lire hors ligne
Groovier Selenium
                                Denver JUG 8/13/2008
                                    Frederic Jean
                                  fred@fredjean.net
                                frederic.jean@sun.com



Wednesday, August 13, 2008                              1
who am i


Wednesday, August 13, 2008              2
Topics
                             (Really) Quick intro to Selenium
                             Groovy Metaprogramming through
                             progressive refactorings of a single,
                             simple yet verbose Java Selenium RC
                             Driver example.
                             A few sundry items


Wednesday, August 13, 2008                                           3
Selenium

                             UI testing tool
                             Runs in browser
                             Well suited for Ajax applications




Wednesday, August 13, 2008                                       4
Selenium IDE

                             Firefox plugin
                             Simplifies writing and testing Selenese
                             test case
                             Can record and play back Selenese tests



Wednesday, August 13, 2008                                             5
Selenese
                             HTML Tables
                              Action
                              Target
                              Value
                             Intepreted by Selenium Core
                             Actions match JavaScript functions

Wednesday, August 13, 2008                                        6
Example
                                         BlogTest

                             open                   /

                    clickAndWait            link=Adoption

                                     Out of my mind... : category
                       assertTitle
                                              adoption



Wednesday, August 13, 2008                                          7
Selenese Locators

                             Allows an action to target a specific
                             DOM element on the page
                             <type>=<locator>




Wednesday, August 13, 2008                                          8
Selenese Locators
                             Locator Type               Description
                                             The name of an input element on a
                                name
                                                              form
                                              The id associated with an element
                                  id
                                                            on a page
                                            The text contained within an anchor
                                 link
                                                         element (<a/>)
                                                A JavaScript expression that
                                 dom
                                                      returns an element
                                             An XPath expression pointing to an
                                xpath
                                                      element on the page

Wednesday, August 13, 2008                                                        9
Sample Test


Wednesday, August 13, 2008                 10
Selenese TestSuites

                             Groups and organizes individual
                             Selenese tests
                             Can be run through ant




Wednesday, August 13, 2008                                     11
Selenium RC

                             Runs as a process on a system
                             Listens to requests on a specific port
                             Has drivers for different languages




Wednesday, August 13, 2008                                           12
Selenium RC Drivers
                             Drives the Selenium RC Ser ver
                             programatically
                             Allows integration with xUnit
                             frameworks
                             Flow control and conditionals
                             Java driver provides a SeleneseTestCase
                             class

Wednesday, August 13, 2008                                             13
Generating Java Test


Wednesday, August 13, 2008             14
Generated Java
    package com.example.tests;

    import com.thoughtworks.selenium.*;
    import java.util.regex.Pattern;

    public class NewTest extends SeleneseTestCase {
       public void setUp() throws Exception {
          setUp(quot;http://fredjean.net/quot;, quot;*chromequot;);
       }
       public void testNew() throws Exception {
          selenium.open(quot;/quot;);
          selenium.click(quot;link=Adoptionquot;);
          selenium.waitForPageToLoad(quot;30000quot;);
          assertEquals(quot;Out of my mind... : category adoptionquot;, selenium.getTitle());
          selenium.click(quot;link=We Are Out!quot;);
          for (int second = 0;; second++) {
             if (second >= 60) fail(quot;timeoutquot;);
             try { if (selenium.isTextPresent(quot;Commentsquot;)) break; } catch (Exception e) {}
             Thread.sleep(1000);
          }

               assertTrue(selenium.isTextPresent(quot;Trackbacksquot;));
          }
    }



Wednesday, August 13, 2008                                                                   15
Generated Java
                                  Where
    package com.example.tests;

    import com.thoughtworks.selenium.*;
                                          is it used?
    import java.util.regex.Pattern;

    public class NewTest extends SeleneseTestCase {
       public void setUp() throws Exception {
          setUp(quot;http://fredjean.net/quot;, quot;*chromequot;);
       }
       public void testNew() throws Exception {
          selenium.open(quot;/quot;);
          selenium.click(quot;link=Adoptionquot;);
          selenium.waitForPageToLoad(quot;30000quot;);
          assertEquals(quot;Out of my mind... : category adoptionquot;, selenium.getTitle());
          selenium.click(quot;link=We Are Out!quot;);
          for (int second = 0;; second++) {
             if (second >= 60) fail(quot;timeoutquot;);
             try { if (selenium.isTextPresent(quot;Commentsquot;)) break; } catch (Exception e) {}
             Thread.sleep(1000);
          }

               assertTrue(selenium.isTextPresent(quot;Trackbacksquot;));
          }
    }



Wednesday, August 13, 2008                                                                   16
Generated Java
    package com.example.tests;

    import com.thoughtworks.selenium.*;  Need to rename class.
    import java.util.regex.Pattern;

    public class NewTest extends SeleneseTestCase {
       public void setUp() throws Exception {
          setUp(quot;http://fredjean.net/quot;, quot;*chromequot;);
       }
       public void testNew() throws Exception {
          selenium.open(quot;/quot;);
          selenium.click(quot;link=Adoptionquot;);
          selenium.waitForPageToLoad(quot;30000quot;);
          assertEquals(quot;Out of my mind... : category adoptionquot;, selenium.getTitle());
          selenium.click(quot;link=We Are Out!quot;);
          for (int second = 0;; second++) {
             if (second >= 60) fail(quot;timeoutquot;);
             try { if (selenium.isTextPresent(quot;Commentsquot;)) break; } catch (Exception e) {}
             Thread.sleep(1000);
          }

               assertTrue(selenium.isTextPresent(quot;Trackbacksquot;));
          }
    }



Wednesday, August 13, 2008                                                                   17
Generated Java from
                                     Must inherit
                                                          SeleneseTestCase
    package com.example.tests;

    import com.thoughtworks.selenium.*;
    import java.util.regex.Pattern;

    public class NewTest extends SeleneseTestCase {
       public void setUp() throws Exception {
          setUp(quot;http://fredjean.net/quot;, quot;*chromequot;);
       }
       public void testNew() throws Exception {
          selenium.open(quot;/quot;);
          selenium.click(quot;link=Adoptionquot;);
          selenium.waitForPageToLoad(quot;30000quot;);
          assertEquals(quot;Out of my mind... : category adoptionquot;, selenium.getTitle());
          selenium.click(quot;link=We Are Out!quot;);
          for (int second = 0;; second++) {
             if (second >= 60) fail(quot;timeoutquot;);
             try { if (selenium.isTextPresent(quot;Commentsquot;)) break; } catch (Exception e) {}
             Thread.sleep(1000);
          }

               assertTrue(selenium.isTextPresent(quot;Trackbacksquot;));
          }
    }



Wednesday, August 13, 2008                                                                   18
Generated Java
    package com.example.tests;

    import com.thoughtworks.selenium.*;
    import java.util.regex.Pattern;


                                        Should rename method
    public class NewTest extends SeleneseTestCase {
       public void setUp() throws Exception {
          setUp(quot;http://fredjean.net/quot;, quot;*chromequot;);
       }
       public void testNew() throws Exception {
          selenium.open(quot;/quot;);
          selenium.click(quot;link=Adoptionquot;);
          selenium.waitForPageToLoad(quot;30000quot;);
          assertEquals(quot;Out of my mind... : category adoptionquot;, selenium.getTitle());
          selenium.click(quot;link=We Are Out!quot;);
          for (int second = 0;; second++) {
             if (second >= 60) fail(quot;timeoutquot;);
             try { if (selenium.isTextPresent(quot;Commentsquot;)) break; } catch (Exception e) {}
             Thread.sleep(1000);
          }

               assertTrue(selenium.isTextPresent(quot;Trackbacksquot;));
          }
    }



Wednesday, August 13, 2008                                                                   19
Generated Java
    package com.example.tests;


                                    selenium.this
    import com.thoughtworks.selenium.*;
    import java.util.regex.Pattern;

                                   selenium.that
    public class NewTest extends SeleneseTestCase {
       public void setUp() throws Exception {

       }                      selenium.thisandthat
          setUp(quot;http://fredjean.net/quot;, quot;*chromequot;);

       public void testNew() throws Exception {
          selenium.open(quot;/quot;);
          selenium.click(quot;link=Adoptionquot;);
          selenium.waitForPageToLoad(quot;30000quot;);
          assertEquals(quot;Out of my mind... : category adoptionquot;, selenium.getTitle());
          selenium.click(quot;link=We Are Out!quot;);
          for (int second = 0;; second++) {
             if (second >= 60) fail(quot;timeoutquot;);
             try { if (selenium.isTextPresent(quot;Commentsquot;)) break; } catch (Exception e) {}
             Thread.sleep(1000);
          }

               assertTrue(selenium.isTextPresent(quot;Trackbacksquot;));
          }
    }



Wednesday, August 13, 2008                                                                   20
Generated Java
    package com.example.tests;

    import com.thoughtworks.selenium.*;
    import java.util.regex.Pattern;

    public class NewTest extends SeleneseTestCase {
       public void setUp() throws Exception {
          setUp(quot;http://fredjean.net/quot;, quot;*chromequot;);
       }
       public void testNew() throws Exception {    Where did
                                             waitForTextPresent go?
          selenium.open(quot;/quot;);
          selenium.click(quot;link=Adoptionquot;);
          selenium.waitForPageToLoad(quot;30000quot;);
          assertEquals(quot;Out of my mind... : category adoptionquot;, selenium.getTitle());
          selenium.click(quot;link=We Are Out!quot;);
          for (int second = 0;; second++) {
             if (second >= 60) fail(quot;timeoutquot;);
             try { if (selenium.isTextPresent(quot;Commentsquot;)) break; } catch (Exception e) {}
             Thread.sleep(1000);
          }

               assertTrue(selenium.isTextPresent(quot;Trackbacksquot;));
          }
    }



Wednesday, August 13, 2008                                                                   21
Generated Java

                             Good start
                             Needs some work to be useful
                             Certainly faster than coding by hand
                             Noisy



Wednesday, August 13, 2008                                          22
Groovy
           package com.example.tests

           import com.thoughtworks.selenium.*

           class NewGroovyTest extends SeleneseTestCase {
               void setUp() {
                   setUp quot;http://fredjean.net/quot;, quot;*chromequot;
               }
               void testNew() {
                   selenium.open quot;/quot;
                   selenium.click quot;link=Adoptionquot;
                   selenium.waitForPageToLoad quot;30000quot;
                   assert quot;Out of my mind... : category adoptionquot; == selenium.title
                   selenium.click quot;link=We Are Out!quot;
                   for (second in 0..60) {
                       if (second == 60) fail quot;timeoutquot;
                       if (selenium.isTextPresent(quot;Commentsquot;)) break;
                       sleep(1000)
                   }

                             assert selenium.isTextPresent(quot;Trackbacksquot;)
                   }
           }



Wednesday, August 13, 2008                                                            23
Groovy

                             Less noisy than Java
                             Still repetitive
                             waitForTextPresent is still missing




Wednesday, August 13, 2008                                         24
Metaprogramming


                      Writing of computer programs that write or
                      manipulate other programs (or themselves) as
                                      their data.




                 http://en.wikipedia.org/wiki/Metaprogramming
Wednesday, August 13, 2008                                           25
Metaprogramming

                             Increases code expressiveness
                             Allows SMEs to understand the code
                              Domain Specific Languages




Wednesday, August 13, 2008                                        26
Meta Object Protocol
                             Establishes the rules behind method
                             calling in Groovy
                             Provides the hooks to modify your
                             program's behavior
                              invokeMethod
                              propertyMissing
                              methodMissing

Wednesday, August 13, 2008                                         27
Metaclass

                             All Groovy objects have one
                             Can be defined for Java objects
                             Per class vs per instance
                             Allows developers to quot;mutatequot; a class



Wednesday, August 13, 2008                                           28
Delegation
                             For ward method calls to another object
                             Tedious to do in Java
                              Extend delegate
                              Manually code delegation code
                             Almost trivial in Groovy
                              ExpandoMetaClass

Wednesday, August 13, 2008                                             29
Groovy Delegation
                             /**
                               * Called when a method cannot be found in the class
                               * or the meta class for an object or class.
                               * @param name The name of the missing method
                               * @param args The arguments for the method
                               */
                             void methodMissing(String name, args) {
                                  selenium.quot;$namequot;(* args)
                             }

                             /**
                               * Called when a property cannot be found in the class
                               * or the meta class associated with a class or object.
                               * @param name The name of the property
                               */
                             void propertyMissing(String name) {
                                  selenium.quot;$namequot;
                             }




Wednesday, August 13, 2008                                                              30
Goodbye Repetition
                             void testDelegation() {
                                 open quot;/quot;
                                 click quot;link=Adoptionquot;
                                 waitForPageToLoad quot;30000quot;
                                 assert quot;Out of my mind... : category adoptionquot; == title
                                 click quot;link=We Are Out!quot;
                                 for (second in 0..60) {
                                     if (second == 60) fail quot;timeoutquot;
                                     if (isTextPresent(quot;Commentsquot;)) break;
                                     sleep(1000)
                                 }

                                 assert isTextPresent(quot;Trackbacksquot;)
                             }




Wednesday, August 13, 2008                                                                 31
Performance Hit




Wednesday, August 13, 2008                     32
Performance Hit




Wednesday, August 13, 2008                     33
Intercept, Cache, Invoke

       /**
         * Called when a method cannot be found in the class
         * or the meta class for an object or class.
         * @param name The name of the missing method
         * @param args The arguments for the method
         */
       void methodMissing(String name, args) {
            NewGroovyTest.metaClass.quot;$namequot; = { Object varArgs ->
                delegate.selenium.metaClass.invokeMethod(delegate.selenium, name, varArgs)
            }
            selenium.quot;$namequot;(* args)
       }




Wednesday, August 13, 2008                                                               34
Performance Hit




Wednesday, August 13, 2008                     35
Groovy Delegation

                             Results in cleaner test code
                             Almost trivial to implement in Groovy
                             Performance hit can be mitigated




Wednesday, August 13, 2008                                           36
waitForTextPresent?
                             void testDelegation() {
                                 open quot;/quot;
                                 click quot;link=Adoptionquot;
                                 waitForPageToLoad quot;30000quot;
                                 assert quot;Out of my mind... : category adoptionquot; == title
                                 click quot;link=We Are Out!quot;
                                 for (second in 0..60) {
                                     if (second == 60) fail quot;timeoutquot;
                                     if (isTextPresent(quot;Commentsquot;)) break;
                                     sleep(1000)
                                 }

                                 assert isTextPresent(quot;Trackbacksquot;)
                             }




Wednesday, August 13, 2008                                                                 37
waitForTextPresent?
                             void testDelegation() {
                                 open quot;/quot;                  Replaces waitFor...
                                 click quot;link=Adoptionquot;
                                 waitForPageToLoad quot;30000quot;   with a loop
                                 assert quot;Out of my mind... : category adoptionquot; == title
                                 click quot;link=We Are Out!quot;
                                 for (second in 0..60) {
                                     if (second == 60) fail quot;timeoutquot;
                                     if (isTextPresent(quot;Commentsquot;)) break;
                                     sleep(1000)
                                 }

                                 assert isTextPresent(quot;Trackbacksquot;)
                             }




Wednesday, August 13, 2008                                                                 38
waitForTextPresent?
                             void testDelegation() {
                                 open quot;/quot;
                                 click quot;link=Adoptionquot;
                                 waitForPageToLoad quot;30000quot;
                                 assert quot;Out of my mind... : category adoptionquot; == title
                                 click quot;link=We Are Out!quot;
                                 for (second in 0..60) {
                                                             How about
                                     if (second == 60) fail quot;timeoutquot;

                                                         assertTextPresent?
                                     if (isTextPresent(quot;Commentsquot;)) break;
                                     sleep(1000)
                                 }

                                 assert isTextPresent(quot;Trackbacksquot;)
                             }




Wednesday, August 13, 2008                                                                 39
waitForTextPresent?

                             Selenese generates waitFor, verify, and
                             assert methods
                             Java driver doesn't provide them
                             Java -> Explicitly typed language
                             JavaScript -> What's a type?


Wednesday, August 13, 2008                                             40
Wait a minute...

                             JavaScript is a dynamic language...
                             Groovy is a dynamic language...
                             Why not synthesize these methods in
                             Groovy?



Wednesday, August 13, 2008                                         41
Synthetic Methods

                             Methods that don't really exist
                             Grails finder methods
                              Person.findByFirstNameAndAge(...)




Wednesday, August 13, 2008                                        42
Steps to Take

                             Identify synthetic methods
                             Implement behavior
                             Locate actual getter method




Wednesday, August 13, 2008                                 43
Identifying Methods
                             def methodMissing(String name, args) {
                                 switch (name) {
                                     case ~/waitForNot.*/: return waitForNot(name, args)
                                     case ~/waitFor.*/: return waitFor(name, args)
                                     case ~/assertNot.*/:
                                         assertNot(name, args)
                                         break
                                     case ~/assert.*/:
                                         assertThat(name, args)
                                         break
                                     case ~/verifyNot.*/:
                                         return verifyNot(name, args)
                                     case ~/verify.*/:
                                         return verifyThat(name, args)
                                     default:
                                         return createAndCallMethod(name, args)
                                 }
                             }




Wednesday, August 13, 2008                                                                 44
Implement Behavior
                private waitFor(name, args) {
                    // Make the bold assumption that the time out is the first param.
                    def timeout = args[0]
                    if (timeout instanceof Integer) {
                        args = args[1..args.length - 1].toArray()
                    } else {
                        timeout = 60000
                    }
                    def methodName = getMethodName(quot;waitForquot;, name);
                    for (i in 0..(timeout / 1000)) {
                        if (quot;$methodNamequot;(* args)) {
                             return true;
                        }
                        sleep(1000)
                    }
                    fail(quot;Timeout occured in $name for $argsquot;)
                }




Wednesday, August 13, 2008                                                              45
Locating Getter

                def getMethodName(prefix, name) {
                    [quot;isquot;, quot;getquot;].collect {
                        name.replaceFirst(prefix, it)
                    }.find {
                        delegate.selenium.metaClass.respondsTo(delegate.selenium, it)
                    }
                }




Wednesday, August 13, 2008                                                              46
Loop Begone!

                             void testDelegation() {
                                 open quot;/quot;
                                 click quot;link=Adoptionquot;
                                 waitForPageToLoad quot;30000quot;
                                 assert quot;Out of my mind... : category adoptionquot; == title
                                 click quot;link=We Are Out!quot;
                                 waitForTextPresent quot;Commentsquot;
                                 assertTextPresent quot;Trackbacksquot;
                             }




Wednesday, August 13, 2008                                                                 47
Refactor!
                             Move methods to super class
                              methodMissing
                              propertyMissing
                              Supporting methods
                             Group Groovy tests in one suite


Wednesday, August 13, 2008                                     48
GroovierSelenium
                             Extends SeleneseTestCase with
                             methodMissing
                             Allows Groovy users to write tests that
                             almost look like Selenese
                             http://groovierselenium.googlecode.com
                             Licensed under ASLv2.0


Wednesday, August 13, 2008                                             49
Near Future

                             JUnit 4.5 test runners
                              GroovierSeleniumRunner
                              GroovySuiteRunner
                             @Selenium annotation



Wednesday, August 13, 2008                             50
NetBeans & Groovy

                             Grails and Groovy Plugin integrated
                             with NetBeans 6.5
                             Adds Groovy Support to Java Projects




Wednesday, August 13, 2008                                          51
Looking Back
                             Talked about Selenium
                             Leveraging Groovy metaprogramming
                              Delegating to another object
                              Creating synthetic methods
                             GroovierSelenium
                             NetBeans

Wednesday, August 13, 2008                                       52
Book


                             Programming Groovy (Venkat S.)




Wednesday, August 13, 2008                                    53
Links

                             http://groovy.codehaus.org
                             http://groovierselenium.googlecode.com
                             http://www.pragprog.com/titles/vslg/
                             programming-groovy



Wednesday, August 13, 2008                                            54

Contenu connexe

Similaire à Groovier Selenium (Djug)

Automated Web Testing Using Selenium
Automated Web Testing Using SeleniumAutomated Web Testing Using Selenium
Automated Web Testing Using SeleniumWeifeng Zhang
 
Creating a Web of Data with Restlet
Creating a Web of Data with RestletCreating a Web of Data with Restlet
Creating a Web of Data with Restletguest7d0e11
 
JSUG - Java FX by Christoph Pickl
JSUG - Java FX by Christoph PicklJSUG - Java FX by Christoph Pickl
JSUG - Java FX by Christoph PicklChristoph Pickl
 
Testing Java Web Apps With Selenium
Testing Java Web Apps With SeleniumTesting Java Web Apps With Selenium
Testing Java Web Apps With SeleniumMarakana Inc.
 
Magento's Imagine eCommerce Conference 2011 - Unit Testing with Magento
Magento's Imagine eCommerce Conference 2011 - Unit Testing with MagentoMagento's Imagine eCommerce Conference 2011 - Unit Testing with Magento
Magento's Imagine eCommerce Conference 2011 - Unit Testing with MagentoMagentoImagine
 
Boston selenium meetup: Selenium 2
Boston selenium meetup: Selenium 2Boston selenium meetup: Selenium 2
Boston selenium meetup: Selenium 2epall
 
Introduction to Selenium
Introduction to SeleniumIntroduction to Selenium
Introduction to Seleniumrohitnayak
 
Selenium-Browser-Based-Automated-Testing-for-Grails-Apps
Selenium-Browser-Based-Automated-Testing-for-Grails-AppsSelenium-Browser-Based-Automated-Testing-for-Grails-Apps
Selenium-Browser-Based-Automated-Testing-for-Grails-Appschrisb206 chrisb206
 
Testing Android
Testing AndroidTesting Android
Testing AndroidMarc Chung
 
DevLabs Alliance Top 50 Selenium Interview Questions for SDET
DevLabs Alliance Top 50 Selenium Interview Questions for SDETDevLabs Alliance Top 50 Selenium Interview Questions for SDET
DevLabs Alliance Top 50 Selenium Interview Questions for SDETDevLabs Alliance
 
前端網頁自動測試
前端網頁自動測試 前端網頁自動測試
前端網頁自動測試 政億 林
 
Turbo Charged Test Suites
Turbo Charged Test SuitesTurbo Charged Test Suites
Turbo Charged Test SuitesCurtis Poe
 
An introduction to OSGi
An introduction to OSGi An introduction to OSGi
An introduction to OSGi Andrea Chiodoni
 
Selenium Testing with TestingBot.com
Selenium Testing with TestingBot.comSelenium Testing with TestingBot.com
Selenium Testing with TestingBot.comtestingbot
 
Basics of Selenium IDE,Core, Remote Control
Basics of Selenium IDE,Core, Remote ControlBasics of Selenium IDE,Core, Remote Control
Basics of Selenium IDE,Core, Remote Controlusha kannappan
 

Similaire à Groovier Selenium (Djug) (20)

Automated Web Testing Using Selenium
Automated Web Testing Using SeleniumAutomated Web Testing Using Selenium
Automated Web Testing Using Selenium
 
Creating a Web of Data with Restlet
Creating a Web of Data with RestletCreating a Web of Data with Restlet
Creating a Web of Data with Restlet
 
Groke
GrokeGroke
Groke
 
JSUG - Java FX by Christoph Pickl
JSUG - Java FX by Christoph PicklJSUG - Java FX by Christoph Pickl
JSUG - Java FX by Christoph Pickl
 
Selenium
SeleniumSelenium
Selenium
 
Testing Java Web Apps With Selenium
Testing Java Web Apps With SeleniumTesting Java Web Apps With Selenium
Testing Java Web Apps With Selenium
 
Magento's Imagine eCommerce Conference 2011 - Unit Testing with Magento
Magento's Imagine eCommerce Conference 2011 - Unit Testing with MagentoMagento's Imagine eCommerce Conference 2011 - Unit Testing with Magento
Magento's Imagine eCommerce Conference 2011 - Unit Testing with Magento
 
Boston selenium meetup: Selenium 2
Boston selenium meetup: Selenium 2Boston selenium meetup: Selenium 2
Boston selenium meetup: Selenium 2
 
Introduction to Selenium
Introduction to SeleniumIntroduction to Selenium
Introduction to Selenium
 
Selenium-Browser-Based-Automated-Testing-for-Grails-Apps
Selenium-Browser-Based-Automated-Testing-for-Grails-AppsSelenium-Browser-Based-Automated-Testing-for-Grails-Apps
Selenium-Browser-Based-Automated-Testing-for-Grails-Apps
 
Testing Android
Testing AndroidTesting Android
Testing Android
 
DevLabs Alliance Top 50 Selenium Interview Questions for SDET
DevLabs Alliance Top 50 Selenium Interview Questions for SDETDevLabs Alliance Top 50 Selenium Interview Questions for SDET
DevLabs Alliance Top 50 Selenium Interview Questions for SDET
 
前端網頁自動測試
前端網頁自動測試 前端網頁自動測試
前端網頁自動測試
 
Turbo Charged Test Suites
Turbo Charged Test SuitesTurbo Charged Test Suites
Turbo Charged Test Suites
 
Selenium Primer
Selenium PrimerSelenium Primer
Selenium Primer
 
Testing In Java
Testing In JavaTesting In Java
Testing In Java
 
Testing In Java4278
Testing In Java4278Testing In Java4278
Testing In Java4278
 
An introduction to OSGi
An introduction to OSGi An introduction to OSGi
An introduction to OSGi
 
Selenium Testing with TestingBot.com
Selenium Testing with TestingBot.comSelenium Testing with TestingBot.com
Selenium Testing with TestingBot.com
 
Basics of Selenium IDE,Core, Remote Control
Basics of Selenium IDE,Core, Remote ControlBasics of Selenium IDE,Core, Remote Control
Basics of Selenium IDE,Core, Remote Control
 

Dernier

"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfRankYa
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piececharlottematthew16
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Wonjun Hwang
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 

Dernier (20)

"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdf
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piece
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 

Groovier Selenium (Djug)

  • 1. Groovier Selenium Denver JUG 8/13/2008 Frederic Jean fred@fredjean.net frederic.jean@sun.com Wednesday, August 13, 2008 1
  • 2. who am i Wednesday, August 13, 2008 2
  • 3. Topics (Really) Quick intro to Selenium Groovy Metaprogramming through progressive refactorings of a single, simple yet verbose Java Selenium RC Driver example. A few sundry items Wednesday, August 13, 2008 3
  • 4. Selenium UI testing tool Runs in browser Well suited for Ajax applications Wednesday, August 13, 2008 4
  • 5. Selenium IDE Firefox plugin Simplifies writing and testing Selenese test case Can record and play back Selenese tests Wednesday, August 13, 2008 5
  • 6. Selenese HTML Tables Action Target Value Intepreted by Selenium Core Actions match JavaScript functions Wednesday, August 13, 2008 6
  • 7. Example BlogTest open / clickAndWait link=Adoption Out of my mind... : category assertTitle adoption Wednesday, August 13, 2008 7
  • 8. Selenese Locators Allows an action to target a specific DOM element on the page <type>=<locator> Wednesday, August 13, 2008 8
  • 9. Selenese Locators Locator Type Description The name of an input element on a name form The id associated with an element id on a page The text contained within an anchor link element (<a/>) A JavaScript expression that dom returns an element An XPath expression pointing to an xpath element on the page Wednesday, August 13, 2008 9
  • 11. Selenese TestSuites Groups and organizes individual Selenese tests Can be run through ant Wednesday, August 13, 2008 11
  • 12. Selenium RC Runs as a process on a system Listens to requests on a specific port Has drivers for different languages Wednesday, August 13, 2008 12
  • 13. Selenium RC Drivers Drives the Selenium RC Ser ver programatically Allows integration with xUnit frameworks Flow control and conditionals Java driver provides a SeleneseTestCase class Wednesday, August 13, 2008 13
  • 14. Generating Java Test Wednesday, August 13, 2008 14
  • 15. Generated Java package com.example.tests; import com.thoughtworks.selenium.*; import java.util.regex.Pattern; public class NewTest extends SeleneseTestCase { public void setUp() throws Exception { setUp(quot;http://fredjean.net/quot;, quot;*chromequot;); } public void testNew() throws Exception { selenium.open(quot;/quot;); selenium.click(quot;link=Adoptionquot;); selenium.waitForPageToLoad(quot;30000quot;); assertEquals(quot;Out of my mind... : category adoptionquot;, selenium.getTitle()); selenium.click(quot;link=We Are Out!quot;); for (int second = 0;; second++) { if (second >= 60) fail(quot;timeoutquot;); try { if (selenium.isTextPresent(quot;Commentsquot;)) break; } catch (Exception e) {} Thread.sleep(1000); } assertTrue(selenium.isTextPresent(quot;Trackbacksquot;)); } } Wednesday, August 13, 2008 15
  • 16. Generated Java Where package com.example.tests; import com.thoughtworks.selenium.*; is it used? import java.util.regex.Pattern; public class NewTest extends SeleneseTestCase { public void setUp() throws Exception { setUp(quot;http://fredjean.net/quot;, quot;*chromequot;); } public void testNew() throws Exception { selenium.open(quot;/quot;); selenium.click(quot;link=Adoptionquot;); selenium.waitForPageToLoad(quot;30000quot;); assertEquals(quot;Out of my mind... : category adoptionquot;, selenium.getTitle()); selenium.click(quot;link=We Are Out!quot;); for (int second = 0;; second++) { if (second >= 60) fail(quot;timeoutquot;); try { if (selenium.isTextPresent(quot;Commentsquot;)) break; } catch (Exception e) {} Thread.sleep(1000); } assertTrue(selenium.isTextPresent(quot;Trackbacksquot;)); } } Wednesday, August 13, 2008 16
  • 17. Generated Java package com.example.tests; import com.thoughtworks.selenium.*; Need to rename class. import java.util.regex.Pattern; public class NewTest extends SeleneseTestCase { public void setUp() throws Exception { setUp(quot;http://fredjean.net/quot;, quot;*chromequot;); } public void testNew() throws Exception { selenium.open(quot;/quot;); selenium.click(quot;link=Adoptionquot;); selenium.waitForPageToLoad(quot;30000quot;); assertEquals(quot;Out of my mind... : category adoptionquot;, selenium.getTitle()); selenium.click(quot;link=We Are Out!quot;); for (int second = 0;; second++) { if (second >= 60) fail(quot;timeoutquot;); try { if (selenium.isTextPresent(quot;Commentsquot;)) break; } catch (Exception e) {} Thread.sleep(1000); } assertTrue(selenium.isTextPresent(quot;Trackbacksquot;)); } } Wednesday, August 13, 2008 17
  • 18. Generated Java from Must inherit SeleneseTestCase package com.example.tests; import com.thoughtworks.selenium.*; import java.util.regex.Pattern; public class NewTest extends SeleneseTestCase { public void setUp() throws Exception { setUp(quot;http://fredjean.net/quot;, quot;*chromequot;); } public void testNew() throws Exception { selenium.open(quot;/quot;); selenium.click(quot;link=Adoptionquot;); selenium.waitForPageToLoad(quot;30000quot;); assertEquals(quot;Out of my mind... : category adoptionquot;, selenium.getTitle()); selenium.click(quot;link=We Are Out!quot;); for (int second = 0;; second++) { if (second >= 60) fail(quot;timeoutquot;); try { if (selenium.isTextPresent(quot;Commentsquot;)) break; } catch (Exception e) {} Thread.sleep(1000); } assertTrue(selenium.isTextPresent(quot;Trackbacksquot;)); } } Wednesday, August 13, 2008 18
  • 19. Generated Java package com.example.tests; import com.thoughtworks.selenium.*; import java.util.regex.Pattern; Should rename method public class NewTest extends SeleneseTestCase { public void setUp() throws Exception { setUp(quot;http://fredjean.net/quot;, quot;*chromequot;); } public void testNew() throws Exception { selenium.open(quot;/quot;); selenium.click(quot;link=Adoptionquot;); selenium.waitForPageToLoad(quot;30000quot;); assertEquals(quot;Out of my mind... : category adoptionquot;, selenium.getTitle()); selenium.click(quot;link=We Are Out!quot;); for (int second = 0;; second++) { if (second >= 60) fail(quot;timeoutquot;); try { if (selenium.isTextPresent(quot;Commentsquot;)) break; } catch (Exception e) {} Thread.sleep(1000); } assertTrue(selenium.isTextPresent(quot;Trackbacksquot;)); } } Wednesday, August 13, 2008 19
  • 20. Generated Java package com.example.tests; selenium.this import com.thoughtworks.selenium.*; import java.util.regex.Pattern; selenium.that public class NewTest extends SeleneseTestCase { public void setUp() throws Exception { } selenium.thisandthat setUp(quot;http://fredjean.net/quot;, quot;*chromequot;); public void testNew() throws Exception { selenium.open(quot;/quot;); selenium.click(quot;link=Adoptionquot;); selenium.waitForPageToLoad(quot;30000quot;); assertEquals(quot;Out of my mind... : category adoptionquot;, selenium.getTitle()); selenium.click(quot;link=We Are Out!quot;); for (int second = 0;; second++) { if (second >= 60) fail(quot;timeoutquot;); try { if (selenium.isTextPresent(quot;Commentsquot;)) break; } catch (Exception e) {} Thread.sleep(1000); } assertTrue(selenium.isTextPresent(quot;Trackbacksquot;)); } } Wednesday, August 13, 2008 20
  • 21. Generated Java package com.example.tests; import com.thoughtworks.selenium.*; import java.util.regex.Pattern; public class NewTest extends SeleneseTestCase { public void setUp() throws Exception { setUp(quot;http://fredjean.net/quot;, quot;*chromequot;); } public void testNew() throws Exception { Where did waitForTextPresent go? selenium.open(quot;/quot;); selenium.click(quot;link=Adoptionquot;); selenium.waitForPageToLoad(quot;30000quot;); assertEquals(quot;Out of my mind... : category adoptionquot;, selenium.getTitle()); selenium.click(quot;link=We Are Out!quot;); for (int second = 0;; second++) { if (second >= 60) fail(quot;timeoutquot;); try { if (selenium.isTextPresent(quot;Commentsquot;)) break; } catch (Exception e) {} Thread.sleep(1000); } assertTrue(selenium.isTextPresent(quot;Trackbacksquot;)); } } Wednesday, August 13, 2008 21
  • 22. Generated Java Good start Needs some work to be useful Certainly faster than coding by hand Noisy Wednesday, August 13, 2008 22
  • 23. Groovy package com.example.tests import com.thoughtworks.selenium.* class NewGroovyTest extends SeleneseTestCase { void setUp() { setUp quot;http://fredjean.net/quot;, quot;*chromequot; } void testNew() { selenium.open quot;/quot; selenium.click quot;link=Adoptionquot; selenium.waitForPageToLoad quot;30000quot; assert quot;Out of my mind... : category adoptionquot; == selenium.title selenium.click quot;link=We Are Out!quot; for (second in 0..60) { if (second == 60) fail quot;timeoutquot; if (selenium.isTextPresent(quot;Commentsquot;)) break; sleep(1000) } assert selenium.isTextPresent(quot;Trackbacksquot;) } } Wednesday, August 13, 2008 23
  • 24. Groovy Less noisy than Java Still repetitive waitForTextPresent is still missing Wednesday, August 13, 2008 24
  • 25. Metaprogramming Writing of computer programs that write or manipulate other programs (or themselves) as their data. http://en.wikipedia.org/wiki/Metaprogramming Wednesday, August 13, 2008 25
  • 26. Metaprogramming Increases code expressiveness Allows SMEs to understand the code Domain Specific Languages Wednesday, August 13, 2008 26
  • 27. Meta Object Protocol Establishes the rules behind method calling in Groovy Provides the hooks to modify your program's behavior invokeMethod propertyMissing methodMissing Wednesday, August 13, 2008 27
  • 28. Metaclass All Groovy objects have one Can be defined for Java objects Per class vs per instance Allows developers to quot;mutatequot; a class Wednesday, August 13, 2008 28
  • 29. Delegation For ward method calls to another object Tedious to do in Java Extend delegate Manually code delegation code Almost trivial in Groovy ExpandoMetaClass Wednesday, August 13, 2008 29
  • 30. Groovy Delegation /** * Called when a method cannot be found in the class * or the meta class for an object or class. * @param name The name of the missing method * @param args The arguments for the method */ void methodMissing(String name, args) { selenium.quot;$namequot;(* args) } /** * Called when a property cannot be found in the class * or the meta class associated with a class or object. * @param name The name of the property */ void propertyMissing(String name) { selenium.quot;$namequot; } Wednesday, August 13, 2008 30
  • 31. Goodbye Repetition void testDelegation() { open quot;/quot; click quot;link=Adoptionquot; waitForPageToLoad quot;30000quot; assert quot;Out of my mind... : category adoptionquot; == title click quot;link=We Are Out!quot; for (second in 0..60) { if (second == 60) fail quot;timeoutquot; if (isTextPresent(quot;Commentsquot;)) break; sleep(1000) } assert isTextPresent(quot;Trackbacksquot;) } Wednesday, August 13, 2008 31
  • 34. Intercept, Cache, Invoke /** * Called when a method cannot be found in the class * or the meta class for an object or class. * @param name The name of the missing method * @param args The arguments for the method */ void methodMissing(String name, args) { NewGroovyTest.metaClass.quot;$namequot; = { Object varArgs -> delegate.selenium.metaClass.invokeMethod(delegate.selenium, name, varArgs) } selenium.quot;$namequot;(* args) } Wednesday, August 13, 2008 34
  • 36. Groovy Delegation Results in cleaner test code Almost trivial to implement in Groovy Performance hit can be mitigated Wednesday, August 13, 2008 36
  • 37. waitForTextPresent? void testDelegation() { open quot;/quot; click quot;link=Adoptionquot; waitForPageToLoad quot;30000quot; assert quot;Out of my mind... : category adoptionquot; == title click quot;link=We Are Out!quot; for (second in 0..60) { if (second == 60) fail quot;timeoutquot; if (isTextPresent(quot;Commentsquot;)) break; sleep(1000) } assert isTextPresent(quot;Trackbacksquot;) } Wednesday, August 13, 2008 37
  • 38. waitForTextPresent? void testDelegation() { open quot;/quot; Replaces waitFor... click quot;link=Adoptionquot; waitForPageToLoad quot;30000quot; with a loop assert quot;Out of my mind... : category adoptionquot; == title click quot;link=We Are Out!quot; for (second in 0..60) { if (second == 60) fail quot;timeoutquot; if (isTextPresent(quot;Commentsquot;)) break; sleep(1000) } assert isTextPresent(quot;Trackbacksquot;) } Wednesday, August 13, 2008 38
  • 39. waitForTextPresent? void testDelegation() { open quot;/quot; click quot;link=Adoptionquot; waitForPageToLoad quot;30000quot; assert quot;Out of my mind... : category adoptionquot; == title click quot;link=We Are Out!quot; for (second in 0..60) { How about if (second == 60) fail quot;timeoutquot; assertTextPresent? if (isTextPresent(quot;Commentsquot;)) break; sleep(1000) } assert isTextPresent(quot;Trackbacksquot;) } Wednesday, August 13, 2008 39
  • 40. waitForTextPresent? Selenese generates waitFor, verify, and assert methods Java driver doesn't provide them Java -> Explicitly typed language JavaScript -> What's a type? Wednesday, August 13, 2008 40
  • 41. Wait a minute... JavaScript is a dynamic language... Groovy is a dynamic language... Why not synthesize these methods in Groovy? Wednesday, August 13, 2008 41
  • 42. Synthetic Methods Methods that don't really exist Grails finder methods Person.findByFirstNameAndAge(...) Wednesday, August 13, 2008 42
  • 43. Steps to Take Identify synthetic methods Implement behavior Locate actual getter method Wednesday, August 13, 2008 43
  • 44. Identifying Methods def methodMissing(String name, args) { switch (name) { case ~/waitForNot.*/: return waitForNot(name, args) case ~/waitFor.*/: return waitFor(name, args) case ~/assertNot.*/: assertNot(name, args) break case ~/assert.*/: assertThat(name, args) break case ~/verifyNot.*/: return verifyNot(name, args) case ~/verify.*/: return verifyThat(name, args) default: return createAndCallMethod(name, args) } } Wednesday, August 13, 2008 44
  • 45. Implement Behavior private waitFor(name, args) { // Make the bold assumption that the time out is the first param. def timeout = args[0] if (timeout instanceof Integer) { args = args[1..args.length - 1].toArray() } else { timeout = 60000 } def methodName = getMethodName(quot;waitForquot;, name); for (i in 0..(timeout / 1000)) { if (quot;$methodNamequot;(* args)) { return true; } sleep(1000) } fail(quot;Timeout occured in $name for $argsquot;) } Wednesday, August 13, 2008 45
  • 46. Locating Getter def getMethodName(prefix, name) { [quot;isquot;, quot;getquot;].collect { name.replaceFirst(prefix, it) }.find { delegate.selenium.metaClass.respondsTo(delegate.selenium, it) } } Wednesday, August 13, 2008 46
  • 47. Loop Begone! void testDelegation() { open quot;/quot; click quot;link=Adoptionquot; waitForPageToLoad quot;30000quot; assert quot;Out of my mind... : category adoptionquot; == title click quot;link=We Are Out!quot; waitForTextPresent quot;Commentsquot; assertTextPresent quot;Trackbacksquot; } Wednesday, August 13, 2008 47
  • 48. Refactor! Move methods to super class methodMissing propertyMissing Supporting methods Group Groovy tests in one suite Wednesday, August 13, 2008 48
  • 49. GroovierSelenium Extends SeleneseTestCase with methodMissing Allows Groovy users to write tests that almost look like Selenese http://groovierselenium.googlecode.com Licensed under ASLv2.0 Wednesday, August 13, 2008 49
  • 50. Near Future JUnit 4.5 test runners GroovierSeleniumRunner GroovySuiteRunner @Selenium annotation Wednesday, August 13, 2008 50
  • 51. NetBeans & Groovy Grails and Groovy Plugin integrated with NetBeans 6.5 Adds Groovy Support to Java Projects Wednesday, August 13, 2008 51
  • 52. Looking Back Talked about Selenium Leveraging Groovy metaprogramming Delegating to another object Creating synthetic methods GroovierSelenium NetBeans Wednesday, August 13, 2008 52
  • 53. Book Programming Groovy (Venkat S.) Wednesday, August 13, 2008 53
  • 54. Links http://groovy.codehaus.org http://groovierselenium.googlecode.com http://www.pragprog.com/titles/vslg/ programming-groovy Wednesday, August 13, 2008 54