Java / mvn code coverage AND redundancy? - java

Have a monolthic app that runs JUnit tests through Surefire and Maven. I see several options out there that will tell me about code coverage, but I'm trying to find something a little different:
Specifically, I'd like to run a mvn build that generates a report (or use an Eclipse plugin that does the same) that will give me a way to see what tests are all pretty much doing the same thing, in addition to the parts of the app that do not have good coverage. Does something like this exist?

I doesn't cover the redundancy part, but for the coverage you may use Jacoco, it's easy to setup with maven:
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>3.6</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.7.201606060606</version>
<executions>
<execution>
<id>default-prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<reporting>
<excludeDefaults>true</excludeDefaults>
<outputDirectory>${project.build.directory}/site</outputDirectory>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
</plugin>
</plugins>
</reporting>
To generate the report, type mvn site. The reports will be created under target/site.

To combine with #alexbt answer you can utilize the report you have with Jacoco but plug that report into SonarQube (you can easily install it locally) then get the SonarLint Eclipse plugin that connects to the local SonarQube instance to get the integration you want.
In addition you get copy and paste detection and some redundant code checks. I say some because public methods are never marked as redundant.
Here are an examples of an online report with and without major problems
https://sonarcloud.io/dashboard?id=org.apache.maven:maven
https://sonarqube.com/dashboard?id=net.trajano.mojo:batik-maven-plugin
https://sonarcloud.io/component_measures/domain/Coverage?id=net.trajano.jetng:jetng
One bonus is you can centralize the rules for your team.

Related

How to generate pdf report of junit test results?

I have a maven project and want to generate pdf report of my junit test results. I used Surefire and pdf plug-in as well.
my pom looks like
/*<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<archive>
<manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>
</archive> <outputDirectory>D:\backups\third\aristocrat_template_project\game-jars\queenOfTheNile_html</outputDirectory>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pdf-plugin</artifactId>
<version>1.3</version>
<executions>
<execution>
<id>pdf</id>
<phase>site</phase>
<goals>
<goal>pdf</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
*/
In my target site folder html files are generated but does not contains the report related to junit results. I also got a pdf file under target->pdf folder but it does not contain any information related to project or junit result. Thanks !
You can use this: How to us Maven PDF Plugin to generate PDF from Surefire Report?
you can use any (at least all I know) test coverage tool (like cobertura, jacoco) and will generate raports itselfes.
You can as well use cucumber test framework for very friendly reports, but that's a lof of effort to create cucumber tests.

Integration sonar with jacoco. I see excluded packages in sonar coverage report

