Search code examples
groovyspockgeb

Only first test succeeds running Spock suite with setupSpec()


I've been experimenting with Geb/Spock for testing some web applications but have hit an issue that I cannot seem to figure out.

I have a test class with a setupSpec() fixture method that calls a login method defined in AuthenticationSpec, and then a bunch of other methods that assert various things on this page:

class TestThisPage extends AuthenticationSpec {
    def setupSpec() {
        loginComplete("some user ID", "some password")
        assert page instanceof ThisPage
    }

    def "Verify some link's text is correct"() {
        when: "The user is at this page"

        then: "The this specific link's text is correct"
        assert  someLink.text().equalsIgnoreCase("I am some text")
    }

    def "Verify that the correct user name is displayed"() {
        when: "The user is signed in and at this page"

        then: "The signed-in user's display name appears correctly on the page"
        assert signInText.equalsIgnoreCase("Signed in as: some user ID")
    }

    def "Verify this page's copyright"() {
        when: "The user is redirected to this page"

        then: "The copyright is correct"
        assert legalInfo.text().trim().equalsIgnoreCase("Some copyright text here")
    }
}

Now when I run TestThisPage as a test suite, only the first test case (after the setupSpec() method) passes, all the rest fail with: groovy.lang.MissingPropertyException: Unable to resolve <some content identifier specified on ThisPage>

I know my content is defined correctly:

class ThisPage extends Page {

    static at = {
        title == "This page"
    }
    static content = {
        someLink(to: SomeOtherPage) {$("a[href='someOtherPage.jsp'")}
        signInText  {loginInfo.find("#static-label").text().trim()}
    }
}

and I can switch the order of the test methods and the first one will always pass, even if it failed the last run. If I run these test methods as a single unit test, they all pass too.

The only way I have gotten this to work is if I add at ThisPage to the when or given block. I guess it makes sense to explicitly set the page to ThisPage in each test method, but why, when running the entire class as a test suite, does only the first test method pass (even without the at ThisPage)?


Solution

  • Each subsequent test method does not know about the page you are on.

    You can create a shared instance of the page which can then be accessed by each of your tests within the same spec:

    class TestThisPage extends AuthenticationSpec {
    
        @Shared ThisPage thisPage
    
        def setupSpec() {
            thisPage = loginComplete("some user ID", "some password")
            assert page instanceof ThisPage
        }
    
        def "Verify some link's text is correct"() {
            when: "The user is at this page"
    
            then: "The this specific link's text is correct"
            assert  thisPage.someLink.text().equalsIgnoreCase("I am some text")
        }
    
        def "Verify that the correct user name is displayed"() {
            when: "The user is signed in and at this page"
    
            then: "The signed-in user's display name appears correctly on the page"
            assert thisPage.signInText.equalsIgnoreCase("Signed in as: some user ID")
        }
    
        def "Verify this page's copyright"() {
            when: "The user is redirected to this page"
    
            then: "The copyright is correct"
            assert thisPage.legalInfo.text().trim().equalsIgnoreCase("Some copyright text here")
        }
    }