Mixing TestNG and JUnit tests in one Maven module – 2013 edition

Posted: 2013-03-12 in Tricks & Tips
Tags: , , , , , ,

Recently I wanted to configure an ability to run both TestNG and JUnit tests in one Maven module (project). At the end I managed how to do it clean and short, but before that I have found a few different solutions on the web (top 5 in Google) which part of them didn’t work and the rest applied to the earlier versions of Surefire plugin and was overly complicated (e.g. two separate executions). Therefore I decided to write this short post to show how it could be done in Surefire 2.13 – the newest version available in March 2013.

Mixing those tests frameworks in one module can be done just by adding both JUnit and TestNG as a plugin dependencies (not as project dependencies):

<plugin>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>${surefire.version}</version>
    <dependencies>
        <dependency>
            <groupId>org.apache.maven.surefire</groupId>
            <artifactId>surefire-junit47</artifactId>
            <version>${surefire.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.maven.surefire</groupId>
            <artifactId>surefire-testng</artifactId>
            <version>${surefire.version}</version>
        </dependency>
    </dependencies>
</plugin>

As the result both test types are executed.

[INFO] --- maven-surefire-plugin:2.13:test (default-test) @ junit-testng-poc ---
[INFO] Surefire report directory: /tmp/junit-testng-poc/target/surefire-reports
[INFO] Using configured provider org.apache.maven.surefire.junitcore.JUnitCoreProvider
[INFO] Using configured provider org.apache.maven.surefire.testng.TestNGProvider

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
parallel='none', perCoreThreadCount=true, threadCount=2, useUnlimitedThreads=false
Running info.solidsoft.rnd.junit.testng.SampleJUnitTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.253 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0


-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running TestSuite
Configuring TestNG with: TestNG652Configurator
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.869 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

Why to use TestNG with JUnit together? TestNG has a few features which are unavailable or less flexible in JUnit (just to mention a few: dependencies between tests and groups of tests (irreplaceable for integration tests with long startup), parametrized tests, concurrent execution or per suite/group/class init/shutdown operations). Therefore it is tempting to migrate existing tests from JUnit to TestNG. Having large code base it could be not so easy to migrate all of them at once and presented configuration allows to write the new tests in TestNG and rewrite the old tests when appropriate.

The whole working example can be found in my GitHub repository.

Btw, it is worth to mention that thanks to the fact TestNG generates reports also in the JUnit’s XML format all the tools compatible with JUnit (Jenkins, Sonar, …) will merge test results from JUnit and TestNG and display all of them properly.

Btw2, the same configuration works also with Failsafe plugin.

Btw3, thanks to the fact Spock Framework is under the hood a runner for JUnit presented trick can be used also to mix it with TestNG. This requires some additional work to integrate also Groovy and I plan to write about it in one of my future posts.

Comments
  1. Marcel says:

    Nice post, Marcin :)

  2. Masahiko Sakamoto says:

    Good post ! And I made sample Maven3 project which execute JUnit(Java, Groovy) and TestNG(Java, Groovy) and Spock(Groovy only) test cases at same time (“mvn test”).
    Thank you!!

  3. Masahiko Sakamoto says:

    Sorry, I forgot sample project link : https://github.com/msakamoto-sf/maven3-junit-spock-testng-mixin

  4. Nice post, thanks! That’s a clean solution.

    However, it does not work if you have a TestNG configuration that can’t be found in JUnit. For example, you’re excluding a group in the TestNG tests. The JUnit execution will fail.

    The solution is probably to have 2 profiles but it’s not straightforward anymore.

  5. Xiang says:

    Thanks for the post. Now, the cobertura code coverage finally covers both tests.

    Follow the method in the post, I could see both Junit and TestNG run. The test reports are printed in the console. I have a question for you. I run the same way on Jenkins. From the console output, I could see the Junit and TestNG tests are run and reported. But, from test statistics grid, I could only see the results from one test (whichever run latter).

    Could you please describe how to make the test statistics reported in Jenkins cover both tests?
    Thanks

    • emszpak says:

      Sorry for late reply. Hmm, I would expect JUnit only tests presented in Jenkins – as they are generated to `target/surefire-reports` which (for Maven builds) should be a default directory for JUnit plugin for Jenkins.

      I dig out my old PoC project and I confirmed that TestNG (in addition to XML reports generated in it own format) generates also test result in JUnit format (for tools which do not support TestNG). Those files are placed in `target/surefire-reports/junitreports` directory. So to make them visible by Jenkins you should add also that directory (`target/surefire-reports/junitreports/*.xml`) in the field “Test report XMLs` in Jenkins project configuration.
      As I tested with my (a little bit outdated) PoC TestNG do not override JUnit report in the configuration presented in my post.

  6. Chastina Li says:

    Replacing project dependencies with plugin dependencies?? How?? I removed testng and junit project dependencies and added plugin dependencies but my code doesn’t even compile?

    • emszpak says:

      No, those plugin dependencies (surefire-junit47 and surefire-testng) are in addition to your project dependencies (junit and testng).

  7. virgo47 says:

    A lot of google searching today – and twice I got to this blog. First to the post with most up-to-date Maven config how to run Geb/Spock/Groovy stuff (gmavenplus) – very helpful. And now this, mixing both TestNG and JUnit tests in one module. Thank you very much, both concise and precisely what I needed.

  8. Really helpfull post, would be good if you could update how to run with 2 different context configurations, probably through profiles?

  9. I actually just tried your approach with surefire plugin on 2 test runners one with @RunWith(WebDriverRunner.class) for selenium tests, other class extends AbstractTransactionalTestNGSpringContextTests for testng unit and mocked integration tests, both anotated with @SpringApplicationConfiguration, so they are different contexts. There’s no need to use profiles surefire did the job just great. The only thing is that selenium tests are executed twice.

  10. james roberts says:

    Brilliant! Thank you so much!

Leave a reply to Marcel Cancel reply