I want to migrate from cobertura to jacoco codecoverage tool.
I'm using maven as build tool and I added jococo-maven-plugin in my pom.xml file. its configuration looks like this:
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.2.201409121644</version>
<configuration>
<append>true</append>
<outputEncoding>UTF-8</outputEncoding>
<destFile>${sonar.jacoco.reportPath}</destFile>
<dataFile>${sonar.jacoco.reportPath}</dataFile>
<outputDirectory>${jacoco.output.path}</outputDirectory>
<excludes>
<exclude>com/acmecorp/acmeproject/mbean/**/*.class</exclude>
<exclude>com/acmecorp/acmeproject/model/**/*.class</exclude>
</excludes>
</configuration>
<executions>
<execution>
<id>agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>jacoco-site</id>
<phase>package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
So after performing mvn clean install jacoco generates me some pretty html pages with code coverage. And this document looks exactly how I want it to look.
The second step I need to perform is integrate jococo with sonar. Previously I integrated sonar with cobertura. So I simply removed cobertura specific properties and added properties related to jococo.
<properties>
<!--<sonar.cobertura.reportPath>target/site/cobertura/coverage.xml</sonar.cobertura.reportPath>-->
<sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
<sonar.projectKey>${project.artifactId}</sonar.projectKey>
<sonar.projectName>ACME Project</sonar.projectName>
<sonar.projectVersion>${project.version}</sonar.projectVersion>
<sonar.java.source>${java.compliance.level}</sonar.java.source>
<sonar.sources>src/main/java</sonar.sources>
<sonar.jdbc.url>jdbc:mysql://4.4.8.8:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance</sonar.jdbc.url>
<sonar.jdbc.driver>com.mysql.jdbc.Driver</sonar.jdbc.driver>
<sonar.jdbc.username>ranos</sonar.jdbc.username>
<sonar.jdbc.password>ranos</sonar.jdbc.password>
<sonar.host.url>http://4.4.8.8:9000/sonar/</sonar.host.url>
<sonar.jacoco.reportPath>target/sites/jacoco/jacoco.exec</sonar.jacoco.reportPath>
<jacoco.output.path>target/sites/jacoco/</jacoco.output.path>
</properties>
Maven plugin
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>3.0.1</version>
</plugin>
and profile
<profiles>
<profile>
<id>sonar</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
</profiles>
As a result I get such code coverage on server:
And I see that in generated coverage report on server I see that my excluded packages are included in report. When I use cobertura everything worked fine.
So may be someone could help me with this. I do not want to add exclusions for sonar configuration. I really hope that it could be some additional configuration for jococo plugin.
UPDATE
In case I use cobertura maven-plugin with sonar
(I mean if I comment this line <sonar.jacoco.reportPath>target/sites/jacoco/jacoco.exec</sonar.jacoco.reportPath> and uncomment this one <sonar.cobertura.reportPath>target/site/cobertura/coverage.xml</sonar.cobertura.reportPath>)
The exclusions need to happen not on the JaCoCo side, but on the SonarQube side, and be specified via the SonarQube UI, rather than in your POM.
The docs will give you details: http://docs.sonarqube.org/display/SONAR/Narrowing+the+Focus#NarrowingtheFocus-IgnoreCodeCoverage
Put packages that you want to exclude in maven <properties> block in your pom.xml:
<properties>
<sonar.jacoco.excludes>*model*,*generated*,*exception*</sonar.jacoco.excludes>
</properties>
If that does not work, try changing property name to sonar.coverage.exclusions, I think it changed in later versions.

Executing Maven unit tests with classpath set to generated project JAR

Some unit tests in my application are related to finding and manipulating certain files resources that are part of the application itself.
I need these tests to be executed in the real production setting of the application, where it is deployed as a JAR file, not as an exploded directory.
How could I instruct Maven to execute my unit tests considering as the classpath the project generated jar file (and any other declared library dependencies) instead of the compiled classes in the file system as it does by default?.
In other words, right now the classpath for my unit tests is set to: /$PROJECTPATH/target/classes/.
Instead, I would like this classpath to be set to: /$PROJECTPATH/target/myjarfile.jar.
I have tried manually adding and removing dependency classes, as explained here:
http://maven.apache.org/plugins/maven-surefire-plugin/examples/configuring-classpath.html
,but until now it is not working.
My current project POM looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.mygroupid</groupId>
<artifactId>myartifact</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
...
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.1.2</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.4</version>
<configuration>
<includeScope>runtime</includeScope>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>process-resources</phase>
<!-- <phase>package</phase> -->
<goals>
<goal>copy-dependencies</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.3</version>
<configuration>
<classpathDependencyExcludes>
<classpathDependencyExclude>
${project.build.outputDirectory}
</classpathDependencyExclude>
</classpathDependencyExcludes>
<additionalClasspathElements>
<additionalClasspathElement>
${project.build.directory}/${project.build.finalName}.${project.packaging}
</additionalClasspathElement>
</additionalClasspathElements>
</configuration>
</plugin>
</plugins>
</build>
</project>
Thanks in advance for any help!.
The standard unit tests executed as part of the test lifecycle phase cannot see the project JAR because the test phase is executed before the package phase, so your tests are run before Maven generates the JAR. See this page for a list of lifecycle phases and their order.
What you want it to run your tests as integration tests, which execute in the integration-test phase.
There are a number of tutorials for setting up Maven to run integration tests. Here and here are a couple of starters. The failsafe plugin is typically used for executing integration tests.
I can't recall exactly if integration tests use target/classes or your project's JAR file in the classpath. But if it doesn't you could always create another Maven project, add your tests in there and add the main project as a dependency to this integration test project. In some cases this can be preferable to using the integration test phase in the main project if it is not just a standard Java library, for example if you are writing an annotation processor.

What is the best way to avoid maven-jar?

