There are times when you need to build a Maven project without running its tests — a fast sanity build, a deployment pipeline that runs tests in a separate stage, or a temporary workaround while fixing a broken test suite. Maven provides two primary command‑line flags with subtly different behaviour, plus Surefire configuration for finer‑grained control. In this article, we’ll explore all the options, their trade‑offs, and when to use each.
Option 1: -DskipTests (Compile Tests, Don't Run Them)
The most common flag – compiles test classes but skips test execution:
mvn package -DskipTests
mvn install -DskipTests
mvn verify -DskipTests
What happens:
- The
test-compilephase runs – test source files are compiled. - The
testphase is skipped – the compiled tests are never executed. - The build still fails if your test classes have compilation errors (broken imports, renamed methods, type errors in test code).
This is the preferred option in most situations because it catches test compilation failures while saving the time of actually running the tests. It’s also the default behaviour in many CI/CD pipelines where tests are run in a separate stage.
Option 2: -Dmaven.test.skip=true (Don't Even Compile Tests)
A more aggressive skip – completely bypasses test compilation and execution:
mvn package -Dmaven.test.skip=true
mvn install -Dmaven.test.skip=true
What happens:
- The
test-compilephase is skipped – test sources are not compiled at all. - The
testphase is skipped. - Compilation errors in test code are silently ignored – the build proceeds as if the tests didn't exist.
- Slightly faster than
-DskipTestsbecause there's no test compilation step.
Use this when you know your test code doesn't compile (e.g., you're in the middle of a refactor that broke tests you haven't fixed yet) and you just need to produce a JAR or WAR.
Key Difference at a Glance
Default recommendation: use -DskipTests in most cases. Reserve -Dmaven.test.skip=true for situations where test compilation is actively broken and you cannot or don't want to fix it immediately.
More Options: Skipping Test Failures, Ignoring Failures
Maven also provides flags to control what happens when tests do run:
# Continue the build even if tests fail (but still run them)
mvn test -Dmaven.test.failure.ignore=true
# Skip only failing tests? No, but you can use Surefire's re-run capabilities.
The -Dmaven.test.failure.ignore=true property tells Surefire to not fail the build if tests fail.
This is useful in exploratory builds where you want to see all test results, but never use this in CI – it will hide real regressions.
There's also -Dmaven.test.error.ignore (similar) and -Dmaven.test.skip (alias for maven.test.skip).
The property names can be confusing; stick to the documented ones above.
Skipping Tests via Maven Profiles
For more structured control, you can define a Maven profile that sets the skip property only when the profile is active:
<profiles>
<profile>
<id>skip-tests</id>
<properties>
<skipTests>true</skipTests>
</properties>
</profile>
</profiles>
Activate it with:
mvn package -Pskip-tests
This approach keeps your command line clean and allows you to activate the skip from your IDE's Maven runner as well. You can also combine profiles to skip only integration tests:
<profile>
<id>skip-integration-tests</id>
<properties>
<skipITs>true</skipITs> <!-- Failsafe property -->
</properties>
</profile>
Skipping Tests in pom.xml (Not Recommended for Permanent Use)
You can configure skipTests in the Surefire plugin configuration in pom.xml, but this affects every build – including CI – and is easy to forget:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.1.2</version>
<configuration>
<!-- Don't commit this – it will skip tests on every developer's machine and in CI -->
<skipTests>${skipTests}</skipTests>
</configuration>
</plugin>
Using a property placeholder (${skipTests}) lets you keep the pom configuration without hard‑coding the skip – it defaults to false and can be overridden per run with -DskipTests=true.
This is a safe pattern if you want to allow skips via command line, but avoid setting skipTests to true directly in the pom.xml.
Skipping Specific Test Classes with Surefire Excludes
When you need to exclude specific test classes rather than all tests, configure Surefire's <excludes>:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.1.2</version>
<configuration>
<excludes>
<exclude>**/SlowIntegrationTest.java</exclude>
<exclude>**/DatabaseMigrationTest.java</exclude>
</excludes>
</configuration>
</plugin>
The ** glob matches any directory, so this excludes those classes from any package.
You can also use <includes> to run only specific tests.
Running Only Specific Tests
The inverse – run only specific tests and skip everything else:
# Run only a specific test class
mvn test -Dtest=CalculatorTest
# Run only a specific test method
mvn test -Dtest=CalculatorTest#add
# Run tests matching a pattern
mvn test -Dtest="Calculator*"
# Run multiple specific classes (comma separated)
mvn test -Dtest=CalculatorTest,OrderServiceTest
# Combine with -DfailIfNoTests=false to avoid failure if no tests match
mvn test -Dtest=NonExistentTest -DfailIfNoTests=false
When using -Dtest=ClassName, Maven only runs the specified tests and skips all others – useful for debugging a single failing test without the full test run.
Separating Unit Tests from Integration Tests
A better long‑term pattern than skipping tests is separating them into different Maven phases using the Failsafe plugin for integration tests:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>3.1.2</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
With this setup:
mvn testruns only unit tests (Surefire,*Test.javaby default).mvn verifyruns both unit and integration tests (Failsafe,*IT.javaby default).mvn verify -DskipITsskips only integration tests while still running unit tests.
This gives you granular control over what runs in each pipeline stage – a much cleaner approach than skipping all tests.
Decision Matrix: Which Flag to Use?
| Scenario | Recommended Command | Reason |
|---|---|---|
| Quick local build, test code compiles | mvn package -DskipTests | Saves execution time, but catches compilation errors. |
| Local build with broken test code | mvn package -Dmaven.test.skip=true | Bypasses compilation completely – unblocks you. |
| CI pipeline with separate test stage | mvn deploy -DskipTests in deploy stage | Run tests earlier in pipeline; skip them at deploy. |
| Debugging a single test class | mvn test -Dtest=MyTest | Runs only that test, fast iteration. |
| Skip integration tests, run unit tests | mvn verify -DskipITs | Uses Failsafe property – keeps unit tests. |
| Run all tests but don't fail the build | mvn test -Dmaven.test.failure.ignore=true | Collect all failures without breaking build (local only). |
Common Pitfalls and Best Practices
Pitfall: Hard‑coding skip in pom.xml
Never set <skipTests>true</skipTests> directly in your pom.xml – it will be accidentally committed and will skip tests everywhere, including CI.
Use property placeholders or profiles instead.
Pitfall: Forgetting to run tests at all in CI
If you skip tests in your CI build, you might miss regressions.
Always have a dedicated stage that runs tests (possibly with mvn verify) before deployment.
Pitfall: Using -Dmaven.test.skip=true when you only want to skip execution
Many developers mistakenly use the aggressive skip, which hides test compilation errors.
Prefer -DskipTests to keep the safety net.
Best Practice: Use Maven properties for flexibility
Define a property like <skipTests>${skipTests}</skipTests> in your Surefire configuration – this allows overriding via command line without changing the pom.xml.
Best Practice: Separate integration tests with Failsafe
Organise your tests into unit tests (Surefire) and integration tests (Failsafe).
Use the skipITs property to skip only the slow integration tests during rapid development.
Best Practice: Use maven.test.failure.ignore sparingly
Only use this flag in development, never in CI. In CI, test failures should fail the build to prevent deploying broken code.
Best Practice: Combine with -DfailIfNoTests=false
If you use -Dtest=SomeClass and the class doesn't exist, the build will fail.
Add -DfailIfNoTests=false to avoid that (e.g., mvn test -Dtest=SomeTest -DfailIfNoTests=false).
Summary
Maven offers two main ways to skip tests:
-DskipTests– compiles test sources but skips execution. This is the recommended default.-Dmaven.test.skip=true– skips test compilation and execution entirely. Use only when tests don't compile.
For more targeted control, use Surefire's <excludes> or the -Dtest parameter to run only specific tests.
For long‑term project health, separate unit and integration tests with the Failsafe plugin and use -DskipITs to skip only integration tests.
Always run your tests in CI – skipping them is a temporary measure, not a permanent strategy.
Happy building!
No comments :
Post a Comment
Please leave your message queries or suggetions.
Note: Only a member of this blog may post a comment.