JaCoCo plugin gives different coverage - java

I'm using the JaCoCo Maven plugin and agent to measure and retrieve the code coverage data of an application which is tested nightly.
This is the schema of the architecture:
My Maven project is configured with the JMeter Maven plugin to execute some API tests during the Maven verify phase.
The Maven command executed by the Jenkins server is the following
mvn verify org.jacoco:jacoco-maven-plugin:0.7.8:dump sonar:sonar -Djacoco.address=TEST_SERVER -Djacoco.destFile=/proj/coverage-reports/jacoco-it.exec -Dsonar.projectKey=sonar_test -Dsonar.projectName=sonar_test -Dsonar.branch=sonar_test -Dsonar.jacoco.itReportPath=/proj/coverage-reports/jacoco-it.exec -Dsonar.java.coveragePlugin=jacoco -Dsonar.language=java
As you can see first the tests are executed through the verify phase, then the jacoco:dump goal retrieves the coverage data from the test server (I configured the server to run the JaCoCo agent) and at last the data is uploaded to my Sonar server.
The "strange" behaviour I'm having is that if I run this command on my computer and then on Jenkins (configuring the Jenkins project accordingly) in the SonarQube page I get different coverage results. Moreover, if I configure the Jenkins project and then I simply COPY it creating a new (but equivalent) Jenkins project, the results are different.
I tried different configurations and cases, but I cannot understand what the problem can be. Am I not considering some JaCoCo constraints (e.g. someting related to the Jenkins project name)?

As said in the question comments, the artifact deployed on the test server and the one compiled during the verify phase on which the report is generated must be exactly the same, so it is not enough that the code is the same.
To solve my problem I had to implement this workflow with Jenkins:
Do a mvn package on the project
Deploy the generated WAR on the remote server using Ansible (we already use Ansible for nightly deploys and other tasks on remote machines)
Run the remote tests without recompiling the wars. To do this I had to add the Maven flag -Dmaven.compiler.useIncrementalCompilation=false (thanks to this and this for the hints) in order to not re-compile the artifacts during the verify phase
Retrieve (dump) the JaCoCo coverage data
So the Maven command described in the question has been split in two commands: the one which creates the package and the one which performs the tests and retrieves the JaCoCo data without recompiling the artifacts.

Related

Why system.out.println changes reflects without building jar?

I am using maven as a build tool and running some integration-test cases. I logged some statements in my test case using System.out.println() and did a mvn verify and even i didn't clean install/package the jar.The changes were reflecting for logging statements. Did the mvn verify implicitly does a install/package or it doesn't require building the jar. If any one have any idea please share.
The maven goal verify comes after package see: Maven Build Lifecycle so the packaging occurs.
See mvn build lifecycle for order (all above are used) https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html :
validate - validate the project is correct and all necessary information is available
compile - compile the source code of the project
test - test the compiled source code using a suitable unit testing framework. These tests should not require the code be packaged or deployed
package - take the compiled code and package it in its distributable format, such as a JAR.
integration-test - process and deploy the package if necessary into an environment where integration tests can be run
verify - run any checks to verify the package is valid and meets quality criteria
install - install the package into the local repository, for use as a dependency in other projects locally
deploy - done in an integration or release environment, copies the final package to the remote repository for sharing with other developers and projects.

How to do a deployment pipeline with Maven

We want to accelerate our build pipeline for a multi-module Java web application, which roughly consists of
compile/code analysis
unit tests
integration tests
GUI tests
At the moment each of these build steps starts from scratch, compiling and building again and again, which costs time and means that we do not deploy the actual files to production that have gone through the tests. Is it possible to get Maven to not recompile everything on subsequent steps but instead run the tests against the previously compiled classes?
We are using Maven3 to manage our dependencies and Teamcity as a build server (7 at the moment, planning to upgrade to 8 soon). I have tried to set up a build chain, doing a
mvn clean install
on the first step and then exporting all the */target/ folders to the following builds. Then ideally I would only do a
mvn test
mvn integration-test
Unfortunately I have not been able to persuade Maven to do this properly. Either it compiles the classes again or produces errors.
Has anyone successfully done this kind of setup and has any pointers for me? Is this possible with Maven and is this even the right way to do things?

What is the process with Maven project to compile and test the code?