I am using a different plugin (ant4eclipse) to jar my files. What is the best way to avoid the maven-jar plugin from executing?
I tried to remove the <plugin>maven-jar-plugin</plugin>
I tried to <exclude> ** / * < / exclude>
I tried to <skip>true</skip>
None worked
In Maven 3.0.x (I tried 3.0.2) you can disable maven-jar-plugin by binding the default-jar execution to a nonexistent phase, as #bmargulies suggested. Unfortunately that doesn't work in 2.2.1, but you can prevent it from interfering with your own jar by setting an alternative <finalName> and <classifier> for the default-jar execution; it will still create a jar, but it will be set as a secondary artifact for the project and won't overwrite the one you've created. Here's an example that should work in both Maven 2 and Maven 3:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>test</artifactId>
<version>0.1-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>default-jar</id>
<phase>none</phase>
<configuration>
<finalName>unwanted</finalName>
<classifier>unwanted</classifier>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Once you've disabled maven-jar-plugin, maven-install-plugin may give you trouble too. In Maven 3 it can be disabled the same as maven-jar-plugin: bind default-install to a nonexistent phase. However, in Maven 2 maven-install-plugin requires that the target/classes directory exist, and it will install the dummy jar when there isn't a primary artifact present.
This should do the trick - notice the use of <id>default-jar</id> and <phase/>.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>default-jar</id>
<phase/>
</execution>
</executions>
</plugin>
</plugins>
</build>
In my case, I only wanted to disable the jar plugin because the jar was empty. You can use the skipIfEmpty option in the plugin configuration
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<skipIfEmpty>true</skipIfEmpty>
</configuration>
</plugin>
What happens if you declare this?
<packaging>pom</packaging>
Even if it does what you're looking for, be careful. I'm not sure if there could be negative side effects -- such as other maven projects that depend on your jar not being able to locate it.
Using maven 3.3.9, the following worked for me:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.2</version>
<executions>
<execution>
<id>default-jar</id>
<phase>none</phase>
<configuration>
<finalName>unwanted</finalName>
<classifier>unwanted</classifier>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>3.0.0-M1</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
So in case of the maven-jar-plugin, I bound it to a non-existent phase. For the maven-install-plugin, I used the "skip" configuration parameter. The documentation about it says: "Set this to true to bypass artifact installation. Use this for artifacts that does not need to be installed in the local repository."
Explicitly bind the jar plugin to a phase that doesn't exist.
As other's have said, it's not possible to turn it off, other than using <packaging>pom</packaging>, which turns everything off and is probably not what you want.
Even though it will generate twice, a working solution is to bind your jar process to the package phase, as that is guaranteed to run after the default. By overwriting the same JAR file, you'll find that yours is used wherever the original would have been.
I am using a different plugin to jar my files. What is the best way to avoid the maven-jar plugin from executing?
First, the jar:jar goal is bound by default on the package phase for a project with a packaging of type jar. Second, there is no way to unbind a plugin bound to a phase. So, if you are using another plugin(?), either accept to produce 2 JARs or change the packaging (but I don't think this will work well).
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>

How to run findbugs automatically in maven on install

It's easy to add the findbugs plugin to maven so that it will run if I do
mvn site
However, I would like it to run whenever I do
mvn install
just like unit tests. That is, I don't want the install to succeed if findbugs finds any bugs. Is there are way for me to do this?
About the findbugs:check goal, the documentation writes:
Fail the build if there were any FindBugs violations in the source code. An XML report is put out by default in the target directory with the errors. To see more documentation about FindBugs' options, please see the FindBugs Manual.
So this is precisely the goal you're looking for. You now just have to bind the check goal to the install verify phase (the verify phase occurs just before install and is actually made to run any checks to verify the package is valid and meets quality criteria so I think it's a better choice):
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<version>2.0.1</version>
<configuration>
<effort>Max</effort>
<threshold>Low</threshold>
<xmlOutput>true</xmlOutput>
</configuration>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
...
</plugins>
...
</build>
...
</project>
Of course, adapt the configuration to suit your needs.
<build>
<plugins>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<version>2.0</version>
<configuration>
...
</configuration>
</plugins>
</build>
findbugs:check goal
findbugs: Violation Checking

Categories

Resources