Posts Tagged intellij idea

Grails, Selenium, Maven and integration testing

Today I wanna share with you my experience of configuring Selenium RC (with Java client drivers), Maven, Surefire to develop and run integration tests on Grails applications. We will build Grails demo application in Intellij IDEA (with Maven project model behind) and run simple integration test written in Groovy using Selenium RC.

Creating project structure

  • Create “demo” directory in your projects dir an step inside it.
  • Create basic Grails application with Maven by running:
mvn org.apache.maven.plugins:maven-archetype-plugin:2.0-alpha-4:generate -DarchetypeGroupId=org.grails -DarchetypeArtifactId=grails-maven-archetype -DarchetypeVersion=1.0 -DgroupId=com.grailsgeek -DartifactId=maven-grails-demo

Fix Grails application pom.xml with tips I described in my previous post.

  • Create integration-test module by running:
mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DgroupId=com.grailsgeek -DartifactId=integration-test

And don’t forget to remove App and AppTest from sources that were generated by Maven.

  • You should stay in your main project dir “demo”. Create multi-module pom.xml in project root dir with following content:
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                      http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.grailsgeek</groupId>
    <version>1.0-SNAPSHOT</version>
    <artifactId>demo</artifactId>
    <packaging>pom</packaging>
    <modules>
        <module>demo-app</module>
        <module>integration-test</module>
    </modules>
</project>
  1. Now run mvn install from project root directory, and see “BUILD SUCCESSFUL” ;)

Adding necessary dependencies to maven poms

We are going to modify only <build> sections of each pom. So If you extending your existing application with integration tests you’ll need to make just few adjustments.

  • Grails application pom (our demo-app). Go to <build> -> <plugins> section and insert jetty plugin:
            <plugin>
                <groupId>org.mortbay.jetty</groupId>
                <artifactId>maven-jetty-plugin</artifactId>
                <version>6.1.10</version>
                <configuration>
                    <scanIntervalSeconds>10</scanIntervalSeconds>
                    <stopKey>foo</stopKey>
                    <stopPort>9999</stopPort>
                </configuration>
                <executions>
                    <execution>
                        <id>start-jetty</id>
                        <phase>pre-integration-test</phase>
                        <goals>
                            <goal>run-war</goal>
                        </goals>
                        <configuration>
                            <scanIntervalSeconds>0</scanIntervalSeconds>
                            <daemon>true</daemon>
                        </configuration>
                    </execution>
                    <execution>
                        <id>stop-jetty</id>
                        <phase>post-integration-test</phase>
                        <goals>
                            <goal>stop</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

