Published on

Setting Up Different Test Groups with JUnit 5 and Gradle

Authors

When working with a project, there often comes a time where you need to write integration tests or other specialised tests.

The problem with these tests is that they take longer to run, they need to be set up with special dependencies or/and they have been written to test something somewhat manually (for example if you are testing an integration client and want to confirm the integration by tweaking the test code).

Doing this with JUnit 5 and Gradle ended up being fairly straightforward.

There are 2 parts to getting this working.

  1. You need to annotate (at the class level) the tests you want to be grouped in a certain way
  2. You need to add a Gradle task per group and configure the main test task to exclude one or more groups (where applicable)

For 1. let's start by annotating the Spring Boot application class. In my example below this test is heavier as it uses test containers to test against a real database (testcontainers are not needed at all for this categorisation, but shown here for demo purposes)

package com.my.awesome.company.some.app

import org.junit.jupiter.api.Tag
import org.springframework.boot.test.context.SpringBootTest
import org.testcontainers.junit.jupiter.Container
import org.testcontainers.junit.jupiter.Testcontainers
//...

@Tag("integration")
@Testcontainers
@SpringBootTest
class MyAwesomeApplicationTests {

	@Test
	fun contextLoads() {
	}

//...

//test container setup

companion object {

    @Container
    val container: PostgreSQLContainer<Nothing> = PostgreSQLContainer<Nothing>("postgres:12").apply {
    withDatabaseName("somedb")
    withUsername("postgres")
    withPassword("password")
}


    @Suppress("unused")
    @JvmStatic
    @DynamicPropertySource
    fun properties(registry: DynamicPropertyRegistry) {
        registry.add("spring.datasource.url", container::getJdbcUrl);
        registry.add("spring.datasource.password", container::getPassword);
        registry.add("spring.datasource.username", container::getUsername);
    }
}


}

We can annotate any other classes as above that we want to put in the integration category. We can also of course tag classes with another category for example manual` for manual tests.

Now in our build.gradle we need to configure it as follows:

//...
test {
    useJUnitPlatform {
        excludeTags 'integration', 'manual'
    }
}

task integrationTest(type: Test) {
    useJUnitPlatform {
        includeTags 'integration'
    }
}

task manualTest(type: Test) {
    useJUnitPlatform {
        includeTags 'manual'
    }
}

//...

With the above in place, you can run normal Gradle builds and the 2 new categories will not be run:

gradle build

If you want to explicitly run for example just integration via gradle run:

gradle integration

If you use IntelliJ as your IDE, when you click the run button for a test for the first time, it will prompt you to choose which test group it falls under. If you choose the wrong test group by mistake, simply delete the test run configuration and click the green play button again to choose a different test group.