0

I have a very simple Maven project that I updated here, I obtained it simplifying my real project: GitHub repository

I need to run Surefire plugin to compile tests, so they can be used by Jacoco. I tried sooo many things, even changing/reducing the dependencies, but none worked! I excluded the tests in maven-compiler-plugin because it said "package main.it.isp.utility does not exist". I don't know if excluding it is correct, though....

This is my pom.xml and project structure:

enter image description here

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>it.isp.batch</groupId>
<artifactId>Estrazioni-Batch</artifactId>
<version>1.0.0-SNAPSHOT</version>

<properties>
    <!-- Dependency versions -->
    <junit.jupiter.version>5.5.2</junit.jupiter.version>
    <!-- Java 8 -->
    <maven.compiler.target>1.8</maven.compiler.target>
    <maven.compiler.source>1.8</maven.compiler.source>
    <java.version>1.8</java.version>
    <!-- Encoding -->
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>

<dependencies>

    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.17.2</version>
    </dependency>
    <dependency>
        <groupId>org.junit</groupId>
        <artifactId>junit5-engine</artifactId>
        <version>5.0.0-ALPHA</version>
    </dependency>
    <!-- Jupiter API for writing tests -->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>5.8.2</version>

    </dependency>
    <dependency>
        <groupId>org.junit.platform</groupId>
        <artifactId>junit-platform-runner</artifactId>
        <version>1.8.2</version>
    </dependency>


    <!-- https://mvnrepository.com/artifact/org.mockito/mockito-junit-jupiter -->
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-junit-jupiter</artifactId>
        <version>4.4.0</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>5.3.18</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-tx -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>5.3.18</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.mockito/mockito-core -->
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-core</artifactId>
        <version>4.4.0</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>3.2.1.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-dbcp2 -->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-dbcp2</artifactId>
        <version>2.9.0</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.12.0</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/commons-lang/commons-lang -->
    <dependency>
        <groupId>commons-lang</groupId>
        <artifactId>commons-lang</artifactId>
        <version>2.6</version>
    </dependency>

</dependencies>

<build>
    <finalName>Estrazioni-Batch</finalName>
    <sourceDirectory>src</sourceDirectory>
    <testSourceDirectory>test</testSourceDirectory>

    <resources>
        <resource>
            <directory>src/</directory>
            <excludes>
                <exclude>test/</exclude>
            </excludes>
        </resource>
    </resources>

    <plugins>

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>

            <version>3.10.1</version>


            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <outputDirectory>${basedir}/target/diraliases/BATCHROOT/Estrazioni-batch/classes</outputDirectory>
                <testExcludes>
                    <testExclude>**/*Test*</testExclude>
                </testExcludes>
            </configuration>

        </plugin>

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>3.0.0-M6</version>
            <configuration>
                <testFailureIgnore>false</testFailureIgnore>
                <skip>false</skip> <!-- Please take care of these parameters. They will help you to spot failure 
                    in test assertions -->
                <skipTests>false</skipTests>
                <testSourceDirectory>${basedir}/src/main/test/</testSourceDirectory>

                <properties>
                    <property>
                        <name>surefire.testng.verbose</name>
                        <value>10</value>
                    </property>
                </properties>
                <includes>
                    <include>**/*Test.java</include>
                </includes>
            </configuration>
            <dependencies>
                <dependency>
                    <groupId>org.junit.platform</groupId>
                    <artifactId>junit-platform-surefire-provider</artifactId>
                    <version>1.2.0-M1</version>
                </dependency>
                <dependency>
                    <groupId>org.junit.jupiter</groupId>
                    <artifactId>junit-jupiter-engine</artifactId>
                    <version>5.8.2</version>

                </dependency>
                <!-- https://mvnrepository.com/artifact/org.apache.maven.surefire/surefire-api -->
                <dependency>
                    <groupId>org.apache.maven.surefire</groupId>
                    <artifactId>surefire-api</artifactId>
                    <version>3.0.0-M6</version>
                </dependency>
            </dependencies>
        </plugin>
        <plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <version>0.8.7</version>
            <!-- Suggested to always use the latest, at minimun 0.8.3 -->
            <executions>
                <execution>
                    <id>prepare-agent</id>
                    <goals>
                        <goal>prepare-agent</goal>
                    </goals>
                    <configuration>
                        <!-- EXEC format is still used as an intermediate report format, but 
                            it purpose is only internal to JaCoCo execution -->
                        <!-- It will not be parsed by Sonar. There will be one EXEC file for 
                            each module of the application -->
                        <destFile>./jacoco-${project.artifactId}.exec</destFile>
                    </configuration>
                </execution>
                <execution>
                    <id>report</id>
                    <goals>
                        <goal>report</goal>
                    </goals>
                    <configuration>
                        <!-- The purpose of REPORT goal is to convert each EXEC in evry output 
                            format that JaCoCo is able to produce, including XML -->
                        <!-- The XML files are placed inside a temporary directory -->
                        <dataFile>./jacoco-${project.artifactId}.exec</dataFile>
                        <outputDirectory>./sonar-report/temp-jacoco-xml/${project.artifactId}</outputDirectory>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>com.coderplus.maven.plugins</groupId>
            <artifactId>copy-rename-maven-plugin</artifactId>
            <version>1.0</version>
            <executions>
                <execution>
                    <id>copy-file</id>
                    <phase>verify</phase>
                    <goals>
                        <goal>copy</goal>
                    </goals>
                    <configuration>
                        <!-- The purpose of this plugin is to collect all the XML files under 
                            the temp directory in each module -->
                        <!-- and copy in to the right path scanned by Sonar. There will be 
                            one XML file for each module -->
                        <sourceFile>./sonar-report/temp-jacoco-xml/${project.artifactId}/jacoco.xml</sourceFile>
                        <destinationFile>./sonar-report/jacoco-xml/jacoco-${project.artifactId}.xml</destinationFile>
                    </configuration>
                </execution>
            </executions>
        </plugin>






    </plugins>



