/ fitnesse

FitNesse with Maven and Jenkins

I needed to automate FitNesse tests in my clients build process. I also needed the test cases in Git so that testers can develop tests in the same feature branches as the developers are using.

I was looking for a simple way of doing that in a Java project where Maven and Jenkins is being used. I did not find any acceptable solutiion, here is my solution.

What I Found

I found Running from Junit in the official documentation. But I was unable to use it.

  • That API looks strange and it is unclear how to use it.
  • I could not find any API for specifying where the jar files, with the service under test, are on the filesystem. When digging into the code on GitHub I concluded that there are no such feature.

I found the Jenkins Plugin but I wanted testers to be able to work with the test cases locally. That plugin would only, potentially, solve it in Jenkins. There is also Xebia but same problem there.

What I Did

I created a pom that uses antrun to basically just run the java program with command line arguments. The version of FitNesse is managed in the pom.

The wiki pages have:

!define TEST_SYSTEM {slim}
!path target/dependencies/*.jar

Here is the pom.xml.

<?xml version="1.0" encoding="UTF-8"?>
<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>

 <artifactId>bjurr-fitnesse</artifactId>

 <dependencies>
  <dependency>
   <groupId>org.fitnesse</groupId>
   <artifactId>fitnesse</artifactId>
   <version>20161106</version>
   <scope>test</scope>
  </dependency>
 </dependencies>

 <properties>
  <fitnesse.command></fitnesse.command>
 </properties>

 <build>
  <plugins>
   <plugin>
    <artifactId>maven-antrun-plugin</artifactId>
    <version>1.3</version>
    <executions>
     <execution>
      <id>start-fitnesse</id>
      <phase>test</phase>
      <configuration>
       <tasks>
        <copy todir="target/dependencies" flatten="true">
         <fileset dir="../">
          <include name="**/*.jar" />
         </fileset>
        </copy>
        <echo message="" />
        <echo message="" />
        <echo message="Fitnesse wiki available here:" />
        <echo message="" />
        <echo message="  http://localhost:8888/MyTests.MySuite" />
        <echo message="" />
        <echo message="" />
        <java classname="fitnesseMain.FitNesseMain" classpathref="maven.test.classpath"
         fork="true">
         <arg line="-p 8888" />
         <arg line="-d ." />
         <arg line="-e 9999" />
         <arg line="-b target/fitnesse-junit.xml" />
         <arg line="${fitnesse.command}" />
         <jvmarg value="-Xmx1024m" />
        </java>
       </tasks>
      </configuration>
      <goals>
       <goal>run</goal>
      </goals>
     </execution>
    </executions>
   </plugin>
  </plugins>
 </build>
</project>

To start the wiki to work with the test cases I do:
mvn test
And that will start the FitNesse wiki on localhost.

When tests change, the changed wiki pages are committet and pushed to the remote repo.

To run all the tests I do:
mvn test -Dfitnesse.command="-c MyTests.MySuite?suite&format=junit"
And in Jenkins I use the Lockable Resources Plugin to allow IP port collision and only have one job running FitNesse at once.

A pipeline stage may look like this:

...
stage('FitNesse test') {
  lock(resource: "compiler_${env.NODE_NAME}", inversePrecedence: true) {
   try {
    sh """
     cd fitnesse
     ${mvnHome}/bin/mvn test -Dfitnesse.command=\"-c MyTests.MySuite?suite&format=junit\"
     tar -zcvf fitnesseTestResults.tar.gz FitNesseRoot/files/testResults
    """
    archiveArtifacts artifacts: 'fitnesseTestResults.tar.gz', fingerprint: true
    junit "**/fitnesse/target/*.xml"
    commentMr(env.gitlabMergeRequestId, "FitNesse ok :) $gitlabSourceBranch ${BUILD_URL}")
   } catch (e) {
    commentMr(env.gitlabMergeRequestId, "FitNesse **not ok** in $gitlabSourceBranch ${BUILD_URL}")
    junit "**/fitnesse/target/*.xml"
    throw e
   }
  }
 }
...