Saturday, October 8, 2016

How to run maven

1 Maven Command (mvn)

The basic syntax for running Maven is:

mvn [options] [<plugin:goal>] [<phase>]

The execution order depends on how goals and build phases are specified on the command line.

2 Running Maven Phases

Example: Compile a project

mvn clean compile

This command removes the previous build output and compiles the project's source code.

3 Running Unit Tests and Integration Tests

Unit tests usually test individual classes or components in isolation. Integration tests verify that multiple components work together, for example an application communicating with a database.

Maven itself does not inherently know whether a test is a unit test or an integration test. The distinction is usually created through plugin configuration and test class naming conventions.

Different Maven plugins can recognize different test class naming patterns. For example, the maven-surefire-plugin is normally used for unit tests, while the maven-failsafe-plugin is normally used for integration tests.

3.1 How Maven Test Plugins Recognize Test Classes

Each test plugin has its own default include patterns. These patterns determine which Java classes are considered test classes and executed by the plugin.

For example, the maven-surefire-plugin, which is normally used for unit tests, recognizes common test class names such as:

Test*.java
*Test.java
*Tests.java
*TestCase.java

Therefore, classes such as the following can be recognized as unit tests:

UserTest.java
TestUser.java
UserTests.java
UserTestCase.java

The maven-failsafe-plugin uses different default patterns for integration tests:

IT*.java
*IT.java
*ITCase.java

Therefore, classes such as the following can be recognized as integration tests:

ITDatabase.java
DatabaseIT.java
DatabaseITCase.java

This naming convention makes it possible to separate unit tests from integration tests while keeping both types of tests in the same Maven test source directory.

Example: Run Unit Tests

mvn test

This command executes the Maven lifecycle up to the test phase. It compiles the application, compiles the test code, and runs the unit tests.

The unit tests are normally executed by the maven-surefire-plugin.

For example:

mvn clean test

This command first removes the previous build output and then compiles and executes the unit tests.

Example: Run Unit Tests and Integration Tests

mvn verify

The verify phase occurs later in the Maven default lifecycle. Therefore, Maven executes all the preceding phases before reaching verify.

If the project is configured with the maven-failsafe-plugin, the integration tests are executed during the integration-test and verify phases.

A common command is:

mvn clean verify

This command performs a clean build, runs the unit tests, packages the application, and executes the integration tests.

The simplified execution flow is:

clean
  |
compile
  |
test
  |---- Unit Tests
  |
package
  |
integration-test
  |---- Integration Tests
  |
verify

3.2 Running Integration Tests with Surefire

Using the maven-failsafe-plugin is the standard approach when you want to separate unit tests from integration tests. However, using two test plugins is not mandatory.

If you prefer to use only the maven-surefire-plugin, you can name your integration test classes using one of Surefire's default test patterns.

For example, both of the following classes match Surefire's default naming conventions:

UserServiceTest.java
DatabaseIntegrationTest.java

Although DatabaseIntegrationTest.java is logically an integration test, its name matches the *Test.java pattern. Therefore, Surefire recognizes it as a test class and executes it together with the unit tests.

For example, consider the following test structure:

src
|
+-- test
    |
    +-- java
        |
        +-- UserServiceTest.java
        +-- RepositoryTest.java
        +-- DatabaseIntegrationTest.java
        +-- JpaIntegrationTest.java

All these classes match the default patterns recognized by the maven-surefire-plugin.

Therefore, the following command executes both the unit tests and the integration tests:

mvn test

Or, for a clean build:

mvn clean test

In this configuration, Maven does not distinguish between unit tests and integration tests. Both types of tests are executed during the test phase by the Surefire plugin.

UserServiceTest.java
RepositoryTest.java
        |
        +----> maven-surefire-plugin
        |
DatabaseIntegrationTest.java
JpaIntegrationTest.java
        |
        +----> maven-surefire-plugin
                    |
                    v
                test phase

This approach can be useful for small projects where running all tests together is sufficient and a separate integration test lifecycle is not required.

However, if integration tests require additional setup or cleanup operations, such as starting and stopping a database, a container, or an external service, using the maven-failsafe-plugin is usually the better approach.

3.3 integration-test vs verify

The integration-test and verify phases are both part of the Maven default lifecycle, but they have different purposes.

The command:

mvn integration-test

runs the Maven lifecycle up to the integration-test phase. Therefore, all preceding phases are executed first.

In a project using the maven-failsafe-plugin, the integration tests are executed during this phase.

For example, the execution flow can be summarized as:

mvn test
    ↓
Unit tests


mvn package
    ↓
Unit tests
    ↓
Package


mvn integration-test
    ↓
Unit tests
    ↓
Package
    ↓
Integration tests


mvn verify
    ↓
Unit tests
    ↓
Package
    ↓
Integration tests
    ↓
Verification of integration-test results


mvn install
    ↓
Unit tests
    ↓
Package
    ↓
Integration tests
    ↓
Verification of integration-test results
    ↓
Install artifact into local repository


mvn deploy
    ↓
Unit tests
    ↓
Package
    ↓
Integration tests
    ↓
Verification of integration-test results
    ↓
Install artifact into local repository
    ↓
Deploy artifact to remote repository

The important difference is that integration-test is the phase where the integration tests are executed, while verify is a later phase where the results of the integration-test execution can be checked.