</build>
Pipkin
  • 99
  • 1
  • 2
  • 7
  • 1
    First remove the configuration for `src` and this: `test` and follow conventions. Put production code into `src/main/java/` and unit- integration test into `src/test/java/` put resources into `src/main/resources` and resources for testing purposes into `src/test/resources` This would mean also remove configuration for `resources`,,, – khmarbaise Apr 23 '22 at 08:50
  • Thank you for your precious tip, I will remember to use the standard Maven structure (I fixed it in my project) :) – Pipkin Apr 24 '22 at 07:38

1 Answers1

2

The most important thing is to follow conventions in Apache Maven. So do not change the configuration for source directory and the test directory that makes in 99.999% of the cases no sense.

So first remove the following configuration parts:

<finalName>Estrazioni-Batch</finalName>    
<sourceDirectory>src</sourceDirectory>
<testSourceDirectory>test</testSourceDirectory>

The <finalName> ..</finalName> does not make sense because your artifact is named based on your artifactId...furthermore an artifactId should be lowercase.

You have configured either Eclipse wrong or it's based on the wrong configuration.

The production code belongs to src/main/java/<packageName> and the according unit- or integration tests should be done into src/test/java/<packageName>.

For unit tests you should follow naming conventions like *Test.java what you already did. And for integration tests you should use *IT.java.

Furthermore remove the configuration for the resources:

 <resources>
        <resource>
            <directory>src/</directory>
            <excludes>
                <exclude>test/</exclude>
            </excludes>
        </resource>
    </resources>

Because in your setup you've already used src/main/resources for test using src/test/resources.

Looking into the pom file you have given there are other strange things like mixing different junit-jupiter versions/parts.

So first remove the following from your pom file:

<dependency>
    <groupId>org.junit</groupId>
    <artifactId>junit5-engine</artifactId>
    <version>5.0.0-ALPHA</version>
</dependency>
<!-- Jupiter API for writing tests -->
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <version>5.8.2</version>

</dependency>
<dependency>
    <groupId>org.junit.platform</groupId>
    <artifactId>junit-platform-runner</artifactId>
    <version>1.8.2</version>
</dependency>

The easiest way to handle that is to use the junit bom file like the following:

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.junit</groupId>
        <artifactId>junit-bom</artifactId>
        <version>5.8.2</version>
        <scope>import</scope>
        <type>pom</type>
      </dependency>
      ..
  </dependencyManagement>

Afterwards you have to define a single dependency in your pom like this:

 <dependencies>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-api</artifactId>
      <scope>test</scope>
    </dependency>
    ...
 </dependencies>

Furthermore remove the whole setup/configuration of maven-surefire-plugin and replace with the following:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>3.0.0-M6</version>
</plugin>

The whole configuration/setup of the maven-compiler-plugin should simply look like this:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-compiler-plugin</artifactId>
  <version>3.10.1</version>
</plugin>

Also remove the whole configuration/setup of jacoco-maven-plugin and replace it with this:

<plugins>
  <plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.8.8</version>
    <executions>
      <execution>
        <goals>
          <goal>prepare-agent</goal>
          <goal>report</goal>
        </goals>
      </execution>
    </executions>
  </plugin>
</plugins>

Remove the whole configuration/setup for copy-rename-maven-plugin.

Some words about usage of the dependencies:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.12.0</version>
</dependency>
<dependency>
    <groupId>commons-lang</groupId>
    <artifactId>commons-lang</artifactId>
    <version>2.6</version>
</dependency>

Why using different versions of the same artifact? Remove commons-lang:commons-lang:2.6 and continue to work with org.apache.commons:commons-lang3:3.12.0 instead.

If you like to use sonar report you should execute the sonar-maven-plugin which is described here: https://docs.sonarqube.org/latest/analysis/scan/sonarscanner-for-maven/

There are full working example https://github.com/khmarbaise/example-junitjupiter

One final strong recommendation is to define the all the plugins which are used during the build (see the example)..

khmarbaise
  • 92,914
  • 28
  • 189
  • 235
  • Your tips helped me understanding: 1-How to configure properly a Maven Project: copying parts from the web (without the proper knowledge) made it worse. I will remember to follow the standard Maven structure.And that simple is better :) 2-After fixing parts as indicated by you, I noticed that in maven-compiler-plugin I used "outputDirectory" to move the class files, since I need them in another directory, BUT that maked everything fail. So I removed that and just copied the classes as last step in the pom; Now everything is working.Thank you so much for helping, that was really appreciated! – Pipkin Apr 24 '22 at 07:38
  • configuring something from outside the `target` is usually a bad idea...Why do you need to copy the classes ? Can you elaborate a bit more why you need that? – khmarbaise Apr 24 '22 at 10:56
  • The mechanism used by my company to deploy the software through Jenkins requires the software to be released in the following path: target/diraliases/[something]. Then, the resulting classes will be launched by my shells (.sh), as a batch software. – Pipkin Apr 24 '22 at 11:21
  • What does it mean to have a path `target/diraliases/..` ? `target` is a temporary directory during the jar/compilation.. the resulting part is `jar`, `war` etc. which have a defined structure... ? That sounds strange to honest? Starting classes via a shell script does not make sense because using simply a jar or a ueber jar which simply can be started via `java -cp XYZ.jar ..`... why shell scripts? (This is violating one of the defaults which also makes it more complicated than needed.)... Starting of apps should be done by using an other job ... – khmarbaise Apr 24 '22 at 11:46
  • My company guidelines are: "make a copy of the compiled software in the temporary folder target/diraliases" - otherwise the Jenkins build stops saying that didn't found the classes in that path. It is very specific of the environment of my company, I think. I agree that launching the jar with -cp is also better than launching the single classes. The shell scripts -> because the scheduling apps used by my company trigger shell scripts, so those shells are the way we can launch Java programs. I hope I have been more clear – Pipkin Apr 24 '22 at 13:34
  • A company guidelines is one thing but I asking about the reason what is the problem that should be solved by that? It makes things more complicated etc. But it is as it is... – khmarbaise Apr 24 '22 at 14:00