JUnit Platform Suite provides declarative test suite framework with annotations for creating and configuring comprehensive test suites on the JUnit 5 platform.
—
Suite configuration management through parameters and properties files, plus lifecycle hooks for suite setup and teardown operations with comprehensive parameter inheritance control.
Specify configuration key-value pairs for test suite execution, enabling fine-grained control over JUnit Platform behavior and custom test configuration.
/**
* Specifies configuration key-value pairs for the discovery request.
* Can be repeated to specify multiple parameters.
* Combined with parent configuration unless disabled by @DisableParentConfigurationParameters.
*
* @since 1.8
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
@Documented
@Repeatable(ConfigurationParameters.class)
@API(status = STABLE, since = "1.10")
public @interface ConfigurationParameter {
/**
* Configuration parameter key.
* @return key name; never null or blank
*/
String key();
/**
* Value to add for the specified key.
* @return parameter value for the key
*/
String value();
}
/**
* Container for multiple @ConfigurationParameter declarations.
* Automatically used when @ConfigurationParameter is repeated.
*
* @since 1.8
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
@Documented
@API(status = STABLE, since = "1.10")
public @interface ConfigurationParameters {
/**
* Array of configuration parameter declarations.
* @return configuration parameters to apply
*/
ConfigurationParameter[] value();
}Usage Examples:
// Single configuration parameter
@Suite
@SelectPackages("com.example")
@ConfigurationParameter(key = "junit.jupiter.execution.parallel.enabled", value = "true")
class ParallelSuite {
}
// Multiple configuration parameters
@Suite
@SelectPackages("com.example")
@ConfigurationParameter(key = "junit.jupiter.execution.parallel.enabled", value = "true")
@ConfigurationParameter(key = "junit.jupiter.execution.parallel.mode.default", value = "concurrent")
@ConfigurationParameter(key = "junit.jupiter.execution.parallel.config.strategy", value = "dynamic")
class AdvancedParallelSuite {
}
// Custom test configuration
@Suite
@SelectPackages("com.example")
@ConfigurationParameter(key = "test.database.url", value = "jdbc:h2:mem:testdb")
@ConfigurationParameter(key = "test.timeout.default", value = "30s")
@ConfigurationParameter(key = "test.environment", value = "integration")
class CustomConfigSuite {
}Load configuration parameters from properties files on the classpath, enabling externalized configuration management.
/**
* Specifies properties file on classpath for configuration parameters.
* Uses standard Java properties format for key-value pairs.
* Can be repeated to load from multiple resource files.
*
* @since 1.11
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
@Documented
@Repeatable(ConfigurationParametersResources.class)
@API(status = EXPERIMENTAL, since = "1.11")
public @interface ConfigurationParametersResource {
/**
* Classpath location for properties file.
* @return classpath resource path; never null or blank
*/
String value();
}
/**
* Container for multiple @ConfigurationParametersResource declarations.
* Automatically used when @ConfigurationParametersResource is repeated.
*
* @since 1.11
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
@Documented
@API(status = EXPERIMENTAL, since = "1.11")
public @interface ConfigurationParametersResources {
/**
* Array of configuration parameter resource declarations.
* @return resource declarations to load
*/
ConfigurationParametersResource[] value();
}Usage Examples:
// Single properties file
@Suite
@SelectPackages("com.example")
@ConfigurationParametersResource("test-config.properties")
class ResourceConfigSuite {
}
// Multiple properties files
@Suite
@SelectPackages("com.example")
@ConfigurationParametersResource("common-test-config.properties")
@ConfigurationParametersResource("integration-test-config.properties")
class MultiResourceConfigSuite {
}
// Environment-specific configuration
@Suite
@SelectPackages("com.example")
@ConfigurationParametersResource("test-config-${test.env:local}.properties")
class EnvironmentConfigSuite {
}Control how suite configuration parameters are inherited from parent discovery requests.
/**
* Disables parent configuration parameters for the test suite.
* By default, suites use both explicit configuration parameters and
* configuration parameters from the parent discovery request.
* This annotation disables the latter, using only explicit parameters.
*
* Affects both @ConfigurationParameter and @ConfigurationParametersResource.
*
* @since 1.8
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
@Documented
@API(status = STABLE, since = "1.10")
public @interface DisableParentConfigurationParameters {
}Usage Examples:
// Isolated suite configuration
@Suite
@SelectPackages("com.example")
@DisableParentConfigurationParameters
@ConfigurationParameter(key = "junit.jupiter.execution.parallel.enabled", value = "false")
class IsolatedConfigSuite {
}
// Override parent settings
@Suite
@SelectPackages("com.example")
@DisableParentConfigurationParameters
@ConfigurationParametersResource("override-config.properties")
class OverrideConfigSuite {
}Provide setup and teardown capabilities at the suite level, executing before and after all tests in the suite.
/**
* Executed before all tests in the current test suite.
* Method must be static, void return type, and not private.
* Inherited from superclasses if not overridden.
* Multiple methods have deterministic but non-obvious order.
* Recommendation: At most one per test class/interface.
*
* @since 1.11
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
@API(status = EXPERIMENTAL, since = "1.11")
public @interface BeforeSuite {
}
/**
* Executed after all tests in the current test suite.
* Method must be static, void return type, and not private.
* Inherited from superclasses if not overridden.
* Multiple methods have deterministic but non-obvious order.
* Recommendation: At most one per test class/interface.
*
* @since 1.11
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
@API(status = EXPERIMENTAL, since = "1.11")
public @interface AfterSuite {
}Usage Examples:
// Basic lifecycle management
@Suite
@SelectPackages("com.example")
class BasicLifecycleSuite {
@BeforeSuite
static void setupSuite() {
System.setProperty("test.environment", "suite");
// Initialize shared resources
TestDatabase.initialize();
}
@AfterSuite
static void cleanupSuite() {
// Clean up shared resources
TestDatabase.cleanup();
System.clearProperty("test.environment");
}
}
// Complex setup with configuration
@Suite
@SelectPackages("com.example")
@ConfigurationParameter(key = "test.database.url", value = "jdbc:h2:mem:suitedb")
class ComplexLifecycleSuite {
private static TestServer testServer;
@BeforeSuite
static void setupInfrastructure() {
// Start test server
testServer = new TestServer()
.withPort(9999)
.withDatabase("suitedb")
.start();
// Wait for server readiness
testServer.waitForReadiness(Duration.ofSeconds(30));
// Set system properties for tests
System.setProperty("test.server.url", testServer.getUrl());
}
@AfterSuite
static void teardownInfrastructure() {
// Stop test server
if (testServer != null) {
testServer.stop();
}
// Clear system properties
System.clearProperty("test.server.url");
}
}
// Inherited lifecycle methods
class BaseSuite {
@BeforeSuite
static void baseSetup() {
// Base suite setup
}
@AfterSuite
static void baseCleanup() {
// Base suite cleanup
}
}
@Suite
@SelectClasses({SpecificTest.class})
class ExtendedSuite extends BaseSuite {
@BeforeSuite
static void extendedSetup() {
// Extended suite setup (runs after baseSetup)
}
@AfterSuite
static void extendedCleanup() {
// Extended suite cleanup (runs before baseCleanup)
}
}Different configurations for different test environments:
// Local development configuration
@Suite
@SelectPackages("com.example")
@ConfigurationParameter(key = "test.database.url", value = "jdbc:h2:mem:localdb")
@ConfigurationParameter(key = "test.timeout.default", value = "10s")
@ConfigurationParameter(key = "test.parallel.enabled", value = "false")
class LocalDevSuite {
}
// CI/CD configuration
@Suite
@SelectPackages("com.example")
@ConfigurationParameter(key = "test.database.url", value = "${TEST_DB_URL}")
@ConfigurationParameter(key = "test.timeout.default", value = "60s")
@ConfigurationParameter(key = "test.parallel.enabled", value = "true")
@ConfigurationParameter(key = "test.parallel.threads", value = "4")
class CISuite {
}Externalized configuration using properties files:
// Main configuration from resources
@Suite
@SelectPackages("com.example")
@ConfigurationParametersResource("test-defaults.properties")
@ConfigurationParametersResource("test-environment.properties")
class ResourceBasedSuite {
}
// Override with additional parameters
@Suite
@SelectPackages("com.example")
@ConfigurationParametersResource("common-config.properties")
@ConfigurationParameter(key = "test.suite.name", value = "SpecialSuite")
@ConfigurationParameter(key = "test.override.enabled", value = "true")
class OverriddenResourceSuite {
}Complete isolation from parent configuration:
// Completely isolated suite
@Suite
@SelectPackages("com.example")
@DisableParentConfigurationParameters
@ConfigurationParameter(key = "junit.jupiter.execution.parallel.enabled", value = "false")
@ConfigurationParameter(key = "junit.jupiter.testinstance.lifecycle.default", value = "per_class")
class IsolatedSuite {
@BeforeSuite
static void setupIsolatedEnvironment() {
// Setup completely independent environment
}
@AfterSuite
static void cleanupIsolatedEnvironment() {
// Cleanup independent environment
}
}Advanced setup and teardown patterns:
@Suite
@SelectPackages("com.example.integration")
@ConfigurationParametersResource("integration-test-config.properties")
class IntegrationTestSuite {
private static TestCluster testCluster;
private static MockServices mockServices;
@BeforeSuite
static void setupIntegrationEnvironment() {
// Start test cluster
testCluster = TestCluster.builder()
.withServices("database", "cache", "messaging")
.withReplicas(3)
.build()
.start();
// Start mock external services
mockServices = MockServices.builder()
.withPaymentService()
.withEmailService()
.withAuditService()
.start();
// Configure system properties
System.setProperty("integration.cluster.url", testCluster.getConnectionUrl());
System.setProperty("integration.mocks.url", mockServices.getBaseUrl());
// Wait for services to be ready
testCluster.waitForReadiness(Duration.ofMinutes(2));
mockServices.waitForReadiness(Duration.ofSeconds(30));
}
@AfterSuite
static void teardownIntegrationEnvironment() {
try {
// Collect test metrics
if (testCluster != null) {
testCluster.exportMetrics("target/integration-metrics.json");
}
// Stop services
if (mockServices != null) {
mockServices.stop();
}
if (testCluster != null) {
testCluster.stop();
}
} finally {
// Clear system properties
System.clearProperty("integration.cluster.url");
System.clearProperty("integration.mocks.url");
}
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-junit-platform--junit-platform-suite