Post navigation

One of the biggest struggles while testing web applications that use AJAX is dealing with the timing issues caused by asynchronous nature of the request. A common solution is using timeouts to wait for the AJAX call to be completed. This could cause lots of timing issues. Using Geb there is a better way to determine that the AJAX call and its callback has been completed.

In the previous blog post about Geb, we have been introduced to the Geb Framework. In this blogpost we will be introduced to Pages and Modules. A Page represents a specific page from a web application. A module represent a part of the page; for example a sign-up form, a menu bar or contact form. Pages and Modules are very useful since they are very easy to reuse and therefore useful to create more advanced UI tests.

In this blogpost we are going to use Pages and Modules to test the contact form of the JDriven website. We will verify that a success message will appear if we submit a valid form.

Pages have a url attribute which represent the address to the page. To get the complete url, Geb requires a baseUrl which we can define in the GebConfig.groovy

1

baseUrl="http://www.jdriven.com/"

Since the contact form has a select form tag, we require an extra jar as Selenium dependency to handle select tags. Therefore we add the following dependency to our pom.xml.

1

2

3

4

5

<dependency>

<groupId>org.seleniumhq.selenium</groupId>

<artifactId>selenium-support</artifactId>

<version>2.45.0</version>

</dependency>

Next step is to define our ContactPage which extends from geb.Page. The static at attribute represents the condition for Geb to verify the browser is at the defined page.

Java

1

2

3

4

5

6

7

8

9

10

11

classContactPageextendsPage{

staticurl="contact"

staticat={heading.text()=="Contact"}

staticcontent={

heading{$("h2")}

contactForm{module ContactFormModule}

}

}

The static url string represents the suffix which will be added to the baseUrl to navigate to the Contact page.

In the static closure content block we define our content which is on the Contact page. For the JDriven website we define for now the header and the contact form. As you can see there is a reference to the the ContactFormModule which is defined below. The mechanism to define module content is the similar to the way we define page content.

Geb is framework which makes it easy to create functional tests for your application. Since you can use Groovy, Spock and the elegance of the JQuery selector, you can setup solid functional test very easy.

In this blogpost we will make a simple test which will test a functional part of the JDriven website. We will start our test with configuring the Maven POM file. We need to add the following dependencies.

XHTML

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

<dependencies><dependency>

<groupId>org.codehaus.groovy</groupId>

<artifactId>groovy-all</artifactId>

<version>2.4.3</version>

</dependency>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>4.8.1</version>

<scope>test</scope>

</dependency>

<dependency>

<groupId>org.spockframework</groupId>

<artifactId>spock-core</artifactId>

<version>1.0-groovy-2.4</version>

<scope>test</scope>

<exclusions>

<exclusion>

<groupId>org.codehaus.groovy</groupId>

<artifactId>groovy-all</artifactId>

</exclusion>

</exclusions>

</dependency>

<dependency>

<groupId>org.gebish</groupId>

<artifactId>geb-spock</artifactId>

<version>0.10.0</version>

<scope>test</scope>

</dependency>

<dependency>

<groupId>org.seleniumhq.selenium</groupId>

<artifactId>selenium-firefox-driver</artifactId>

<version>2.45.0</version>

<scope>test</scope>

</dependency>

</dependencies>

We also need to configure the GMaven plugin which will compile our Groovy files for us and

XHTML

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

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

<plugins>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-surefire-plugin</artifactId>

<version>2.9</version>

<configuration>

<includes>

<include>*Spec.*</include>

</includes>

<systemPropertyVariables>

<geb.build.reportsDir>target/test-reports/geb</geb.build.reportsDir>

</systemPropertyVariables>

</configuration>

</plugin>

<plugin>

<groupId>org.codehaus.gmaven</groupId>

<artifactId>gmaven-plugin</artifactId>

<version>1.4</version>

<configuration>

<providerSelection>1.8</providerSelection>

</configuration>

<executions>

<execution>

<goals>

<goal>testCompile</goal>

</goals>

</execution>

</executions>

<dependencies>

<dependency>

<groupId>org.codehaus.gmaven.runtime</groupId>

<artifactId>gmaven-runtime-1.8</artifactId>

<version>1.4</version>

<exclusions>

<exclusion>

<groupId>org.codehaus.groovy</groupId>

<artifactId>groovy-all</artifactId>

</exclusion>

</exclusions>

</dependency>

<dependency>

<groupId>org.codehaus.groovy</groupId>

<artifactId>groovy-all</artifactId>

<version>1.8.6</version>

</dependency>

<dependency>

<groupId>org.spockframework</groupId>

<artifactId>spock-core</artifactId>

<version>0.7-groovy-1.8</version>

<exclusions>

<exclusion>

<groupId>org.codehaus.groovy</groupId>

<artifactId>groovy-all</artifactId>

</exclusion>

</exclusions>

</dependency>

</dependencies>

</plugin>

</plugins>

When using Geb, a GebConfig.groovy file is requrired to be on your classpath. The best location is to put it in a recognizable location e.g. test/functional. In this file you configure your WebDriver (e.g. Firefox, Chrome etc) and the profile settings for this driver e.g. download folders, proxy settings etc.

1

2

3

4

5

6

7

import org.openqa.selenium.firefox.FirefoxDriver

import org.openqa.selenium.firefox.FirefoxProfile

driver={

FirefoxProfile profile=newFirefoxProfile()

newFirefoxDriver(profile)

}

Our test class will do a simple check to verify if there is a working link with the text ‘JDriven’ on the JDriven website which refers to the homepage.

1

2

3

4

5

6

7

8

9

10