We’ll use it to launch our Grails application in the “integration-test” phase. And will click with Selenium on it, but a bit later about all that.

  1. Integration tests module. I’ll post here entire pom.xml because it’s not aware about project under test, only groupId could differ.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.grailsgeek</groupId>
  <artifactId>integration-test</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>integration-test</name>
  <url>http://maven.apache.org</url>
  <dependencies>
        <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy</artifactId>
            <version>1.6.3</version>
        </dependency>

        <dependency>
            <groupId>org.seleniumhq.selenium.client-drivers</groupId>
            <artifactId>selenium-java-client-driver</artifactId>
            <version>1.0-beta-2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.groovy.maven</groupId>
                <artifactId>gmaven-plugin</artifactId>
                <executions>
                    <execution>
                        <id>test-compile</id>
                        <phase>test-compile</phase>
                        <goals>
                            <goal>generateTestStubs</goal>
                            <goal>testCompile</goal>
                        </goals>
                        <configuration>
                            <sources>
                                <fileset>
                                    <directory>${pom.basedir}/src/test</directory>
                                    <includes>
                                        <include>**/*.groovy</include>
                                    </includes>
                                </fileset>
                            </sources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>selenium-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>pre-integration-test</phase>
                        <goals>
                            <goal>start-server</goal>
                        </goals>
                        <configuration>
                            <background>true</background>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <skip>true</skip>
                </configuration>
                <executions>
                    <execution>
                        <id>surefire-it</id>
                        <phase>integration-test</phase>
                        <goals>
                            <goal>test</goal>
                        </goals>
                        <configuration>
                            <skip>false</skip>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.5</source>
                    <target>1.5</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>seleniumhq</id>
            <name>seleniumhq</name>
            <url>http://nexus.openqa.org/content/repositories/releases/</url>
        </repository>
    </repositories>
</project>

I propose to run “mvn integration-test” from project root, and see what will happen now. There are no tests yet, but Maven should resolve all dependencies and pass all execution phases. “BUILD SUCCESSFUL” means that we could go on :)

Preparing simple functionality for our tests

Import our Maven project into Intellij IDEA as I described in my previous post.

Now I’m creating domain class Message:

public class Message {
    String text
}

And controller for it:

class MessageController {
    def scaffold = true
}

That’s it, our application is ready to be tested.

Writing first Selenium test

Switch to integration-test module, and create “integration-test/test/java/com/grailsgeek/MessageTest.groovy”:

package com.grailsgeek

import com.thoughtworks.selenium.SeleneseTestCase

public class MessageTest extends SeleneseTestCase {

    public void setUp() {
        setUp "http://localhost:8080/demo-app/", "*firefox"
    }

    void testCreateMessage() {
        selenium.with {
            speed = "3000"

            open "message"
            waitPage()
            assertEquals "Message List", title

            click "//a[text()=\"New Message\"]"
            waitPage()
            assertEquals "Create Message", title

            type "text","Message Text ;)"
            click "//input[@value=\"Create\"]"
            waitPage()
            assertEquals "Show Message", title

            assertTrue isTextPresent ("Message Text ;)")
        }
    }

    private def waitPage() {
        selenium.waitForPageToLoad "30000"
    }
}

Running tests from Maven

Run “mvn integration-test” from project root directory and enjoy :). But since your project is going to grow fast (I hope so) or you already big enough, you could experience problems with out of memory error (PermGen space) due to Groovy dynamism. You could easy solve this by adding “MAVEN_OPTS=-Xmx512m -XX:MaxPermSize=256m” to your environment variables.

Running tests from Intellij IDEA

  1. Go to “Maven” context (at the right edge).
  2. Run your application “demo -> Modules -> demo-app -> Plugins -> grails -> grails:run-app” or just run IDEA grails configuration which should be already available.
  3. Run Selenium with “demo -> Modules -> integration-test -> Plugins -> selenium -> selenium:start-server”
  4. Execute your MessageTest.

Intellij IDEA allows you to save run configuration for ease of further use (selenium:start-server and grails:run-app could be saved as preconfigured). Also you there is no need to restart your application each time you made some changes. Grails will take care of it as usual.

Tags: , , , , , , , ,

Settin’ up Grails 1.1.1. with Grails Maven Plugin in Intellij IDEA + JetGroovy

Grails Maven Plugin is still non predictable and it’s 1.0 version supports only 1.1 version of Grails. 1.1-SNAPSHOT version supports grails 1.1.1 but there are still misunderstandings with Grails plugins are exist (Grails wants to store them in your user home, but  Grails Maven plugin wants them to be stored in your application dir).

As for now I’m trying to avoid using plugins from Grails, and include all libraries directly with Maven dependencies.

1. Make your maven know where to get grails-maven-plugin by editing your /.m2/settings.xml (create it if there is no one exist):

<settings>
    <pluginGroups>
        <pluginGroup>org.grails</pluginGroup>
    </pluginGroups>
</settings>

2. Go to secret place where you store you projects and run:

mvn org.apache.maven.plugins:maven-archetype-plugin:2.0-alpha-4:generate -DarchetypeGroupId=org.grails -DarchetypeArtifactId=grails-maven-archetype -DarchetypeVersion=1.0 -DgroupId=example -DartifactId=maven-grails-demo

3. Now open just generated pom.xml and make following changes:

  • change versions of grails-crud and grails-gorm from “1.1” to “1.1.1”
  • change grails-maven-plugin version from “1.0” to “1.1-SNAPSHOT”
4. Run “mvn initialize” from your project root.
5. One more trick, that should be applied for 1.1-SNAPSHOT version of grails-maven-plugin to make it work: add following dependency to your pom.xml (see http://jira.codehaus.org/browse/GRAILS-4574 for details):
<dependency>
    <groupId>org.tmatesoft.svnkit</groupId>
    <artifactId>svnkit</artifactId>
    <version>1.2.3.5521</version>
    <scope>runtime</scope>
</dependency>

6. Now, it’s time to import your maven project into Intellij IDEA (I recommend to use latest EAP http://www.jetbrains.net/confluence/display/IDEADEV/Maia+EAP). You can do it by “Create New Project → Import Project from External Model → Maven…”.

Pay attention to Facets that Idea will detect on project import finished. Hint: look in right bottom corner for round icon with “i” on it, if Idea won’t show you dialog window with detected facets. Facets detection is important to let Idea know that it’s Grails application.
Now close and reopen project again to let JetGroovy plugin use facets and treat application directories in a right way. You should see “Grails:maven-grails-demo” preselected in IDEA’s run/debug configurations combo. If it’s so – you on the right way and JetGroovy knows that it’s Grails application. If not – try to fix it in “module settings → facets”. If you didn’t make it – contact me, I’ll try to help.

You probably already tried to run application but all you’ve got was:
Exception in thread "main" java.lang.ClassNotFoundException: org.codehaus.groovy.grails.cli.support.GrailsStarter at java.net.URLClassLoader$1.run(URLClassLoader.java:200) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:188) at java.lang.ClassLoader.loadClass(ClassLoader.java:307) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) at java.lang.ClassLoader.loadClass(ClassLoader.java:252) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:169) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:87)
Don’t worry. It’s because grails-maven-plugin depends on grails-core which not contain GrailsStarter. It’s available in standalone Grails distribution. First of all you are still able to run grails application with “Maven Projects → maven-grails-demo → Plugins → grails → grails:run-app” or just by running “mvn grails:run-app” from project root. If you still want to run your application from run configuration in Idea you could or create run configuration from Maven goal, by clicking on with right button and selecting appropriate menu item or by installing standalone Grails and telling IDEA where it is.

Setting up standalone Grails for your application

  • Install Grails as described http://grails.org/Installation.
  • Go to module settings → Groovy → click “Add…” → Create new Grails SDK… → Tell Idea where your standalone Grails is → Click “Replace” (not “Add”, important) in dialog appeared
Now you able to run your Grails application directly from Idea with JetGroovy plugin. Enjoy ;)

Tags: , , , , ,