Search code examples
spocksharedunroll

How to implement Spock Parameterized test best practice?


I have a test spec, which can be run with a unique data set. The best practice for this is a bit unclear. How should the code below be modified to run with:

@Stepwise
class marktest extends ShopBootStrap  {

   private boolean useProductionUrl = false

   def "Can Access Shop DevLogin page"() {
       // DevStartLogin: 'New OE Start' button click
       setup:
           println System.getProperty("webdriver.chrome.driver")
       when:
           to ShopDevStartPage
       then:
           at ShopDevStartPage
   }

   def "on start enrollment, select 'United States' and click 'continue' button"() {
       when: "enter Sponsor ID and click New OE Start"
           to ShopDevStartPage
           sponsorId.value(ShopDevStartPage.SPONSORID)
           NewOEButton.click()
       then:
           waitFor { NewEnrollmentPage }
   }
}

1) data set 1

private boolean useProductionUrl = false
protocol = System.getProperty("protocol") ?: "https"
baseDomain = System.getProperty("base.url") ?: "beta.com"
testPassword = System.getProperty("test.password") ?: "dontyouwish"

2) data set 2

private boolean useProductionUrl = true
protocol = System.getProperty("protocol") ?: "https"
baseDomain = System.getProperty("base.url") ?: "production.com"
testPassword = System.getProperty("test.password") ?: "dywyk"

Solution

  • Generally, to make a test depend on data, use a where block, possibly together with the @Unroll annotation.

    However, your case is simply not the best example for a data driven test.
    The baseDomain and protocol should rather be set in the GebConfig.groovy, similar to the snippets you provided. Refer to this section in the Book of Geb, as that is what you are using.

    Simple example (in GebConfig.groovy):

    environments {
      production {
        baseUrl = "https://production.com"
      }
      beta {
        baseUrl = "https://beta.com"
      }
    }
    

    If done this way, your individual tests does not need to care about the environment, as this is already built into Geb. For example when navigating to pages, their base URL is automatically set. You did not provide that part of the code in your example (how the pages are defined), so I cannot help you with that directly.

    Now, in your case, as far as the "password" is concerned, you could read that from an environment variable or system property, that you set close to where you configure Geb with geb.env or geb.build.baseUrl system properties.
    Note I am just considering this for practial reasons without any regards towards secrecy of the password.

    You would pick up the variable in the page class that uses it.
    Example code in page class:

    static content = {
        //...
        passwordInput = { $('input[type="password"]') }
        //...
    }
    
    void enterPassword() {
        passwordInput.value(System.getProperty('test.password'))
    }
    

    To make this work, you need to start your test with the system properties set to correct values.

    E.g. if starting directly from the command line, you would add parameters -Dgeb.env=beta -Dtest.password=dontyouwish. If running from a Gradle task, you would need to add appropriate systemProperty keys and values to that task. If running from IDE, refer to your IDEs documentation on how to set Java system properties when running a program.