At our company’s blog we have already considered many types of the Grails testing. But there are yet one testing type, on which we have to take a look at. In this article we will check out the overview of writing functional tests using Geb/Spock technologies.
Geb and Spock is a young and fast developing technologies. Spock
provides fast and convenient test writing. And Geb provides testing of
the web application by the HTMLUnit and the real browsers web drivers.
Let’s look how it works.
At first, let’s install geb and spock plugins.
1
2
grails install-plugin geb
grails install-plugin spock
Then you should specify following code in your BuildConfig.groovy
dependencies
1
2
3
4
5
6
7
8
dependencies {
test("org.seleniumhq.selenium:selenium-htmlunit-driver:2.0rc3") {
exclude "xml-apis"
}
test("org.seleniumhq.selenium:selenium-chrome-driver:2.0rc3")
test("org.seleniumhq.selenium:selenium-firefox-driver:2.0rc3")
test "org.codehaus.geb:geb-spock:0.6.0"
}
At the test running stage you may experience some troubles because of
conflict between this plugins and some others you have already installed
to your project, one of this conflict related to "release" plugin usage.
For me, adding of the following lines to the build config worked.
1
2
3
4
5
6
7
8
9
10
11
dependencies {
//code we’ve already specified
build('net.sourceforge.nekohtml:nekohtml:1.9.14') {
excludes "xml-apis"
}
}
plugins {
build(':release:1.0.0.M3') {
excludes "svn", 'nekohtml'
}
}
Now, when we have everything ready, let’s get down to business.
Unfortunately, as you may already notice, grails has nothing like grails
create-functional-test, so you should create functional tests by
yourself, specifying them at the directory test/functional or use this
solution
http://adhockery.blogspot.com/2010/08/auto-generate-spock-specs-for-grails.html
.
The next step would be the creating page objects that you are going to
use in your tests. Let’s write a simple test that is gonna test the
login page generated by spring security.
Login page HTML looks as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<form action='${postUrl}' method='POST' id="loginForm" name="loginForm">
<p class="form_label"><g:message code='ex.ui.login.auth.username' default="Username"/></p>
<p><span class="login">
<input type="text" name="j_username" id="username" size="15"/>
</span></p>
<p class="form_label"><g:message code='ex.ui.login.auth.password' default="Password"/></p>
<p><span class="login">
<input type="password" name="j_password" id="password" size="15"/>
</span></p>
<input type="checkbox" class="checkbox" name="${rememberMeParameter}" id="remember_me" checked="checked"/>
<label for="remember_me"><g:message code='ex.ui.login.auth.remember' default="Remember me"/></label>
<g:submitButton name="loginBtn" value="${message(code:'ex.ui.login.auth.loginBtn')}"/>
</form>
We’re gonna use login page and the home page at our test. Their objects
should look like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
package com.sysgears.example.pages
import geb.Page
class ViewUserPage extends Page {
static url = "admin/view"
static at = { title == "Users" }
static content = {
}
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Let’s take a closer look at the properties: "at" closure specifies a
condition when this is a current page. Values at the "content" property
helps us to access the page elements in the tests. Notice, that access
to the elements is provided in jQuery-like language, that makes
accessing the elements extremely convenient. Now, let’s check out the
test example.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package com.sysgears.example;
import geb.spock.GebReportingSpec;
import spock.lang.Stepwise;
import com.sysgears.example.pages.*
@Stepwise
class LoginAuthSpec extends GebReportingSpec {
String getBaseUrl() { "http://localhost:8080/" }
File getReportDir() { new File("target/reports/geb") }
def "invalid login"() {
given: "I am at the login page"
to LoginPage
when: "I am entering invalid password"
loginForm.j_username = "admin"
loginForm.j_password = "ioguffwf"
loginButton.click()
then: "I am being redirected to the login page, the password I entered is wrong"
at LoginPage
loginForm.j_username == "admin"
!loginForm.j_password
}
def "admin login"() {
given : "I am at the login page"
to LoginPage
when: "I am entering valid username and password"
loginForm.j_username = "admin"
loginForm.j_password = "1234"
loginButton.click()
then: "I am being redirected to the admin homepage"
at ViewUserPage
$().text().contains("You are logged in as admin")
}
}
Let’s take a closer look. Test methods here breaked on the sections
given, when and then. 'Given' gives initial conditions for the test,
'when' specifies test behaviour and 'then' checks assertions at the end
of the test. Test methods: to() method sends HTTP request to the URL,
that was specified in url property of the page object; at() method
checks whether specified page is current or not, for doing this
condition specified at the "at" property is being used. Notice that you
may access HTML elements not only via those values, which was defined in
content property, but also access them directly from the test.
For more examples please see this examples from the Geb
https://github.com/geb/geb-example-grails . Also Geb book should be
very useful
http://www.gebish.org/manual/current/