I have a project composed of several modules that uses maven and is automatically uploaded and deployed to a Jenkins application that runs the build and its tests.
There is for example an API module, a server and a client.
Both client and server use the API as dependency to be able to work correctly. The client connects to the server's web-services through HTTP(s) in normal use.
To be able to function, the server needs to be run on Jetty.
I have unit testing that works and test the client by calling the server's functionality with mocked HTTP requests.
I would like to be able to do some integration testing, to test for example the HTTP (and HTTPS) connection between the 2 entities, testing for timeouts and such, and reproducing the unit testing without resorting to mocked request, to be closer to real use cases.
It seems like such a thing should be easy to do, but I can't find a way to do it simply and in a way that could be automated.
For example, testing manually in my IDE is done by clicking on "run war" on the server project, and "run tests" on my application.
Is there a way to reproduce this simple process in Jenkins so it is done automatically, by Maven configuration or even a Jenkins plugin ?
UPDATE :
I'm trying to make another module that would use the war resulting from the packaging of my server, and run it with Jetty. Since my server's Jetty configuration is quite complicated, using Spring and https configuration filtered by Maven, I've some problems making it work in my new module because of missing classes and relative paths not working in that context.
Is it possible to run that war like it would have been started in the other module without jumping through hoops of duplicating resources and other dirty tricks ?
For information, the specific Jetty war part of my pom.xml is :
<configuration>
<contextHandlers>
<contextHandler implementation="org.eclipse.jetty.webapp.WebAppContext">
<war>${project.parent.basedir}/cmp-service/cmp-webapp/target/cmp-webapp-1.0-SNAPSHOT.war</war>
<contextPath>/cmp</contextPath>
<persistTempDirectory>true</persistTempDirectory>
<allowDuplicateFragmentNames>true</allowDuplicateFragmentNames>
</contextHandler>
</contextHandlers>
</configuration>
UPDATE 2 :
I managed to build a functioning module that starts jetty and run my integration test with this pom.xml.
<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">
<parent>
<artifactId>parent</artifactId>
<groupId>com.project.test</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.project.test.integration-testing</groupId>
<artifactId>integration-testing</artifactId>
<packaging>jar</packaging>
<name>integration-testing</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.3.0.M2</version>
<configuration>
<contextHandlers>
<contextHandler implementation="org.eclipse.jetty.webapp.WebAppContext">
<war>
${project.parent.basedir}/myserver/myservice/target/myservice-${project.parent.version}.war
</war>
<contextPath>/cmp</contextPath>
<persistTempDirectory>true</persistTempDirectory>
<allowDuplicateFragmentNames>true</allowDuplicateFragmentNames>
</contextHandler>
</contextHandlers>
<contextXml>
${project.parent.basedir}/myserver/myservice/src/test/resources/jetty/jetty-context.xml
</contextXml>
<jettyXml>
${project.parent.basedir}/myserver/myservice/src/test/resources/jetty/jetty.xml,${project.parent.basedir}/myserver/myservice/src/test/resources/jetty/jetty-ssl.xml,${project.parent.basedir}/myserver/myservice/src/test/resources/jetty/jetty-http.xml,${project.parent.basedir}/myserver/myservice/src/test/resources/jetty/jetty-https.xml
</jettyXml>
<systemProperties>
<systemProperty>
<name>scsf.configuration.file</name>
<value>
${project.parent.basedir}/myserver/myservice/src/main/resources/config/cmpserver.properties
</value>
</systemProperty>
<systemProperty>
<name>org.eclipse.jetty.annotations.maxWait</name>
<value>180</value>
</systemProperty>
</systemProperties>
<systemPropertiesFile>
${project.parent.basedir}/myserver/myservice/src/main/resources/config/cmpserver.properties
</systemPropertiesFile>
<daemon>true</daemon>
<stopKey>STOP</stopKey>
<stopPort>10001</stopPort>
</configuration>
<executions>
<execution>
<id>start-jetty</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
<configuration>
<scanIntervalSeconds>0</scanIntervalSeconds>
</configuration>
</execution>
<execution>
<id>stop-jetty</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.18.1</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
...
</dependencies>
</project>
You need to add the dependency to your war as provided too.
But (there's always a but) there is a problem when running the verify goal. When I run verify in my integration-test module, it kind of works. But when I run the verify goal in the parent, which is supposed to call that exact same verify goal of my integration-test module (if I understand correctly how it works), some paths are treated differently and are resolved as, for example, parent/src/... instead of parent/integration-test/src...
It seems that when running my goal from the parent, the context of the execution changes and causes my application to break when looking for resources and such.
Is there something I didn't understand about how the whole process works and is there a way to make it work ?
I've resolved to hack my way into making all my paths into absolute paths, it works, but it doesn't explain that behavior.
The simplest way to run integration tests is to use the Maven failsafe plugin. By default, the Maven surefire plugin executes unit tests during the test phase, while the failsafe plugin runs integration tests in the integration-test phase.
Integration testing is the second level of the software testing process comes after unit testing. In this testing, units or individual components of the software are tested in a group. The focus of the integration testing level is to expose defects at the time of interaction between integrated components or units.
You already figured out the basic steps yourself:
maven-failsafe-plugin:integration-test
mojomaven-failsafe-plugin:verify
mojoStephen Connolly, a maven developer, already wrote a great answer about this topic on stackoverflow.
I don't know the jetty-maven-plugin very well, but it seems it doesn't support deploying an existing artifact. Specifying relative or absolute path is definitively not the way to go here. You should probably use cargo instead to deploy to jetty. The cargo configuration could look like this:
<configuration>
<configuration>
<type>runtime</type>
<properties>
<cargo.hostname>testserver</cargo.hostname>
<cargo.servlet.port>8080</cargo.servlet.port>
</properties>
</configuration>
<container>
<containerId>jetty9x</containerId>
</container>
<deployables>
<deployable>
<groupId>your.group.id</groupId>
<artifactId>your-war</artifactId>
<type>war</type>
<properties>
<context>/cmp</context>
</properties>
</deployable>
</deployables>
<deployer>
<type>remote</type>
</deployer>
</configuration>
The cargo documentation has more details.
hth,
- martin
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With