Our current test automation setup for end to end testing is using Maven for preparing the test data, running our test scenarios and creating a test report. Recently, I wanted to refactor the way we use Maven's lifecycles and found a surprisingly easy way to do just that.

Lifecycles

In case you are not aware of what Maven lifecycles are, I highly recommend the Apache's official Maven lifecycle reference. In a nutshell, a lifecycle is a high level task you want Maven to carry out for you.

The ones we use for our test automation are clean for wiping a previous build and default which is the main lifecycle for testing, building and deploying a Java application.

Phases

Each lifecycle consists of phases that run in a fixed order. Some phases use pre-defined Maven plugins automatically, like the phases used for testing.

  • test uses Surefire to run unit test
  • integration-test uses Failsafe to run integration tests

If you don't want certain phases to run, you can skip their invocation.

Additionally, some phases also have pre and post phases such as

  • pre-clean (runs before clean)
  • post-clean (runs after clean)

and even better for test automation:

  • pre-integration-test (runs before integration-test)
  • post-integration-test (runs after integration-test)

Such phases come in handy when setting up or tearing down test data or - like we use it - re-run certain failed tests.

Goals

Each phase can trigger multiple plugins. This can be configured to the marrow and would could be a book of its own.

A goal is essentially a specific task that a plugin should execute. In the following example, we specify that the Checkstyle plugin should run in Maven's validate phase and trigger the plugin goal check that checks our project's code style:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-checkstyle-plugin</artifactId>
    <version>${maven.checkstyle.plugin.version}</version>
    <executions>
        <execution>
            <id>Check code style of tests</id>
            <phase>validate</phase>
            <goals>
                <goal>check</goal>
            </goals>
        </execution>
    </executions>
</plugin>   

The challenge

In case you haven't worked with Maven yet, this might already overwhelm you. However, even if you have there is one essential problem with how your project's lifecycle is configured: it is all in a flat file (called pom.xml) that is written in a very linear form.

Due to the nature of lifecycle, phases, executions and goals, this can mean that the actual execution flow is impossible to see. Plugin executions can be bound to multiple phases so that one has to jump back and forth in this file in order to know what exactly is happening.

This can be hard to debug, hard to write and even harder to understand.

The rescue

After some research I found a rather old plugin called Buildplan.

This can be included in your Maven project like so:

<plugin>
    <groupId>fr.jcgay.maven.plugins</groupId>
    <artifactId>buildplan-maven-plugin</artifactId>
    <version>1.3</version>
</plugin>

With a simple invocation of mvn buildplan:list (buildplan is the name of the plugin, list is the goal), it creates a table listing the lifecycle phases, plugins and goals in their order of invocation!

For our end to end test project, this looks like this:

Maven Lifecycle

Even though this is still rather complex (we use some phases multiple times with different plugins and goals), it is much easier to follow and proved to be an invaluable tool for optimizing and debugging our Maven configurations.

Previous Post Next Post