This is why the Maven Failsafe Plugin is normally configured with both the integration-test and verify goals:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-failsafe-plugin</artifactId>
    <version>3.5.2</version>

    <executions>
        <execution>
            <goals>
                <goal>integration-test</goal>
                <goal>verify</goal>
            </goals>
        </execution>
    </executions>
</plugin>

For this reason, when you want to perform a complete build including integration tests, mvn verify is generally preferred over mvn integration-test.

The commonly used command is:

mvn clean verify

This performs a clean build, runs the unit tests, packages the application, runs the integration tests, and verifies their results.

In other words, integration-test is mainly the phase where integration testing takes place, while verify is the phase normally used to confirm that the complete build has successfully passed all required checks.

4 Configuring Unit and Integration Tests

Maven uses plugins to execute tests. Each plugin can have its own rules for recognizing test classes.

  • maven-surefire-plugin is normally used for unit tests and recognizes class names such as *Test.java.
  • maven-failsafe-plugin is normally used for integration tests and recognizes class names such as *IT.java.

The naming conventions are important because they allow the two plugins to execute different groups of tests.

The following is a simple pom.xml configuration:

<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>com.example</groupId>
    <artifactId>maven-tests-example</artifactId>
    <version>1.0.0</version>

    <properties>
        <maven.compiler.release>8</maven.compiler.release>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>

    </dependencies>

    <build>
        <plugins>

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

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

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>3.5.2</version>

                <executions>
                    <execution>
                        <goals>
                            <goal>integration-test</goal>
                            <goal>verify</goal>
                        </goals>
                    </execution>
                </executions>

            </plugin>

        </plugins>
    </build>

</project>

The following diagram summarizes how the two plugins work:

                    Maven Project
                          |
                          |
                 src/test/java
                          |
              +-----------+-----------+
              |                       |
              |                       |
      UserServiceTest.java      DatabaseIT.java
      RepositoryTest.java       JpaIT.java
              |                       |
              |                       |
              v                       v
    maven-surefire-plugin    maven-failsafe-plugin
              |                       |
              v                       v
          test phase         integration-test phase
              |                       |
              +-----------+-----------+
                          |
                          v
                    verify phase

5 Package a Project

Example: Package a project

mvn clean package

This command compiles the code, runs the unit tests, and packages the application into a distributable format such as a JAR or WAR.

Example: Run a Spring Web application

For example, assume you created a Spring Boot web application named my-spring-webapp.

  • To compile the project and produce an artifact, run mvn clean package from the project root.
  • To run the application, execute java -jar target/my-spring-webapp-1.0.0.jar from the project root.

The embedded Tomcat server starts on port 8080. Open your browser and go to http://localhost:8080.

Example: Install to the local repository

mvn clean install

This is one of the most common Maven commands. It builds the project and installs the generated artifact into your local repository, making it available for other local projects.

Maven executes all default lifecycle phases up to install. If Failsafe is configured, integration tests are also executed before the artifact is installed.

Example: Deploy to a shared repository

mvn clean deploy

In a build environment, this command cleans, builds, tests, and deploys artifacts to a remote repository. In multi-module projects, Maven processes each submodule in order and deploys their artifacts.

6 Running Maven Goals

A build phase can have zero or more goals bound to it. If no goals are bound, the phase does nothing. If goals are bound, all of them are executed when the phase runs.

Example: Generate a project using the Archetype plugin

mvn archetype:generate

Example: Run Checkstyle

mvn checkstyle:check

This command runs the check goal of the Maven Checkstyle plugin. It analyzes your source code to ensure it follows a defined coding standard (style rules).

Checkstyle verifies aspects such as code formatting (indentation, spacing, line length), naming conventions (classes, methods, variables), and code structure and organization.

Example: Execute a goal before packaging

mvn clean dependency:copy-dependencies package

In this command:

  • clean and package are lifecycle phases.
  • dependency:copy-dependencies is a plugin goal.

Execution order:

  • First, the clean phase runs.
  • Next, the dependency:copy-dependencies goal executes.
  • Finally, the package phase runs, including all preceding phases in the default lifecycle.

Maven Command Cheat Sheet

Command Description Typical Use Case
mvn clean Deletes the target directory. Start a fresh build.
mvn clean compile Cleans previous output and compiles the project. Rebuild source code from scratch.
mvn test Runs test classes recognized by the Maven Surefire plugin. By default, these are typically unit tests. Run unit tests during development.
mvn clean test Cleans the project, compiles the code, and runs the test classes recognized by Surefire. Run a clean build with unit tests.
mvn verify Runs the build lifecycle up to the verify phase. With Failsafe configured, integration tests are also executed. Verify the complete application build.
mvn clean verify Performs a clean build, runs unit tests, packages the application, and runs integration tests. Full local or CI build verification.
mvn clean package Cleans, compiles, runs unit tests, and packages the application. Prepare the application for execution or distribution.
mvn clean install Full build and installation of the generated artifact into the local repository. Make the artifact available to other local projects.
mvn clean deploy Full build and deployment of the generated artifact to a remote repository. Share builds with teams or CI/CD systems.
mvn validate Validates the project structure and configuration. Early sanity check before building.
mvn site Generates project documentation. Create project reports and a documentation site.

No comments:

Post a Comment