Maven Surefire’s basedir changes “randomly”

Lately I encountered a seemingly strange behaviour when running unit-tests with Maven’s Surefire-Plugin.

A little background…

These unit-tests are somewhat special, as they do not only test something but also generate content which should be included in the packaged artifact. Therefore they are writing this content directly in the module’s target folder.

Usually you do have a problem of knowing where this target folder exactly is, because the source code is (and mostly shouldn’t) be aware of that. Though in my special case it made sense. Luckily there is this convenient system-property set by surefire called basedir, which points to the module’s location.

Assume a test method looking like this…

Usually, this will print the directory to each module when run with mvn clean test .

Let’s assume a more complex multi-module project setup. Also running with the above this will print the expected results.

However, with a huge multi-module setup your build might take longer than you would like… How might one solve that problem? Sure.. let’s increase the worker threads. Which results in a slightly modified command.  mvn clean install -T 3

Yet again running the above command, still prints the expected output locations…

Basically the above scenario is the one the project I’m working on used.. or so I thought.

I expected my tests to output the correct location for each module and for a while it worked quite well and the content were correctly generated.

Yet the other day someone told me that the content does not exist anymore. After quickly looking at the build, he was right. The content wasn’t generated.

Ok, now to the tricky part…

After analysing the behaviour I concluded that, the content WAS indeed generated, though not in the directory I expected. Due to the fact, that basedir didn’t point to the module’s directory, but rather to a completely different one. This behaviour was reproducible, yet even the wrong directory changed from build to build.

What happened here?

After reviewing some of the more recent changes to the project setup I found something interesting… someone changed surefire’s configuration. One configuration was especially interesting.

By default surefire uses one fork to run the tests. Someone altered this behaviour by reducing the forkCount to 0.

After removing this particular line, the build seemed stable again and the content was generated properly.

How does the forkCount affect the basedir property?

By itself, the forkCount doesn’t affect the basedir property at all. Yet in combination with the multiple builder threads the situation completely changes.

Running multiple builder threads ( mvn clean test -T 3 ) in combination with forkCount set to 0 leads to a race condition between each thread trying to set the same system-property and therefore overriding each other.

Normally this race condition wouldn’t occur because surefire runs in its own fork and therefore the system-properties wouldn’t interfere with each other, but this behaviour was altered and therefore all threads (including surefire) share the same system-properties.

How to fix it?

For us, this was fixed by removing the forkCount property and resolved the cause for this property’s introduction.

This behaviour is correct from a technical point of view, yet I was unable to find any documentation about this behaviour. Therefore I opened SUREFIRE-1301, so others might find this more easily.

Let me know what you think about this…

Best wishes.

 

Leave a Reply

Your email address will not be published.