I've only recently started creating Geb/Spock tests for our web app and -- given my limited knowledge of Geb, Spock, and all things Groovy -- have bumped into an error that makes no sense whatsoever (given my Java experience).
So, here is the module in question:
import geb.Module
import geb.navigator.Navigator
class Tile extends Module {
def currencyPair
static content = {
amount {
$(".currencypair-span", text: containsWord(currencyPair))
.parent().parent()
.find(".tile-amount-setup").find("input") }
}
}
Nothing extraordinary there.
Here is the page (I'm not sure how this all fits together, though):
import geb.Page
class TraderApp extends Page {
static url = "./"
static at = { title == "FOOBARTrader" }
static content = {
tile { instrument -> module Tile, currencyPair: instrument }
}
}
Here is the test spec:
import geb.spock.GebSpec
import spock.lang.*
import org.openqa.selenium.Keys
class BugSpec extends SbkSpec {
final CURPAIR = "FOOBAR"
def setupSpec() {
accountSelector.dropDown.click()
accountSelector.dropDown << Keys.chord(Keys.CONTROL, "a")
accountSelector.dropDown << "FxOnly"
accountSelector.dropDown << Keys.ENTER
waitFor() { accountSelector.dropDown.value() == "FXOnly" }
tileLayout("Majors").tab.click()
}
def "test1"() {
given:
tile(CURPAIR).amount.click()
when:
println("foo")
then:
waitFor {true}
}
def "test2"() {
given:
tile(CURPAIR).amount.click()
when: println("bar")
then:
waitFor {true}
}
}
Now, the issue is that the first test will run and pass, but when the second test is run the JVM will report a NoSuchMethodException on the tile() method.
How is this possible? I appreciate that Groovy is a dynamic language, but where is the method disappearing to?
This makes it impossible for me to reuse content in several different tests, as the content in question is unreachable once I exit the first test that uses it.
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running BugSpec
Starting ChromeDriver (v2.10.267521) on port 32075
Only local connections are allowed.
foo
Tests run: 2, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 19.425 sec <<< FAILURE!
test2(BugSpec) Time elapsed: 0.175 sec <<< ERROR!
groovy.lang.MissingMethodException: No signature of method: geb.navigator.NonEmptyNavigator.tile() is applicable for argument types: (java.lang.String) values: [FOOBAR]
Possible solutions: size(), tail(), filter(java.lang.String), find(java.lang.String), is(java.lang.String), take(int)
at geb.navigator.NonEmptyNavigator.methodMissing(NonEmptyNavigator.groovy:463)
at geb.content.NavigableSupport.methodMissing(NavigableSupport.groovy:123)
at geb.Browser.methodMissing(Browser.groovy:194)
at geb.spock.GebSpec.methodMissing(GebSpec.groovy:51)
at BugSpec.test2(BugSpec.groovy:35)
Help please?
EDIT:
As per Erdi's answer, included is also the superclass of BugSpec:
import geb.spock.GebReportingSpec
class SbkSpec extends GebReportingSpec {
def setupSpec() {
def environment = System.getProperty("geb.env");
given:
to AuthApp
expect:
at AuthApp
when:
def username = browser.getConfig().getRawConfig().get("username")
def password = browser.getConfig().getRawConfig().get("password")
login.username.value(username)
login.password.value(password)
login.loginButton.click()
then:
at TraderApp
and:
waitFor() { accountSelector.dropDown.value() == "FOOBAR-ACCOUNT" }
}
def cleanupSpec() {
given:
at TraderApp
then:
logout.logoutButton.click()
}
}
When using the built-in base GebSpec
/GebReportingSpec
Geb dispatches missing method calls to the page
property of spec's browser
property. Something (without seeing more code it's impossible to say what exactly it is) sets that property to an instance of TraderApp
before the first test. Geb recreates the browser
instance between each test which means that the page instance is reset to the default which is an instance of Page
. If you set the page to be an instance of TraderApp
then tile()
method will be found:
def "test2"() {
given:
page TraderApp
tile(CURPAIR).amount.click()
when: println("bar")
then:
waitFor {true}
}
It would be way easier to reason about things and help out if you provided code for the chain of all superclasses of BugSpec
up to the one that extends GebSpec
/GebReportingSpec
. Looks to me like you might be dealing with a smell where the tests are setup in way where their execution order matters.