I have a Maven project which executes integration tests for another web-application. This application is deployed and started within a tomcat container.
The configuration for this is done in the “cargo-maven2-plugin”:
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<configuration>
<wait>false</wait>
<configuration>
<type>standalone</type>
<properties>
<cargo.hostname>${itest.hostname}</cargo.hostname>
<cargo.protocol>${itest.protocol}</cargo.protocol>
<cargo.servlet.port>${itest.port}</cargo.servlet.port>
<cargo.servlet.uriencoding>UTF-8</cargo.servlet.uriencoding>
<cargo.jvmargs>-Xmx1024m</cargo.jvmargs>
</properties>
</configuration>
<container>
<containerId>tomcat6x</containerId>
<home>${TEST_TOMCAT_HOME}</home>
</container>
<deployer>
<deployables>
<deployable>
<groupId>de.apllicationundertest</groupId>
<artifactId>apllicationundertest</artifactId>
<type>war</type>
<!--
This will test if the app is ready an throw an exception if
the integration tests start before deployment is finished
-->
<pingURL>${itest.protocol}://${itest.hostname}:${itest.port}/${itest.web.context}/main.html
</pingURL>
<pingTimeout>120000</pingTimeout>
<!-- Setting our context for the integration tests -->
<properties>
<context>${itest.web.context}</context>
</properties>
</deployable>
</deployables>
</deployer>
</configuration>
<executions>
<execution>
<id>start-container</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
<goal>deploy</goal>
</goals>
</execution>
<execution>
<id>stop-container</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
The (web-)apllication under tests is integrated as a dependency in the pom.xml of my integration test project, so I have no absolute or relative path to the war.
My problem is that I can't control the tomcat container during the runtime of my program. Though my test scenario requires the stopping and restarting of the container (and the redeployment of the apllication under test) between some tests, f.e. for checking if there are still some active Threads after the stopping of the container or if there are still some elements of my apllication in the cache,...
I want to configure the starting and stopping of the container outside java, preferably in the pom.xml. Is that possible?
Can I specify that certain unit tests require a restarting and execute that? How?
I don't think it is possible since starting container is done in pre-integration-test phase. Why specyfic tests need to be run in restarted server? If it is possible try rewrite your test (do cleanup).
I want to configure the starting and stopping of the container outside java, preferably in the pom.xml. Is that possible?
If you need this hardly you can try put configuration for separate tests in dedicated profiles. Each profile will contain configuration of cargo and surefire/failsafe plugins.
Can I specify that certain unit tests require a restarting and execute that? How?
You can specify what test should be run. Look at surefire/failsafe plugin configuration
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.5</version>
<configuration>
<includes>
<include>Sample.java</include>
</includes>
</configuration>
<executions>
<execution>
<id>integration-test</id>
<phase>integration-test</phase>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
<execution>
<id>verify</id>
<phase>verify</phase>
<goals>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
I want to configure the starting and stopping of the container outside java, preferably in the pom.xml. Is that possible?
What you can do from Maven is what you are currently doing: starting and stoping cargo during the pre-integration-test and post-integration-test phases respectively.
Can I specify that certain unit tests require a restarting and execute that? How?
No, this is not possible. Maven doesn't have this granularity and doesn't give you any hooks for that. If this is really what you need, you have two options:
Control the container from Java like I described in this previous answer.
Put the tests in separate maven modules (so that maven will start and stop your container for each).
Related
i am using javemelody to monitor performance of my app. i am using jetty maven plugin which starts up during mvn install and runs all test cases before generating the war. i wanted to generate a pdf report at the end of post-integration-test phase.
<execution>
<id>stop-jetty</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
i was thinking if i can access the report url of embedded jetty to access javamelody, then maybe i can download my report to some location like using
curl localserver/context/monitoring?reports=pdf
is it possible to execute a custom script/java program in the post-integration-test phase before shutting down the embedded jetty ?
I would suggest to start jetty in the pre-integration-test phase do what ever you need to do in the integration-test phase and shutdown in post-integration phase.
Everything you need to do can be run via an integration test by the usage of the maven-failsafe-plugin.
<project>
[...]
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.16</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
[...]
</project>
with the above setup you can simply write an integration test for example WhatEverINeedToDoIT.java in src/test/java location and run it.
I am writing a multi-module application. Some of the modules are just basic Java libraries which are then included in the WAR of a webapp.
I would like to run code coverage in the following scenario:
I am running the webapp through an embedded Jetty that is started via Maven.
I have tests which are executing HTTP requests against the webapp.
I would like to get code covered in the webapp and also by the tests.
Is this possible and how can it be achieved with Cobertura, JaCoCo or Emma? From what I understand, the code coverage will only cover the client-side code in this scenario. Am I correct?
I think if you would manage to attach the JaCoCo-agent to the jvm that runs the jetty, it should be able to measure which code has been called over the time you run the integration tests against your webapp. So you should get a statistic that shows you the code coverage.
There is a JaCoCo Maven Plugin - though I'm not sure if this will help with you scenario. Just used it during unit tests.
Edit: found a blog-post that seems to point in the right direction here
Measure Code Coverage by Integration Tests with Sonar
Here's how I achieved it
Assuming you already have a minimal pom.xml config:
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</
<version>0.7.4.201502262128</vers
</plugin>
Download JaCoCo's agent and copy jacocoagent.jar to a suitable location (e.g. $HOME/tools/jacocoagent0.7.4.jar)
Attach JaCoCo's agent to Maven's JVM via:
export MAVEN_OPTS="$MAVEN_OPTS \
-javaagent:$HOME/tools/jacocoagent0.7.4.jar=output=tcpserver,port=6300"
Run your application with embedded jetty server e.g. mvn jetty:run
Run your integration tests
In another shell, dump and report via mvn jacoco:dump jacoco:report
Open your report on ./target/site/index.html (by default)
You can use Jacoco plugin to generate code coverage Here is the plugin configuration I used for junit test code coverage.
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.5.10.201208310627</version>
<configuration>
<skip>${maven.test.skip}</skip>
<output>file</output>
<append>true</append>
</configuration>
<executions>
<execution>
<id>jacoco-initialize</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>jacoco-site</id>
<phase>verify</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
Note: you may get life cycle not covered error in maven while using eclipse, one way is you explicitly mention the life cycle using plugin management. I installed the jacoco plugin from the market place which resolved my problem
We had a similar scenario where integration test were run on a jetty server. Also we needed a combined report for all the tests unit and integration. The solution we implemented was to run-forked jetty and pass the jvmargs with the jacoco javaagent details. Our code coverage reports covered all the rest api's and the service layer java code.
The pom config for jacoco
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco-maven-plugin.version}</version>
<configuration>
<append>true</append>
</configuration>
<executions>
<execution>
<id>prepare-test</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<destFile>${project.build.directory}/jacoco.exec</destFile>
<propertyName>surefireArgLine</propertyName>
</configuration>
</execution>
<execution>
<id>prepare-integration</id>
<goals>
<goal>prepare-agent-integration</goal>
</goals>
<configuration>
<destFile>${project.build.directory}/jacoco.exec</destFile>
<propertyName>failsafeArgLine</propertyName>
</configuration>
</execution>
</executions>
</plugin>
With the above config we generated a common exec file for both unit and integration test. Next we configured jetty to run-forked
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>${jetty-maven-plugin.version}</version>
<configuration>
<stopKey>foo</stopKey>
<stopPort>9999</stopPort>
<webApp>
<contextPath>/myway</contextPath>
<descriptor>src/main/webapp/WEB-INF/web.xml</descriptor>
</webApp>
<!-- passing the jacoco plugin as a jvmarg -->
<jvmArgs>${failsafeArgLine}</jvmArgs>
</configuration>
<executions>
<execution>
<id>start-jetty</id>
<phase>pre-integration-test</phase>
<configuration>
<daemon>true</daemon>
<waitForChild>false</waitForChild>
</configuration>
<goals>
<goal>run-forked</goal>
</goals>
</execution>
<execution>
<id>stop-jetty</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
This would launch jetty in a separate jvm with the jvmargs. Finally we generated the report in the reporting tag of the pom. We noticed that adding the report to the build plugins did not capture the integration tests run by the jetty.
<reporting>
</plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco-maven-plugin.version}</version>
<reportSets>
<reportSet>
<id>jacoco-report</id>
<reports>
<report>report</report>
</reports>
</reportSet>
</reportSets>
</plugin>
</plugins>
</reporting>
The reports can be accessed at target/site/jacoco/index.html, alternately you can run it from the command line.
mvn jacoco:report
Hope it helps.
I'm trying to start and stop hsqldb using maven.
I want to start hsqldb server with a specific configuration (database) before the test phase and stop it afterwards and doo the same with an other configuration before and after application starts.
At the moment I start hsqldb with the maven exec plugin but the problem is that the server startup is blocking the complete maven build process (Hit CTRL+C to stop the server.)
Also there is no solution for stopping the server automatically.
Best regards
Hemeroc
check my hsqldb maven plugin :
https://github.com/avianey/hsqldb-maven-plugin
You can just start/stop it like jetty-maven-plugin or tomee-maven-plugin :
<plugin>
<!-- current version -->
<groupId>fr.avianey.mojo</groupId>
<artifactId>hsqldb-maven-plugin</artifactId>
<version>1.0.0</version>
<!--
default value for in memory jdbc:hsqldb:hsql://localhost/xdb
override only values you want to change
-->
<configuration>
<driver>org.hsqldb.jdbcDriver</driver>
<path>mem:test</path>
<address>localhost</address>
<name>xdb</name>
<username>sa</username>
<password></password>
<validationQuery>SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS</validationQuery>
</configuration>
<!-- call start and stop -->
<executions>
<execution>
<id>start-hsqldb</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
</execution>
<execution>
<id>stop-hsqldb</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
I've setup Cargo to start an instance of glassfish during the pre-integration-test phase in a maven profile. My tests are then run in the integration-test phase and, finally, cargo shuts down the tomcat instance in the post-integration-test phases.
This works great when all tests pass, but if any test fails, the maven build fails, and it appears that the post-integration-test phase is never reached, which leaves the glassfish instance running (and me unable to stop it without killing the process).
Am I doing something wrong? Is there a way to make sure cargo shuts down my glassfish instance, even if the integration-test phase fails?
My maven profile:
<profile>
<!-- run integration tests against the app deployed to a container -->
<id>integration</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<!-- override the exclusion and include integration tests -->
<excludes>
<exclude>none</exclude>
</excludes>
<includes>
<include>***IntegrationTest.java</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<version>${cargo.plugin.version}</version>
<executions>
<execution>
<id>start-server</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
</execution>
<execution>
<id>stop-server</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
<configuration>
<container>
<containerId>glassfish3x</containerId>
<artifactInstaller>
<groupId>org.glassfish.main.distributions</groupId>
<artifactId>glassfish</artifactId>
<version>${glassfish.version}</version>
</artifactInstaller>
</container>
<configuration>
<properties>
<cargo.datasource.datasource.mysql>
cargo.datasource.jndi=jdbc/TrackerPool|
cargo.datasource.driver=com.mysql.jdbc.Driver|
cargo.datasource.url=jdbc:mysql://localhost/[database]|
cargo.datasource.transactionsupport=LOCAL_TRANSACTION|
cargo.datasource.username=[username]|
cargo.datasource.password=[password]
</cargo.datasource.datasource.mysql>
</properties>
</configuration>
</configuration>
</plugin>
</plugins>
</build>
</profile>
The problem is simply based in the wrong usage of the maven-surefire-plugin which is intended for using in relation with unit test but not for integration tests. For such purposes the maven-failsave-plugin exist which will solve your problem.
The usage of the maven-failsave-plugin release you from defining of include rule for integration tests. The usual naming convention in Maven for integration tests is like this:
IT*.java
*IT.java
*ITCase.java
So i would suggest to name your integration tests accordingly so you don't need any kind of exlude/include rule neither for maven-surefire-plugin (unit tests) nor for maven-failsafe-plugin (integration tests).
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.13</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
The verify goal is only needed if you like to fail your build in case of failing integration tests. You have to call maven like this:
mvn -Pprofile clean verify
I want completely automated integration testing for a Maven project. The integration tests require that an external (platform-dependent) program is started before running. Ideally, the external program would be killed after the unit tests are finished, but is not necessary.
Is there a Maven plugin to accomplish this? Other ideas?
You could use the antrun plugin. Inside you would use ant's exec apply task.
Something like this.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.2</version>
<executions>
<execution>
<phase> <!-- a lifecycle phase --> </phase>
<configuration>
<tasks>
<apply os="unix" executable="cmd">
<arg value="/c"/>
<arg value="ant.bat"/>
<arg value="-p"/>
</apply>
<apply os="windows" executable="cmd.exe">
<arg value="/c"/>
<arg value="ant.bat"/>
<arg value="-p"/>
</apply>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
Ant support os specific commands of course through the condition task.
The cargo maven plugin is a good way to go if you're doing servlet development and want to deploy the resulting WAR for integration testing.
When I do this myself, I often set up a multi-module project (although that's not strictly nessecarily) and encapsulate all the integration testing into that one module. I then enable the module with profiles (or not) so that it's not blocking the immediate "yeah, I know I broke it" builds.
Here's the pom from that functional test module - make of it what you will:
<?xml version="1.0"?><project>
<parent>
<artifactId>maven-example</artifactId>
<groupId>com.jheck</groupId>
<version>1.5.0.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.jheck.example</groupId>
<artifactId>functional-test</artifactId>
<name>Example Functional Test</name>
<packaging>pom</packaging>
<dependencies>
<dependency>
<groupId>com.jheck.example</groupId>
<artifactId>example-war</artifactId>
<type>war</type>
<scope>provided</scope>
<version>LATEST</version>
</dependency>
<dependency>
<groupId>httpunit</groupId>
<artifactId>httpunit</artifactId>
<version>1.6.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<version>0.3</version>
<configuration>
<wait>false</wait> <!-- don't pause on launching tomcat... -->
<container>
<containerId>tomcat5x</containerId>
<log>${project.build.directory}/cargo.log</log>
<zipUrlInstaller>
<!--
<url>http://www.apache.org/dist/tomcat/tomcat-5/v5.0.30/bin/jakarta-tomcat-5.0.30.zip</url>
-->
<!-- better be using Java 1.5... -->
<url>http://www.apache.org/dist/tomcat/tomcat-5/v5.5.26/bin/apache-tomcat-5.5.26.zip</url>
<installDir>${installDir}</installDir>
</zipUrlInstaller>
</container>
<configuration>
<!-- where the running instance will be deployed for testing -->
<home>${project.build.directory}/tomcat5x/container</home>
</configuration>
</configuration>
<executions>
<execution>
<id>start-container</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
<goal>deploy</goal>
</goals>
<configuration>
<deployer>
<deployables>
<deployable>
<groupId>com.jheck.example</groupId>
<artifactId>example-war</artifactId>
<type>war</type>
<!-- <properties>
<plan>${basedir}/src/deployment/geronima.plan.xml</plan>
</properties> -->
<pingURL>http://localhost:8080/example-war</pingURL>
</deployable>
</deployables>
</deployer>
</configuration>
</execution>
<execution>
<id>stop-container</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
I'm currently working on a more specific plugin that could easily be "degraded" to be a simple external task executer but ... there are quite a few other things to consider.
How do you know the process has actually started?
What do you do with the return code?
How do you make sure the executor plugin runs first (bind it to the test-compile phase)?
I'm sure there would be more if I actually started developing the plugin, but is there really a need for a generic executer?
UPDATE:
I guess there is ... there's an excellent set of Maven plugins at CodeHaus. Here's the one you want: http://mojohaus.org/exec-maven-plugin/.
You probably want to bind your actual integration tests to the integration-test phase of the maven lifecycle. If you use a plugin that fails safe (like the aptly named failsafe plugin) to do the actual testing, you can then run your phases like this:
pre-integration-test: start external application (using the exec plugin or one of the other suggestions here)
integration-test: Run the actual integration tests using the failsafe plugin
post-integration-test: Shut down the external application and do any other necessary cleanup
verify: Have the failsafe plugin verify the results of the test and fail the build at this point
It's fairly straightforward to use the exec plugin, the trick is to get your application started up in the background. You should be careful to make sure that the app is fully up before starting the tests in the next phase. Unfortunately, getting your application up and making sure it's up enough while running in the background is not always a trivial task, and the specifics of how to do that depend on your application. It often involves custom code in the application.
Do you want to start an application server ? Have a look at Cargo and its Maven plugin.