26

Using a Spring maven context, I would like to run specific tests based on a maven profile. I would like to have an easy way of tagging the test groups. If possible I would like to use the annotations. Which options are there, like maven command line parameters, maven profiles specification, etc.

Say I have the following tests:

Example:

// annotation("integration")
public class GeopointFormatterTest {
    @Test
    public void testIntegration1() {  ...  }   
    @Test
    public void testIntegration2() {  ...  }

Annotations like @Profile (which is for creating beans) and @ActiveProfile (which is for selecting specific profiles for creating beans) cannot be used for selecting tests, of course. All tests just run for statements like:

mvn clean install -Pdevelopment

mvn clean install -Pdevelopment -Dspring.profiles.active=acceptance

mvn clean install -Pdevelopment -Dspring.profiles.active=integration

As suggested, I used also @IfProfileValue. This is a good way for selecting tests based on system property values. System property values can be overruled by a CustomProfileValueSource class, like in: @ProfileValueSourceConfiguration(CustomProfileValueSource.class)

EDIT and ALTERNATIVE

The GREAT answers below focus on JUnit's @Category mechanism. Thanks to all!

A different approach is via these steps: [1] set a property within a maven profile and [2] use the property to skip tests via the of the standard surefire test plugin.

[1] Setting the properties via a profile:

<profiles>
    <profile>
        <id>integrationtests</id>
        <properties>
            <integration.skip>false</integration.skip>
            <acceptance.skip>true</acceptance.skip>
        </properties>
    </profile>
    ... other profiles

[2] Using the properties in the surefire test plugin to skip tests.

<build>
   <plugins>
      <plugin>
         <!-- Run the integration test-->
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-surefire-plugin</artifactId>
         <version>${surefire.plugin.version}</version>
         <configuration>
            <skipTests>${acceptance.skip}</skipTests>

Start in maven: mvn clean install –Pintegrationtests

Community
  • 1
  • 1
tm1701
  • 7,307
  • 17
  • 79
  • 168
  • if your question is answered, consider accepting an answer or providing one yourself and accepting that. This question is still marked as open and having a bounty. – eis Nov 19 '17 at 09:50
  • Also, your added answer seems a bit incomplete - currently it is just running surefire plugin based on maven profile, but without more configuration, it will always run only standard unit tests. – eis Nov 19 '17 at 09:51

5 Answers5

24

Take a look at junit categories.

You'd tag your tests with specific category annotations

public interface FastTests { /* category marker */ }
public interface SlowTests { /* category marker */ }

@Category(SlowTests.class)
public class A {
    @Test public void a() {}
}

then form a suite like

@RunWith(Categories.class)
@IncludeCategory({FastTests.class})
@SuiteClasses({A.class, B.class})
public static class FastTestSuite {
     //
}

And then run it with

mvn -Dtest=FastTestSuite test

Note also that if you don't want to manually specify your unit test case classes in the suite class, you can also use the help of ClasspathSuite and then just limit based on categories.

eis
  • 51,991
  • 13
  • 150
  • 199
  • Thank you. Also a very nice option. Can you do this without a TestSuite? If you don't specify a -Dparameter, will it skip the tests with a category? – tm1701 Nov 18 '17 at 08:20
  • @tjm1706 if you don't specify, then all tests are run. And yes, you can do this without a testsuite, for example in a way that was specified in [this other answer](https://stackoverflow.com/a/47317847/365237) – eis Nov 18 '17 at 16:23
7

You will probably need to categorize your tests using the @Category annotation. A complete example has been provided in the Surefire documentation provided here - search for the string Using JUnit Categories.

Assuming that you have categorized your tests accordingly, you will now be able to setup one or more profiles in your maven build which will trigger these tests as per the category

<profiles>
    <profile>
        <id>slow-tests</id>
        <build>
            <plugins>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.11</version>
                    <configuration>
                        <groups>com.mycompany.SlowTests</groups>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </profile>
    <profile>
        <id>fast-tests</id>
        <build>
            <plugins>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.11</version>
                    <configuration>
                        <groups>com.mycompany.FastTests</groups>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>

You can specify one or more profiles on the command line when running the tests.

mvn test -Pslow-tests,fast-tests
Srikanth Anusuri
  • 1,234
  • 9
  • 16
  • Thank you. Is there a way that when you specify NO profile that only a test is run without a category? – tm1701 Nov 18 '17 at 08:18
  • 1
    You could create a profile which is active by default and exclude the groups that you do not wish to run. Here is more info. https://stackoverflow.com/questions/14132174/how-to-exclude-all-junit4-tests-with-a-given-category-using-maven-surefire – Srikanth Anusuri Nov 19 '17 at 04:42
  • I think the best thing to do is to create a category for those tests you want to run without the -P switch, bundle those test methods in one test class and annotate that test class with the new category you've created. Then in your POM, specify a profile for the new category group and make that profile active by default. So when next you do "mvn test" only those test methods will run – Christian Oliver May 27 '20 at 14:50
4

You can specify the profile with this flag:

mvn test -Dspring.profiles.active=acceptance

In my latest project I have an "integration" profile that I use to run the integration tests against an embedded H2 database.

db80
  • 4,157
  • 1
  • 38
  • 38
1

We did solved categorization of junit in the following steps.

I did create a project for you in github. https://github.com/djaganathan/unit-test-samples

Caveat:- Junit Categorization packages still says as experimental.

1) Created a category of interfaces



    /**
     * This interface used to categories Junit Test
     * those Tests will be executed during bamboo build run
     */
    public interface ReleaseTest {
    }

2) Tagged the unit testcases with the category you want



    import org.junit.Test;
    import org.junit.experimental.categories.Category;
    import org.junit.internal.runners.JUnit4ClassRunner;
    import org.junit.runner.RunWith;

    import com.github.djaganathan.unit.test.category.ReleaseTest;

    @RunWith(JUnit4ClassRunner.class)
    public class GeneralTest {

        @Test
        @Category(value={ReleaseTest.class})
        public void doTestForRelease(){}

        @Test
        public void doTestForDev(){}

    }

3) Create profile in maven and attach to it

4) Run the command as mvn test -PreleaseTest

Dhana
  • 813
  • 1
  • 8
  • 19
  • Thank you. Is there a way that when you specify NO profile that only a test is run without a category? – tm1701 Nov 18 '17 at 08:18
1

Based on the answers of a number of posts, I created a simple test project that demonstrates a number of code quality & testing features:

  • Performing either unit tests OR integration tests with plugins Surefire and Failsafe.
  • Improving code quality via the plugin findbugs.
  • Determine test coverage stats with plugin Jacoco.

Enjoy!

Community
  • 1
  • 1
tm1701
  • 7,307
  • 17
  • 79
  • 168
  • Hi! , I just went through your github project. What I don't understand is, How will maven know it has to run the tests annotated with `@Category(IntegrationTest.class)` But , the profile given is `-Pintegration`. *Where is the mapping for `integration` with `IntegrationTest`.???* Are not they supposed to be same? – Arun Gowda Sep 28 '19 at 14:24
  • 1
    It's some time ago. In the pom.xml file you see IntegrationTest. – tm1701 Sep 28 '19 at 14:27