I have maven project imported in my eclipse. Now I need to start making changes to it and test it with the integration test (out of App server). Currently, the integration test is run out of server using openEJB container.
My basic question is, what is the regular process to compile, build and test with Maven?
mvn install
Maven -> Update Project.
Run my test from command line
Is it how it is done? I am specifically interested in knowing mvn install commands.
So should I do all three steps before I can test it?
Example: I just wanted to print something and see what is the output. For this I guess I need to do all these steps?
The openEJB container needs classes so it can load them.
There is a wonderful Maven quick-reference sheet at http://maven.apache.org/guides/MavenQuickReferenceCard.pdf
First, you should be aware that unit tests and integration tests are separate and are run from separate plugins and at separate parts of the maven lifecycles. Unit tests are run with surefire and integration tests are run with failsafe.
You want to run integration tests and the failsafe documentation says:
NOTE: when running integration tests, you should invoke maven with the (shorter to type too)
mvn verify
rather than trying to invoke the integration-test phase directly...
This is the best way to run integration tests directly in maven. It will run all the preceding steps necessary (eg: compile) in order to run the integration tests. It won't waste time doing an install because install happens immediately after verify.
But if you're running the tests locally, it may be a better idea to run your integration tests directly in your IDE. That will give you a much faster feedback loop.
If it is Eclipse project the most reasonable thing is to do everything not from command line but from Eclipse. Assuming you have m2e plugin installed, go to your_project->run as->Maven test and run it.
You dont need neither install nor package phase to run Maven tests, package will create a jar which is not needed for tests, install will copy this jar to local repo which is also useless. When Maven run tests it uses compiled classes from target dir and ignores project's jar if even it exists.
Yes, mvn isntall is the most popular option. It compiles, packages and tests your project.

Maven/Jenkins automatic download/copy

I'm in a team to develop plugins in java.
We got Maven, a repository and Jenkins,
And I got myself a debian-server to test my applications.
When I push my commits, this happens:
Push in repository, upload and build in Jenkins.
Users download these .jar files and upload these to their server
What I want to be happen:
There are two ways,
First: After building with Jenkins: Download these files,
Second: When pressing "maven build", maven builds my applications and copy these to my server
How can I do this?
(Sorry for my bad English: I'm German)
If I understand you correctly, following scenario should help.
create two jobs
first job builds your artifact and archives it: user will be able to download it, job is triggered by source modification
second job is only executed manually (and requires two plugins, listed below), copies artifacts from first job and then uploads them to the server
Following plugins you would need to install:
copy artifact plugin to enable jenkins to copy artifacts from another job
publish over ssh plugin to enable jenkins to upload binaries and run commands on remote servers
You want when you push your SCM repository, to get Jenkins build into your local projet (update your jars), then manipulate send your final build to your server. Is that you want ?
If yes, I think that plugin would be interesting :
http://evgeny-goldin.com/wiki/Jenkins-maven-plugin#Supported_Plugins
you can manage jenkins goals from your pom.xml but I am not sure if you can get jenkins build.

Maven: running Unit-Tests remotely

We are currently working on a distributed Java EE-Application and have therefore a separated test and production system.
Compiling and Bundling is done via an Ant-Task. Now we want to deploy the Jar-Files of the different servers to the test-servers and run the JUnit Integration / Function-Tests there. If they succeed, then the current version should be deployed to the live-servers.
Plain Unit-Tests are executed by Hudson.
Is that possible with Maven and is there any information or best practice available?
Yes. Hudson has maven integration. Take a loot this wiki and this link.
You can set unit test case thresholds for your job to see if it does not pass a certain number of test cases. In that the deploy plugin will not get invoked and the app will not get deployed.
Take a JAR built from Ant and reuse it. I would add a Maven repository to your environment such as Artifactory, Archiva, or Nexus and deploy to that using Ivy. You almost certainly need to use a Maven repository to be happy with Maven for anything other than small scale personal projects. http://ant.apache.org/ivy/
Use Maven to grab the JAR from the Maven Repository. For this, just use a normal Maven dependency declaration.
Run Maven on the QA server, with the JUnit tests declared in that project. If that succeeds, deploy the JAR to the production server. For this, the details depend on the production server. If it's a WAR, I would use Cargo, but if it's a JAR it really depends on what's executing the JAR - you might need some sort of file copy, scp, etc. http://cargo.codehaus.org/
Hudson and TeamCity both have deployment features as well. You just set up a job to run (in this case the Maven job) and tell the CI server to deploy on success.

Categories