There are currently a number of solutions for testing plugins - both in terms of unit testing and integration testing. This has resulted in a confusing situation where plugins can be tested in multiple different ways, and there are no clear instructions for a new plugin author in how to test their plugins.
The objective of this document is to assess all the current approaches, and their positives and negatives, and to provide a baseline for discussion about the various approaches. It will attempt to identify overlap and make proposals to reduce duplication and confusion. It will also attempt to document how to write integration tests for your plugin, depending on your objectives. It will not attempt to propose a single-replacement solution - as there are likely good reasons to have different types of testing, and a separation of different techniques into different plugins (though deprecation of some libraries or techniques to reduce duplication may be necessary).
Definition: This is traditional unit testing - it takes no consideration for the fact that it is a Maven plugin, and tests the code itself.
maven-plugin-testing-harness: This library provides assistance for plugin testing by pre-constructing the Plexus components, providing stub objects for Maven functionality such as projects, and populating fields from an XML file that resembles the plugin configuration in the POM.
- standard JUnit testing: MOJOs written in Java can be tested using JUnit as standard Java objects (possibly using a mock framework to mock the Maven functionality such as projects). For non-Java MOJOs, a corresponding test framework may be used for that language but the same principles apply. Using the
PlexusTestCasecan also give some of the instantiation assistance of the testing harness without the stubs.
Definition: Integration testing for plugins is checking that a plugin works with the Maven framework libraries in a given situation, and is done before the plugin is verified as installable by Maven. It does not necessarily need to do and end-to-end functional test of a Maven project. In the matrix, "contextual integration testing" refers to integration testing the plugin with the Maven framework without running an entire project, where "complete integration testing" refers to testing entire Maven projects before installation of the plugin.
Definition: Functional testing for plugins is running an entire Maven build that utilises a given plugin and verifies the output of the build process.
Definition: A form of functional test that would be run in the integration testing phases and checks base functionality for sanity.
Definition: Performance testing is a specialised form of acceptance testing.
Using Surefire alone to test a Mojo
explicit support in the current implementation
no support in any way
support via Surefire
potential support via Surefire
Has a non-snapshot release
Has a non-alpha/beta release
Has an archetype
Can be used for non-Maven testing
Can be used for Maven App testing
Can be used for plugin testing
Can be used for report testing
Ability to run an htmlunit test after conclusion of execution
Unit Testing Specifics
Provides stub factories for creating Maven objects
Provides alternate remote repository handling
Integration/System Testing - Setup and Verification
Able to stage local repository state
Able to compile custom sources
Able to add custom dependencies
Supports pre-build hook
Supports post-build hook for tearDown
Capture Maven exit code and exceptions
Supports ANSI output
Can ignore failures
Can skip execution
Integration/System Testing - Execution
Note: CIT measures potential ability to use the CIT Java Wrappers to execute - however this appears to not yet be implemented completely. Uncertain features are therefore marked with .
Can stage or use a pre-staged local repository
Runs with Surefire
Generates JUnit XML
Can measure coverage using standard techniques
Can be used for contextual integration testing
Run tests against multiple versions of Maven
Run tests against multiple versions of the plugin
Does not pollute source tree on execution
Cleans up anything stored outside target directory
Includes local repository and system temporary directory
Uses unique storage location for all execution files
This is a concurrency issue if it uses the same location.
Isolated from user's environment/settings by default
Can be achieved by passing a separate settings file for those that support it.
Able to run from the IDE regular test functionality
Able to run offline (unless plugin requires it)
Offline by default
Able to run a single test
Able to run wildcard/regex set of tests
Able to run a suite of tests
Able to run in a separate Maven project
Able to run in the same Maven project
Maven home is configurable
Configurable Maven settings file
Configurable individual Maven settings
Configurable working directory
Configurable input/output handlers for Maven
Configurable Maven logger
Can select which projects to run (include/exclude)
Able to run Maven in batch mode
Able to run Maven in debug mode
Able to inherit shell environment
Pass goals to run Maven with
Pass goals to run Maven with in a file
Interpolate goals to run Maven with
Pass properties to run Maven with
Pass properties to run Maven with in a file
Interpolate properties to run Maven with
Pass profiles to run Maven with
Pass profiles to run Maven with in a file
Pass flags to run Maven with
Pass flags to run Maven with in a file
Able to run tests in parallel
Able to timeout tests run in parallel
To be completed once matrix is complete and examples have been generated to decide direction
To be completed based on suggested use and missing needs
- dfabulich: Make maven-verifier share code with maven-invoker. maven-verifier duplicates a number of utilities; its Maven launcher is entirely surpassed by what maven-invoker can do. Verifier should be just a simple library for configuring and verifying maven-invoker runs, intended to be used in JUnit/TestNG.
- IT plugin has grown out of date
- verifier is stable - used in Maven ITs and Surefire ITs
- invoker is stable
- plugin testing harness is stable but alpha
- plugin testing tools/component IT plugin is stable but alpha
John says: "I'm hoping to converge the tools
we're using in the core ITs with those in the maven-component-test-plugin
(used to be maven-plugin-test-plugin), and the maven-invoker-plugin, and
arrive at some single solution (a plugin) that we can use everywhere...but I
haven't even been able to come up with a unified feature list yet."
Plugin Testing Tool documentation discusses the need for a different local repository (need could be reviewed by improving local repo mechanism, so keep that functionality separate). Incorporate doc into final solution. Note disagreement with "test suite maintenance" - integration tests != functional tests, and both should be well designed, not easily adapted from users (though easily executing users's tests and helping them construct well designed tests is a better goal). Note: Not much different between component tool and plugin tool
Test without installation (c.f. staging and unstaging of plugin - implications for concurrent execution) - to Not pollute the local repository (how about using a timestamped version?
Invoker Plugin has a lot of logic in one mojo, and duplicates other plugins
IT plugin is now duplicated with invoker
Plugin Management Plugin seems roughly equivalent to the component IT plugin but for general use. Could be irrelevant under local repository changes.
Test Tools re a library used by component IT - does a couple of file manipulations for tests.
Verifier duplicates a lot of utilities
Runs within src/it, cleans within there
Functional tests are not included in the POM.
Integration tests are not integrated - set up as separate test projects.
Using the separate project with standard Maven IT practices (these are really functional tests?)
Project Info Reports
Does HTMLUnit tests on the output - manually constructs the mojo like a regular IT, uses plugin testing harness.
Quite slow, though.
Adjustments should be revised.
Some other projects implement Maven executors (eg the release plugin). These should simply be migrated to the invoker (adding in any additional functionality as needed) rather than seeking a unified solution at this point. It is unrelated to testing.
Plugins and libraries for testing: