Just Use My Testing Infrastructure
I use the Maven dependency ecosystem to provide code dependencies to my students via a Maven repository hosted on my group’s artifact page. This gives students access to my code, allows them to conveniently view the corresponding source, allows me to quickly distribute updates, and forces me to more cleanly separate my code.
Since I usually insist on automated tests, I repeatedly find myself with testing infrastructure code that I want to distribute alongsite the respective production code from some module, say foo
. There’s several ways to achieve this:
- I could simply include the testing code with the production code, such that it would be available from
foo
itself. However, this would force me to turn testing dependencies, such ashamcrest
, into production dependencies, which I consider a no-go. - I could create a second Maven module
foo-test
alongside the production modulefoo
and move all the testing code there. This would allow others to depend onfoo-test
in thetest
scope, which resolves the dependency issue. However, sincefoo-test
usually depends onfoo
and I cannot (and don’t want to) declare cyclic dependencies, I cannot use the testing infrastructure infoo-test
to write tests infoo
. Therefore, I have to write the tests forfoo
infoo-test
, which I find counter-intuitive. Moreover, it breaks code coverage measurement, because this happens module-wise in Maven, such that running the tests infoo-test
does not add to the coverage of the code infoo
. - I could just use Maven to solve the problem for me. Turns out this is actually quite simple, using the
maven-jar-plugin
. This gives me a clean separation of testing and production dependencies and allows the respective code to reside in the conventional locations, at the same time.
To provide all the test code from foo
in addition to its production code when I deploy the module, I simply insert the following configuration in the module’s pom.xml
:
Running maven package
will now create an artifact called foo-0.0.1-SNAPSHOT-tests.jar
, which contains all the test code and declares the respective production and test dependencies in its pom.xml
. This artifact gets deployed alongside the main artifact.
To depend on foo
and its testing code in another module or project, I insert the following dependency in the respective module’s pom.xml
:
Note that I declare two dependencies, one on the production code and one on the test code, each with the respective scope. By setting the dependency type
to test-jar
, Maven knows to look for an artifact generated by the test-jar
goal, as configured above. The default value for type
is jar
, which corresponds to the respective module’s main artifact (production code).
And that’s it. Problem solved.
I try to make it easy for my students to use my code. This includes testing infrastructure. Why should they reinvent the wheel? Like all of us, they are more likely to write tests, the easier it is for them to actually do so. No excuses ;)