Question

I have many working/passing functional geb/spock tests (each extending GebReportingSpec) that are testing a web application with test data all created from the BootStrap.groovy at the beginning of the functional test suite.

I want to move the test data creation into startup() / teardown() methods within each Spec, well actually I wanted to have them inherit it from a base class but apparently the StepWise has issues with inheritance.

So, at present each of my test spec classes look something like:

@Stepwise
class ExampleSpec extends GebReportingSpec {

    def "valid root user logs in"() {

        given: "I am at the login page"
        to LoginPage

        when: "I enter root's credentials"
        username = "root"
        password = "password"

        and: "I click the login button"
        loginButton.click()

        then: "I am logged in and directed to the welcome page"
        at WelcomePage
    }
}

Now, my problem is that I can't seem to create a new test (above the first test) that can create test data. Without having a valid given/when/then statement the test doesnt appear to be executed and calling a method from within the existing test also doesnt appear to work. I have looked into the grails-remote-control plugin to help me and I believe this will allow me to successfully envoke closures to setup data but I am not sure on the best mechanism for calling this from within the GebReportSpecs (or some abstract parent).

Below is a brief outline of the kind of thing I want to be able to do, either by making 'setupData()' the first test or by calling that method from within a test... Neither appears to work.

def remote = new RemoteControl()
def setupData() {

    def id = remote {        
        def ShiroUser user = new ShiroUser(username: "root", ...)
        user.save()
        user.id
   }
   println(id)
}

.... Tests then follow

Are there any annotations like @before etc that can force these methods to be invokved?

Any suggestions are appreciated.

Solution: I have accepted dmahapatro's response below at the correct answer, but have also provided an example of my final solution below for those who may find it useful.

Was it helpful?

Solution

(Untested)
GebReportingSpec extends GebSpec which ultimately extends spock.lang.Specification which has Fixture Methods.

You can use them like:

@Stepwise
class ExampleSpec extends GebReportingSpec {
    def setupSpec(){
       super.setupSpec()
       //setup your data
    }

    def cleanupSpec(){
       super.cleanupSpec()
       //I do not think you would need anything else here
    }

    def "This is test 1"(){

    }

    def "This is test 2"(){

    }
}

You cannot use setup as one of your test method because the sate is not maintained for a single test case. It goes like this:-

setup called -> test1 -> teardown called  
setup called -> test2 -> teardown called  
setup called -> test3 -> teardown called  
.........

OTHER TIPS


## Solved ##

Thanks to dmahapatro (and erdi). I specifically glossed over setupSpec() and cleanup() as they are private in GebReportingSpec.

Just for completion sake I am going to post a simplified version of my final solution using the grails remote control plugin just in-case it helps anyone else. The only thing to note is that the setup/teardown appears to be called once per Spec, not before each test. Which for me is actually preferably as my test data is quite complex and takes time to be created. So you have a set of test data from the Spec which is modified through the tests in the Spec and then finally cleared down before your next Spec is executed.

@Stepwise
class TestDataBaseSpec extends GebReportingSpec {

    protected void createTestUsers() {

        def remote = new RemoteControl()
        def created = remote {

        def createUser = { name, roles, pwHash ->
            def user = new ShiroUser(username: name, passwordHash: pwHash, passwordSetDate: new Date())
            roles.each { user.addToRoles(it) }
            user.save(failOnError: true)
            return user
        }

        createUser("root", [ShiroRole.findByName("base_user")], pwHash)
        // .. repeat for more
        }
    }

    protected void deleteTestUsers() {

        def remote = new RemoteControl()
        def created = remote {
            ShiroUser.findAll().each {
                it.delete(flush: true)
            }
            return true
        }
    }
}

@Stepwise
class ExampleSpec extends TestDataBaseSpec {

    def setupSpec() {
        super.createTestUsers()
    }

    def cleanupSpec() {
        super.deleteTestUsers()
    }

    def "valid root user logs in"() {

        given: "I am at the login page"
        to LoginPage

        when: "I enter root's credentials"
        username = "root"
        password = "password"

        and: "I click the login button"
        loginButton.click()

        then: "I am logged in and directed to the welcome page"
        at WelcomePage
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top