When Diffblue Cover creates tests, it must be able to execute your code in a similar way to unit tests you’d write yourself. Your code must both compile and run successfully, otherwise Diffblue Cover won’t be able to write tests.
Anything other than a complete build from the root is often insufficient for complex build configurations that may require installing jar artifacts into your local repository. This is a common problem we see at Diffblue and you might not even be aware of it.
So the first thing to try is compiling your entire project from its root before using Diffblue Cover. If that doesn’t work you likely have an error in your build dependencies – read on for more.
What’s the underlying problem?
Being able to execute your unit tests means that all class files that are produced by compilation of your project must be available. Furthermore all the dependencies (other modules in your project and jar files) are needed. Those are typically downloaded by your build system (e.g., Maven or Gradle). Jar files contain class files and may, in turn, depend on other jar files. Your build system computes the full dependency tree and ensures that all the jar files are downloaded.
Strictly speaking you also need the Java Class Library provided with your JDK, though that usually isn’t an issue as Cover will figure out your JDK version and find the appropriate classes.
Sometimes you might succeed in compiling your code, but when you run your application or your tests you get an error that a class was not found. This happens when dependencies are missing that were not necessary for compilation, but they are still required for execution.
Class not found errors indicate that the project wasn’t compiled correctly and/or that something is wrong or missing in your build configuration (e.g. pom.xml) or Java environment. In these situations Diffblue Cover won’t be able to run the unit tests it writes and complain that a class cannot be loaded successfully.
Fixing build and compilation problems
First, ensure that you have compiled multi-module projects from the root, using a command such as
$ mvn clean install -DskipTests
Even though you have to run Diffblue dcover
from within the module you want to create tests for, you have to run the compilation command from the root of your project, not from within a module.
Let’s see this in an example. Consider the multi-module Maven project JDMN. We first download the project and switch to the release 3.10.0:
$ git clone https://github.com/goldmansachs/jdmn
$ cd jdmn
$ git checkout 3.10.0
We should now run mvn clean install -DskipTests
, but to illustrate compilation problems let’s try to simply mvn compile
first:
$ mvn compile
$ cd dmn-tck-it
$ mvn clean install -DskipTests
Compilation apparently succeeds, but this can hide other problems. It only works because all the required dependencies were downloaded by Maven from the central repository. One of these dependencies was dmn-core
, a module provided by the same project. But the version of that module that Maven downloaded may not correspond to the code we have in the local module dmn-core
. Note that dmn-core
has not even been compiled:
$ ls ../dmn-core/target
ls: ../dmn-core/target: No such file or directory
This could be a problem if we have, for instance, made changes to dmn-core
and expect the code in dmn-tck-it
to exercise those changes.
We have to go back to the project root and run mvn clean install -DskipTests
from there:
$ cd ..
$ mvn clean install -DskipTests
You can now change directory into the module that you would like to create tests for and run dcover create
.
If this still does not work, then you have to inspect your build configuration.
Finding errors in your build configuration
Typical problems arise from system scope dependencies and exclusions. System scope dependencies are sometimes used to bake commonly used dependencies into a prepared environment (e.g. server or CI image). So it could happen that these dependencies are not installed in your local environment.
The solution is to ensure that your local environment conforms to the runtime environment on your servers or CI system. Exclusions specify that certain transitive dependencies should be excluded from your classpaths. It can happen that such an exclusion is incorrect and classes are excluded that are actually needed. The solution in this case is to find the faulty exclusion and fix your build configuration.