classJDrivenBlogSpecextendsGebReportingSpec{

def"Check if there main link refers to homepage"(){

go"http://www.jdriven.nl"

$('a',text:contains('JDriven')).click()

expect:

driver.currentUrl=="http://www.jdriven.nl/home"

}

}

We extend our test class from GebReportingSpec. You can also extend from GebSpec but GebReportingSpec will automatically create a screenshot if your test fails, which is more convenient

Please note that you need Firefox to be installed if you want to run the test. When you execute the following Maven command from the command line, the tests will run.

Since version 2.2 Grails, has better support for managing namespace configuration. This helps to prevent common namespace problems. For example most applications which have security functionality, have for example a UserDetailService which can conflict when you have the Grails SpringSecurity plugin installed. Grails version 2.2. and later comes with four useful techniques to make sure the right class is used

Aliases for Services

If Grails does not find an existing service with a similar name, Grails will automatically generate an alias for you service with the name of the plugin prefix. For example when you have a plugin called UserUtilities and a service called UserDetailService, you can use UserUtilitiesUserDetailService for dependency injection which will not conflict with the SpringSecurity UserDetailService

GORM Table prefixes for domain classes

When you have the grails.gorm.table.prefix.enabled set to true in you Config.groovy, Grails will use the plugin name as prefix for your database table. E.g. if you have a domain User in the UserUtilities plugin, the table name will become USER_UTILITIES_USER.

More specific URL mapping

The UrlMappings.groovy file has now a plugin attribute to specify a specific plugin

1

2

3

4

5

6

7

staticmappings={

"/userDetails"{

controller='userDetails'

plugin='userDetailsUtilities'

}

}

Plugin parameter for GSP controller tags

You now can add a plugin attribute to the link tag to specify the controller of a specific plugin

Grails is built on Groovy which is known as a dynamic language. The dynamic nature of Groovy offers a lot of powerful features but also defers the detection of errors from compile time to runtime. To shorten the feedback cycle for your code Groovy has a handy annotation which will make sure that your classes is are statically compiled. This will give you fast feedback for a lot of mistakes and you also will benefit from the increased performance offered by the static complication.
Unfortunately in Grails this annotation prevents you from using the very useful dynamic GORM methods like list(), get() and the dynamic finder methods. Groovy does not recognize these Grails methods during compile time; see the example below.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

@CompileStatic

classBookController(){

def save(){

//This will successfully compile

}

def get(){

Book.findByName(params.name)

//this will throw a compile error since the findByName method is not known

//at compile time

}

@CompileStatic(TypeCheckingMode.SKIP)

def delete(){

//by setting the TypeCheckinMode, this method will be skipped

}

}

Grails version 2.4 comes with a new annotation called @GrailsCompileStatic. This annotation is able to recognize specific Grails code constructs and will make sure they will be accessed in a dynamic way.

One of the handy features of Groovy is to change the behavior of classes using MOP (Meta-Object Protocol). We change the metaClass property of a class to alter an implementation. You can for example override a static method of a class. See the example below:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

classUserSpecextendsSpecification{

def“test user”(){

given:

// we can mock static methods...

User.metaClass.static.findByName={name->

newUser(name:‘Albert’)}

when:

User user=User.findByName(‘Albert’)

then:

user.name==‘Albert’

when:

// .. but also non-static methods

user.metaClass.getName={return‘Dries’}

then:

user.name==‘Dries’

}

}

However this way of mocking has a nasty side effect. Since we apply changes on the User on class level, the changes are also applied in all our other test cases. This can have some unexpected behavior in your other tests

To prevent this Spock has introduced the @ConfineMetaClassChanges annotation. This annotation makes sure the class will return to its original state when it was used in our test.

See the example below:

1

2

3

4

@ConfineMetaClassChanges([User])// you can add multiple classes in the annotation

classUserSpecextendsSpecification{

...

}

Be aware: this means when some other test did changes to the User class without using @ConfineMetaClassChanges, these changes will be still applicable when the test which has @ConfineMetaClassChanges restores the User class to its old state.

Since version 2.3, Grails supports asynchronous parallel programming to support modern multiple core hardware. Therefore a new Grails command is added to generate asynchronous controllers for domain classes. The generated controller contains CRUD actions for a given domain class. In the example below, we will generate a default asynchronous implementation of a Grails controller. Continue reading →

Since version 2.3 Grails has excellent support for creating REST APIs. This new support comes with some new console commands. Besides the well known generate-controller command, Grails now comes with a new command which let you generate restful controllers for a given domain class.

In the following example, we will create a restful controller using the new generate-restful-controller command.

First we create a domain object

1

$grails create-domain-classgrails.data.Movie

Second we will generate the REST controller using the new command:

1

$grails generate-restful-controller grails.data.Movie

This command will generate a restful controller with the name MovieController with a default REST implementation. Notable is that this generated controller does not extend RestfulController<T> but gives you a full implementation of the REST functionality inside the actions.

Below you can see for example the default implementation of the index method of the generated restful controller.

Java

1

2

3

4

def index(Integermax){

params.max=Math.min(max?:10,100)

respond Movie.list(params),[status:OK]

}

Furthermore this command will generate the REST responseType settings so both JSON and XML formats are supported.

Mockito is a mock framework which you can use to write simple and clean tests. One of it’s nice features is the ArgumentMatcher. With the ArgumentMatcher you can determine the outcome of your mocked service or repository based on any condition you want.

Imagine we have a CandyService which can get a list of candies which are liked by a specific customer. This service uses the external ChocalateService which specifically checks if the customer likes chocolate. Continue reading →