I have an application war that is instrumented via clover and deployed on tomcat on a standalone server. The project is multi-module with structure as below:
main project pom
|---module A (client related)
|---module B (rest related)
|---module C (database related)
|---module D (depends on all the above for successful compilation)
Module D is the one that generates the application WAR file and is the project that is configured for clover instrumentation. This is the main module that has most of the application logic and hence needs to be covered for per-test coverage. The plugin configuration that I have used to instrument the source is as below:
The application is a java web application launching inside tomcat, hence I have passed the below arguments to the JVM
-Dclover.distributed.coverage=host=<ip where my tests are running> \
The end-to-end tests are run from another test box which acts as clover-server. I launch my tests with the below command:
mvn clean clover:setup test -Dtest=SampleClass#sampleTestMethod -Dclover.server=true -Dmaven.clover.cloverDatabase=./clover_tests.db -Dclover.initstring=/absolute/path/to/clover_tests.db
In this configuration am unable to see per-test-coverage results for all the tests that are run. If I try another test class in the above maven command, I do get the per-test coverage correctly. Visibly, there are no striking differences between the two test classes and they seem to test similar areas of the product.
Most of the product code where a hit is expected shows "No tests hitting this source file were found". All executed test cases do show up as executed only under "Test Code" tab. Since some of the tests do show up, am wondering anything wrong with my setup or configuration.
NOTE: During test code instrumentation, I do see the below warning multiple times. Not sure if it is related to the issue am facing, but I do not have any CLOVER:OFF statements in my test code:
[WARNING] Trying to add a statement but current method is null. Did you put CLOVER:OFF before a method signature and CLOVER:ON inside a method body?
Any thoughts on what I could be missing?
First, please verify if your tests are set up correctly:
1. Check if all your tests classes have been instrumented. If they were, you shall see them in the HTML report on the 'Test code' tab. If not - check inclusion/exclusion patterns, check if Clover was set up for given module, check if instrumentation was executed before compilation etc.
2. Check if global code coverage have been recorded for test classes. In the HTML report they have green highlight in their source code. If not - check if clover.db file was accessible at test execution time (there shall be warnings in the console), check if you really executed instrumented classes and not the normal ones (e.g. 'clover:setup test clean test' would wipe-out instrumented code and re-run tests for normal code).
3. Check if per-test code coverage have been recorded for test classes. In the HTML report if you click on a test method (left margin with line numbers) you shall see "Line was covered by tests" dialog, i.e. test should cover itself. If you don't see it - please check if the test framework used is supported by Clover, if not - ensure you've got correct test patterns set (Clover-for-Ant).
Next, please verify if your application under test was set up correctly:
4. Check if all your application classes have been instrumented. You shall find them on the 'Application code' tab.
5. Check if global code coverage have been recorded. Again, look at the HTML report. If not - ensure that clover.db was available at runtime. Use -Dclover.initstring or -Dclover.initstring.basedir to point to the correct location of the files.
6. Check if per-test coverage have been recorded. If it is missing for some tests - ensure that application under tests started *before* test execution. This is relevant for multi-JVM tests (e.g. tests from one JVM calling application on a web server running in another JVM). Use 'clover.distributed.coverage' and numClients parameter.
Lastly, please check if test results have been collected correctly:
7. It may happen that test errors collected by Clover (exceptions thrown from tests executed) do not match test results from TEST-*.xml files. There may be few reasons:
* JUnit test annotations (e.g. @test with excepted exception) are not recognised
* test execution and verification may be separated into different phases - it's a case for maven-failsafe-plugin - tests run in integration-test phase, validation happens in post-integration-test phase.
In such case, configure the report target (<clover-report> for Ant, clover:clover for Maven) to use test results from TEST-*.xml files.
1,2,3 were perfectly fine.
Regarding 4, there is a glitch. The application under test is built in 2 steps:
The main reason that step 1 is not instrumented (though I wanted it to be instrumented) is because the project is separately built and would have generated a separate clover.db file. Since the application is started using tomcat with exactly one WAR file, I have no way to give more that one -Dclover.initstring param during start-up. I tried giving -Dclover.initstring.basedir to point to the root where 2 clover.db files are kept, but the application failed to start stating that it cannot find clover.db file.
5,6,7 were all cross checked and they are looking fine.
Thank you for the inputs. Any suggestions for the above predicament?
If your application is being executed on the same machine where compilation is performed then it shall be no problem to have more than one clover.db file. Or more precisely - if the folder layout is the same. Instrumented classes "remember" full path to their clover.db.
It means that you can have one application using multiple clover.db files.
If folder layout is different then it shall be no problem too. What you can do is that you can share clover.db file between compilations (it can be updated by appending new instrumentation session).
So you could build your core, create clover.db file, save it as an artifact.
Next you could build rest of your application, using the clover.db artifact from the previous step. It will be updated and information about new classes added.
Next use the updated clover.db for application & test execution.
If you want to use clover.inistring.basedir, then you have to use relative paths to clover.db in your modules. E.g.
application - base dir = application
/target/clover.db - initstring=core/target/clover.db
/target/clover.db - initstring=main/target/clover.db
and then when executing tests (also on another machine):
workdir - copy clover.db files preserving relative paths
Tell what the root folder is:
I was able to now get recording files for both the core and the main applications.
But the original problem remains. For few test cases I am able to get the test code<->product code mapping in the report. For few other test cases am unable to. If the non-working test case code is copy/pasted in the test method that was working, the pasted method works correctly.
Totally clueless on why one test works while other does not. Both tests have @test annotation.
I suspect that the problem lies in the way how you create an application WAR and deploy it and how do you later execute tests against the application. Probably you run a "mvn clean" command in between and as a result you the clover.db is wiped out. Is it something like this?
mvn package # to create a WAR
scp ... # to deploy a WAR and clover.db
mvn clean clover:setup test ... # to run tests
Please try to perform entire instrumentation without a cleanup in between. So something like this:
mvn clean clover:setup package ... # to instrument app & tests and create a WAR
scp ... # to deploy a WAR and clover.db
mvn test ... # to execute tests, without clean, without recompilation
The main reason that step 1 is not instrumented (though I wanted it to be instrumented) is because the project is separately built and would have generated a separate clover.db file.
You can configure a different initstring for application and tests, e.g.:
As these have just a file name, it will be easier for you to copy them into one directory and use -Dclover.initstring.basedir parameter.
My partner and I were planning this relocation for years. It was our shared dream to try and live in another country. As children of immigrants, we already have experienced this once, but this still ...
Connect with like-minded Atlassian users at free events near you!Find an event
Connect with like-minded Atlassian users at free events near you!
Unfortunately there are no Community Events near you at the moment.Host an event
You're one step closer to meeting fellow Atlassian users at your local event. Learn more about Community Events