Configuration
Configure Verifyica for your testing needs
Verifyica provides flexible configuration options to control test execution, parallelism, filtering, and behavior.
Configuration Methods
Verifyica can be configured through:
- Properties File -
verifyica.properties in the classpath - System Properties -
-D flags passed to the JVM - Environment Variables - Environment variables with
VERIFYICA_ prefix
Quick Configuration Topics
Properties
Configure engine behavior, parallelism, logging, and more through properties.
Learn more about Properties →
Filters
Use YAML-based filters to include or exclude tests by class name, package, or tags.
Learn more about Filters →
Parallelism
Control how many classes, arguments, and tests execute in parallel.
Learn more about Parallelism →
Configuration Priority
When the same property is defined in multiple places, the priority is:
- System Properties (highest priority)
- Environment Variables
- Properties File (lowest priority)
Example:
# Properties file: parallelism = 2
# System property overrides it
java -Dverifyica.engine.argument.parallelism=4 -jar test.jar
# Result: parallelism = 4
Configuration File Location
The verifyica.properties file should be placed in:
src/test/resources/verifyica.properties
Example verifyica.properties:
# Class-level parallelism
verifyica.engine.class.parallelism=4
# Argument-level parallelism
verifyica.engine.argument.parallelism=2
# Thread type (virtual, platform, platform-ephemeral)
verifyica.engine.thread.type=virtual
# Filter definitions file
verifyica.engine.filter.definitions.filename=verifyica.engine.filter.definitions.yaml
# Logger configuration
verifyica.engine.logger.level=INFO
Next Steps
1 - Properties
Complete reference for all Verifyica configuration properties
This page provides a complete reference for all Verifyica configuration properties.
Properties can be set in three ways:
1. Properties File
Create src/test/resources/verifyica.properties:
verifyica.engine.argument.parallelism=4
verifyica.engine.thread.type=virtual
2. System Properties
Pass as JVM arguments:
java -Dverifyica.engine.argument.parallelism=4 -jar test.jar
3. Environment Variables
Set environment variables (replace . with _ and uppercase):
export VERIFYICA_ENGINE_ARGUMENT_PARALLELISM=4
Parallelism Properties
verifyica.engine.class.parallelism
Controls how many test classes execute in parallel.
- Type: Integer
- Default:
1 (sequential) - Example:
verifyica.engine.class.parallelism=4
Usage:
# Run 4 test classes in parallel
verifyica.engine.class.parallelism=4
verifyica.engine.argument.parallelism
Controls how many arguments within a class execute in parallel.
- Type: Integer
- Default:
1 (sequential) - Example:
verifyica.engine.argument.parallelism=2
Note: This is a default value. Individual @ArgumentSupplier annotations can override this:
@Verifyica.ArgumentSupplier(parallelism = 4) // Overrides default
public static Collection<String> arguments() {
return generateArguments();
}
Usage:
# Run 2 arguments in parallel by default
verifyica.engine.argument.parallelism=2
Thread Configuration
verifyica.engine.thread.type
Configures the type of threads used for parallel execution.
- Type: String
- Values:
virtual, platform, platform-ephemeral - Default:
platform - Example:
verifyica.engine.thread.type=virtual
Options:
| Value | Description | Best For |
|---|
virtual | Java 21+ virtual threads | High concurrency, I/O-bound tests |
platform | Platform threads (traditional) | CPU-bound tests, Java 8+ |
platform-ephemeral | Platform threads that are discarded after use | Tests with thread-local state |
Usage:
# Use virtual threads (requires Java 21+)
verifyica.engine.thread.type=virtual
# Use platform threads (default)
verifyica.engine.thread.type=platform
# Use ephemeral platform threads
verifyica.engine.thread.type=platform-ephemeral
Virtual Threads Example:
Virtual threads are ideal for I/O-bound tests with high concurrency:
verifyica.engine.thread.type=virtual
verifyica.engine.argument.parallelism=100 # Can handle many more with virtual threads
State Machine Throttling
These properties control how fast state machines transition, useful for debugging.
verifyica.engine.class.state.machine.throttle
Throttle class-level state machine transitions.
- Type: Two integers (min, max) in milliseconds
- Default:
0, 1000 - Example:
verifyica.engine.class.state.machine.throttle=100, 500
verifyica.engine.argument.state.machine.throttle
Throttle argument-level state machine transitions.
- Type: Two integers (min, max) in milliseconds
- Default:
0, 1000 - Example:
verifyica.engine.argument.state.machine.throttle=100, 500
verifyica.engine.test.state.machine.throttle
Throttle test-level state machine transitions.
- Type: Two integers (min, max) in milliseconds
- Default:
0, 1000 - Example:
verifyica.engine.test.state.machine.throttle=100, 500
Usage:
Useful for debugging timing issues or simulating slow operations:
# Add random delay between 0-1000ms to state transitions
verifyica.engine.argument.state.machine.throttle=0, 1000
Logging Properties
verifyica.engine.logger.level
Sets the logging level for Verifyica’s internal logger.
- Type: String
- Values:
ALL, TRACE, DEBUG, INFO, WARN, ERROR, OFF - Default:
INFO - Example:
verifyica.engine.logger.level=DEBUG
Usage:
# Enable debug logging
verifyica.engine.logger.level=DEBUG
# Disable all logging
verifyica.engine.logger.level=OFF
# Only errors
verifyica.engine.logger.level=ERROR
verifyica.engine.logger.regex
Filter log messages by regex pattern.
- Type: Regular expression
- Default: (none - all messages logged)
- Example:
verifyica.engine.logger.regex=.*TestContainer.*
Usage:
# Only log messages containing "TestContainer"
verifyica.engine.logger.regex=.*TestContainer.*
# Only log messages from specific package
verifyica.engine.logger.regex=com\\.example\\.tests\\..*
Stack Trace Configuration
verifyica.engine.prune.stacktraces
Controls whether stack traces are pruned to remove framework internals.
- Type: Boolean
- Default:
false - Example:
verifyica.engine.prune.stacktraces=true
Usage:
# Prune stack traces for cleaner output
verifyica.engine.prune.stacktraces=true
Effect:
Without pruning:
at com.example.MyTest.testMethod(MyTest.java:42)
at org.verifyica.engine.internal.TestExecutor.execute(TestExecutor.java:123)
at org.verifyica.engine.internal.ArgumentProcessor.process(ArgumentProcessor.java:456)
at org.verifyica.engine.internal.ClassProcessor.process(ClassProcessor.java:789)
... 50 more framework lines
With pruning:
at com.example.MyTest.testMethod(MyTest.java:42)
Filter Configuration
verifyica.engine.filter.definitions.filename
Specifies the YAML file containing filter definitions.
- Type: String (filename)
- Default:
verifyica.engine.filter.definitions.yaml - Example:
verifyica.engine.filter.definitions.filename=my-filters.yaml
Usage:
# Use custom filter file
verifyica.engine.filter.definitions.filename=my-filters.yaml
See Filters for complete filter documentation.
Interceptor Configuration
These properties control which interceptors are automatically discovered and loaded.
verifyica.engine.autowired.engine.interceptors.exclude.regex
Exclude EngineInterceptors by regex pattern.
- Type: Regular expression
- Default: (none)
- Example:
verifyica.engine.autowired.engine.interceptors.exclude.regex=.*Debug.*
verifyica.engine.autowired.engine.interceptors.include.regex
Include only EngineInterceptors matching regex pattern.
- Type: Regular expression
- Default: (none - all included)
- Example:
verifyica.engine.autowired.engine.interceptors.include.regex=com\\.example\\..*
verifyica.engine.autowired.class.interceptors.exclude.regex
Exclude ClassInterceptors by regex pattern.
- Type: Regular expression
- Default: (none)
- Example:
verifyica.engine.autowired.class.interceptors.exclude.regex=.*Debug.*
verifyica.engine.autowired.class.interceptors.include.regex
Include only ClassInterceptors matching regex pattern.
- Type: Regular expression
- Default: (none - all included)
- Example:
verifyica.engine.autowired.class.interceptors.include.regex=com\\.example\\..*
Usage:
# Only load interceptors from specific package
verifyica.engine.autowired.class.interceptors.include.regex=com\\.example\\.interceptors\\..*
# Exclude debug interceptors in production
verifyica.engine.autowired.class.interceptors.exclude.regex=.*Debug.*
Maven Plugin Properties
These properties configure the Maven plugin behavior.
verifyica.maven.plugin.log.tests
Controls whether the Maven plugin logs test execution.
- Type: Boolean
- Default:
false - Example:
verifyica.maven.plugin.log.tests=true
Usage:
# Enable test logging in Maven plugin
verifyica.maven.plugin.log.tests=true
verifyica.maven.plugin.log.timing.units
Sets the time unit for Maven plugin timing logs.
- Type: String
- Values:
nanoseconds, microseconds, milliseconds, seconds - Default:
milliseconds - Example:
verifyica.maven.plugin.log.timing.units=seconds
Usage:
# Log timing in seconds
verifyica.maven.plugin.log.timing.units=seconds
Complete Configuration Example
Here’s a comprehensive verifyica.properties file:
# Parallelism Configuration
verifyica.engine.class.parallelism=4
verifyica.engine.argument.parallelism=2
# Thread Configuration
verifyica.engine.thread.type=virtual
# Logging Configuration
verifyica.engine.logger.level=INFO
verifyica.engine.logger.regex=
# Stack Trace Configuration
verifyica.engine.prune.stacktraces=true
# Filter Configuration
verifyica.engine.filter.definitions.filename=verifyica.engine.filter.definitions.yaml
# Interceptor Configuration
verifyica.engine.autowired.class.interceptors.include.regex=com\\.example\\.interceptors\\..*
verifyica.engine.autowired.class.interceptors.exclude.regex=.*Debug.*
# Maven Plugin Configuration
verifyica.maven.plugin.log.tests=true
verifyica.maven.plugin.log.timing.units=milliseconds
Environment-Specific Configuration
Development
verifyica.engine.argument.parallelism=1 # Sequential for easier debugging
verifyica.engine.logger.level=DEBUG
verifyica.engine.prune.stacktraces=false # Full stack traces
CI/CD
verifyica.engine.class.parallelism=4
verifyica.engine.argument.parallelism=4
verifyica.engine.thread.type=virtual
verifyica.engine.logger.level=INFO
verifyica.engine.prune.stacktraces=true
Production Integration Tests
verifyica.engine.argument.parallelism=1 # Sequential for stability
verifyica.engine.logger.level=WARN
verifyica.engine.prune.stacktraces=true
Next Steps
2 - Filters
Include or exclude tests using YAML-based filters
Verifyica provides a powerful YAML-based filtering system to control which tests execute based on class names, packages, tags, and patterns.
Filter Configuration File
Filters are defined in a YAML file, by default verifyica.engine.filter.definitions.yaml in the classpath.
Location
Place the filter file in:
src/test/resources/verifyica.engine.filter.definitions.yaml
Custom Filename
Configure a custom filename via properties:
verifyica.engine.filter.definitions.filename=my-filters.yaml
Filter Structure
The filter file has two main sections: include and exclude.
Basic Structure
include:
- # Include filters
exclude:
- # Exclude filters
Filter Priority
- Exclude filters are evaluated first
- Include filters are evaluated second
- If a test matches an exclude filter, it’s excluded regardless of include filters
- If no include filters are specified, all tests (not excluded) are included
Filter Types
Class Name Filters
Filter by exact class name:
include:
- className: "com.example.tests.DatabaseTest"
- className: "com.example.tests.ApiTest"
Package Filters
Filter by package name:
include:
- packageName: "com.example.tests.integration"
- packageName: "com.example.tests.unit"
Pattern Filters
Use regex patterns for flexible matching:
include:
- pattern: ".*IntegrationTest"
- pattern: "com\\.example\\.tests\\..*Test"
Tag Filters
Filter by @Tag annotations:
include:
- tag: "fast"
- tag: "unit"
exclude:
- tag: "slow"
- tag: "integration"
Tests are tagged using the @Tag annotation:
@Tag("fast")
@Tag("unit")
public class FastUnitTest {
// Tests...
}
Complete Filter Examples
Example 1: Run Only Integration Tests
include:
- tag: "integration"
Example 2: Exclude Slow Tests
Example 3: Run Only Specific Package
include:
- packageName: "com.example.tests.critical"
Example 4: Complex Filtering
include:
# Include all integration tests
- tag: "integration"
# Include all tests in critical package
- packageName: "com.example.tests.critical"
# Include tests matching pattern
- pattern: ".*SmokeTest"
exclude:
# Exclude slow tests
- tag: "slow"
# Exclude experimental tests
- tag: "experimental"
# Exclude specific class
- className: "com.example.tests.BrokenTest"
Example 5: Environment-Specific Filters
CI environment (fast tests only):
include:
- tag: "ci"
- tag: "fast"
exclude:
- tag: "slow"
- tag: "manual"
Local development (all except slow):
Production validation (critical tests only):
include:
- tag: "critical"
- tag: "smoke"
Single Tag
import org.verifyica.api.Tag;
@Tag("integration")
public class IntegrationTest {
// Tests...
}
@Tag("integration")
@Tag("database")
@Tag("slow")
public class DatabaseIntegrationTest {
// Tests...
}
Tags can be placed on individual test methods:
public class MixedTest {
@Verifyica.Test
@Tag("fast")
public void fastTest(String argument) {
// Fast test
}
@Verifyica.Test
@Tag("slow")
public void slowTest(String argument) {
// Slow test
}
}
Note: Method-level tags require class-level filtering to work correctly. If the class is excluded, method-level tags won’t be evaluated.
Filter Matching Logic
Multiple Filters of Same Type (OR logic)
Multiple filters of the same type use OR logic:
include:
- tag: "unit"
- tag: "integration"
This includes tests with tag “unit” OR “integration”.
Different Filter Types (AND logic)
Different filter types use AND logic:
include:
- packageName: "com.example.tests"
- tag: "integration"
This includes tests in package “com.example.tests” AND with tag “integration”.
Exclude Takes Precedence
include:
- tag: "integration"
exclude:
- className: "com.example.tests.BrokenIntegrationTest"
BrokenIntegrationTest is excluded even though it has the “integration” tag.
Common Filter Patterns
Run Only Unit Tests
Run Everything Except Slow Tests
Run Only Tests in Specific Package
include:
- packageName: "com.example.tests.smoke"
Run Integration Tests Except Database Tests
include:
- tag: "integration"
exclude:
- tag: "database"
Run All Tests Ending with “SmokeTest”
include:
- pattern: ".*SmokeTest"
Dynamic Filter Files
Maven Profiles
Use Maven profiles to switch filter files:
<profiles>
<profile>
<id>ci</id>
<build>
<resources>
<resource>
<directory>src/test/resources/filters</directory>
<includes>
<include>ci-filters.yaml</include>
</includes>
<targetPath>.</targetPath>
<filtering>false</filtering>
</resource>
</resources>
</build>
<properties>
<verifyica.engine.filter.definitions.filename>ci-filters.yaml</verifyica.engine.filter.definitions.filename>
</properties>
</profile>
</profiles>
Run with: mvn test -Pci
Environment-Based Configuration
Use system properties to switch filters:
# Use CI filters
mvn test -Dverifyica.engine.filter.definitions.filename=ci-filters.yaml
# Use integration test filters
mvn test -Dverifyica.engine.filter.definitions.filename=integration-filters.yaml
Troubleshooting Filters
No Tests Run
If no tests execute after adding filters:
- Check filter syntax - Ensure YAML is valid
- Verify tags - Ensure tests have matching tags
- Check exclusions - Exclude filters may be too broad
- Enable debug logging:
verifyica.engine.logger.level=DEBUG
Unexpected Tests Run
If unexpected tests execute:
- Check include filters - May be too broad
- Verify tag spelling - Tags are case-sensitive
- Check pattern syntax - Regex patterns must be escaped correctly
Filter Not Applied
If filters aren’t working:
- Verify file location - Must be in classpath (src/test/resources)
- Check filename - Default is
verifyica.engine.filter.definitions.yaml - Validate YAML syntax - Use a YAML validator
Best Practices
Use Descriptive Tag Names
// Good: Clear, descriptive tags
@Tag("database-integration")
@Tag("requires-docker")
@Tag("slow")
// Bad: Cryptic tags
@Tag("t1")
@Tag("x")
// Execution speed
@Tag("fast") // < 1 second
@Tag("medium") // 1-10 seconds
@Tag("slow") // > 10 seconds
// Test type
@Tag("unit")
@Tag("integration")
@Tag("e2e")
// Dependencies
@Tag("requires-database")
@Tag("requires-docker")
@Tag("requires-network")
Document Filter Files
# CI Filter Configuration
# Runs fast, critical tests suitable for PR validation
include:
- tag: "fast"
- tag: "critical"
exclude:
- tag: "slow"
- tag: "flaky" # Exclude flaky tests from CI
Keep Filter Files Simple
Start with simple filters and add complexity only as needed:
# Simple: Good starting point
include:
- tag: "ci"
# Complex: Only if needed
include:
- tag: "integration"
- packageName: "com.example.critical"
- pattern: ".*SmokeTest"
exclude:
- tag: "slow"
- tag: "flaky"
- className: "com.example.BrokenTest"
Next Steps
3 - Parallelism
Configure parallel test execution at class, argument, and test levels
Verifyica provides three levels of parallelism control to optimize test execution time while maintaining test isolation.
Parallelism Levels
Verifyica supports parallelism at three levels:
- Class-level - Multiple test classes execute in parallel
- Argument-level - Multiple arguments within a class execute in parallel
- Test-level - Multiple test methods within an argument execute in parallel
Class-Level Parallelism
Control how many test classes execute concurrently.
Configuration
verifyica.engine.class.parallelism=4
Example
With class.parallelism=4:
TestClass1 (Thread 1)
TestClass2 (Thread 2)
TestClass3 (Thread 3)
TestClass4 (Thread 4)
TestClass5 (waits for a thread to become available)
Recommendations
- Small test suites:
1-2 - Medium test suites:
2-4 - Large test suites:
4-8 - CI/CD with many cores: Match available CPU cores
Argument-Level Parallelism
Control how many arguments within a test class execute concurrently.
Configuration
Default for all classes:
verifyica.engine.argument.parallelism=2
Per-class override:
@Verifyica.ArgumentSupplier(parallelism = 4)
public static Collection<String> arguments() {
return generateArguments();
}
Example
With parallelism = 2 and 5 arguments:
For TestClass1:
arg1 (Thread 1)
arg2 (Thread 2)
arg3 (waits for Thread 1 or 2)
arg4 (waits)
arg5 (waits)
When to Use
Good candidates for high parallelism:
- Independent test arguments
- I/O-bound tests (database, network, file operations)
- Tests with significant wait times
- Container-based tests
Keep parallelism low (1-2) when:
- Tests share mutable state
- Tests use limited resources (ports, database connections)
- Tests are CPU-intensive
- Debugging tests
Example: Independent Arguments
@Verifyica.ArgumentSupplier(parallelism = 4)
public static Collection<Argument<Config>> arguments() {
// Each config is completely independent
return Arrays.asList(
Argument.of("h2", new Config("jdbc:h2:mem:test1")),
Argument.of("postgres", new Config("jdbc:postgresql://localhost/test2")),
Argument.of("mysql", new Config("jdbc:mysql://localhost/test3")),
Argument.of("oracle", new Config("jdbc:oracle://localhost/test4"))
);
}
Example: Resource-Constrained
@Verifyica.ArgumentSupplier(parallelism = 1)
public static Collection<Argument<Integer>> arguments() {
// All use same port - must be sequential
return Arrays.asList(
Argument.of("port-8080", 8080),
Argument.of("port-8080-again", 8080) // Would conflict if parallel
);
}
Test-Level Parallelism
Control how many test methods within an argument execute concurrently.
Warning: Test-level parallelism requires careful state management to avoid race conditions.
Configuration
# Currently not configurable via annotation
# Controlled globally via properties
# (Check latest documentation for current support)
Thread Safety Requirements
If test methods run in parallel within an argument:
- Instance variables must be thread-safe
- Use thread-safe collections
- Synchronize access to shared state
Example: Parallel-Safe Tests
public class ParallelSafeTest {
private final AtomicInteger counter = new AtomicInteger(0);
private final Connection connection; // Shared, must be thread-safe
@Verifyica.BeforeAll
public void beforeAll(Config config) {
connection = database.connect(config);
}
@Verifyica.Test
public void test1(Config config) {
int value = counter.incrementAndGet(); // Thread-safe
connection.execute("SELECT " + value); // Connection must be thread-safe!
}
@Verifyica.Test
public void test2(Config config) {
int value = counter.incrementAndGet(); // Thread-safe
connection.execute("SELECT " + value);
}
}
Thread Types
Configure the type of threads used for parallel execution.
Configuration
verifyica.engine.thread.type=virtual
Thread Type Options
| Type | Description | Best For | Java Version |
|---|
virtual | Java virtual threads | High concurrency, I/O-bound | Java 21+ |
platform | Traditional OS threads | CPU-bound, Java 8+ | Java 8+ |
platform-ephemeral | Threads discarded after use | ThreadLocal state isolation | Java 8+ |
Virtual Threads (Java 21+)
Virtual threads enable massive concurrency with minimal overhead:
verifyica.engine.thread.type=virtual
verifyica.engine.argument.parallelism=100
Benefits:
- Extremely lightweight (1000s of virtual threads possible)
- Ideal for I/O-bound operations
- Minimal memory footprint
Example:
// With virtual threads, high parallelism is practical
@Verifyica.ArgumentSupplier(parallelism = 50)
public static Collection<String> arguments() {
// 50 concurrent arguments with minimal overhead
return IntStream.range(0, 1000)
.mapToObj(i -> "arg-" + i)
.collect(Collectors.toList());
}
Traditional OS threads:
verifyica.engine.thread.type=platform
verifyica.engine.argument.parallelism=4
Benefits:
- Compatible with all Java versions
- Predictable behavior
- Better for CPU-bound operations
Platform threads that are discarded after use:
verifyica.engine.thread.type=platform-ephemeral
Benefits:
- Isolates ThreadLocal state between arguments
- Prevents ThreadLocal memory leaks
- Useful for tests that use ThreadLocal
Parallelism Best Practices
Start Sequential, Then Parallelize
// Step 1: Get tests working sequentially
@Verifyica.ArgumentSupplier(parallelism = 1)
public static Collection<String> arguments() {
return generateArguments();
}
// Step 2: Once stable, increase parallelism
@Verifyica.ArgumentSupplier(parallelism = 4)
public static Collection<String> arguments() {
return generateArguments();
}
Match Parallelism to Resources
// Good: Parallelism matches available database connections
private static final int MAX_CONNECTIONS = 4;
@Verifyica.ArgumentSupplier(parallelism = 4)
public static Collection<Config> arguments() {
// 4 arguments can run in parallel with 4 connections
return generateConfigs();
}
Use Virtual Threads for I/O-Bound Tests
# I/O-bound tests (network, database, files)
verifyica.engine.thread.type=virtual
verifyica.engine.argument.parallelism=20
# CPU-bound tests (computation, algorithms)
verifyica.engine.thread.type=platform
verifyica.engine.argument.parallelism=4
Isolate State for Parallel Execution
// Good: Isolated state per argument using context classes
public class IsolatedTest {
// Define a context class to encapsulate per-argument state
public static class TestContext {
private final Connection connection;
public TestContext(Connection connection) {
this.connection = connection;
}
public Connection getConnection() {
return connection;
}
}
@Verifyica.ArgumentSupplier(parallelism = 4)
public static Collection<Argument<Config>> arguments() {
return getArguments();
}
@Verifyica.BeforeAll
public void beforeAll(ArgumentContext argumentContext) {
Config config = argumentContext.getArgument().getPayloadAs(Config.class);
Connection conn = database.connect(config);
// Store context in ArgumentContext map (thread-safe)
TestContext context = new TestContext(conn);
argumentContext.getMap().put("testContext", context);
}
@Verifyica.Test
public void test(ArgumentContext argumentContext) {
TestContext context = (TestContext) argumentContext.getMap().get("testContext");
context.getConnection().execute("SELECT 1");
}
@Verifyica.AfterAll
public void afterAll(ArgumentContext argumentContext) {
TestContext context = (TestContext) argumentContext.getMap().get("testContext");
if (context != null && context.getConnection() != null) {
context.getConnection().close();
}
}
}
// Bad: Shared mutable instance variable with parallelism
public class SharedStateTest {
private Connection connection; // UNSAFE: race condition with parallel arguments!
@Verifyica.ArgumentSupplier(parallelism = 4)
public static Collection<Config> arguments() {
return getConfigs();
}
@Verifyica.BeforeAll
public void beforeAll(Config config) {
connection = database.connect(config); // Race condition!
}
@Verifyica.Test
public void test(Config config) {
connection.execute("SELECT 1"); // May use wrong connection!
}
}
Use interceptors to measure the impact of parallelism:
public class PerformanceInterceptor implements ClassInterceptor {
private long startTime;
@Override
public void prePrepare(ClassContext classContext, Method method) {
startTime = System.currentTimeMillis();
}
@Override
public void postConclude(ClassContext classContext, Method method, Throwable throwable) {
long duration = System.currentTimeMillis() - startTime;
String className = classContext.getTestClass().getSimpleName();
System.out.printf("%s completed in %d ms%n", className, duration);
}
}
Parallelism Troubleshooting
Tests Fail Only When Parallel
Symptoms:
- Tests pass with
parallelism=1 - Tests fail with
parallelism>1
Causes:
- Shared mutable state
- Race conditions
- Resource contention
- Improper synchronization
Solution:
// Use thread-safe collections
private final ConcurrentHashMap<String, Result> results = new ConcurrentHashMap<>();
// Use atomic operations
private final AtomicInteger counter = new AtomicInteger(0);
// Synchronize access to shared resources
private synchronized void updateSharedState() {
// Critical section
}
Tests Are Slower with Parallelism
Causes:
- Too much parallelism (thread overhead)
- Resource contention (database, CPU)
- Shared locks or bottlenecks
Solution:
# Reduce parallelism
verifyica.engine.argument.parallelism=2
# Try different thread type
verifyica.engine.thread.type=platform
Deadlocks or Hangs
Causes:
- Circular dependencies
- Resource exhaustion
- Improper locking
Solution:
# Disable parallelism for debugging
verifyica.engine.argument.parallelism=1
# Enable debug logging
verifyica.engine.logger.level=DEBUG
Example 1: TestContainers with Parallelism
@Verifyica.ArgumentSupplier(parallelism = 3)
public static Collection<Argument<Container>> arguments() {
// Start 3 containers in parallel
return Arrays.asList(
Argument.of("nginx", new NginxContainer()),
Argument.of("postgres", new PostgreSQLContainer()),
Argument.of("redis", new RedisContainer())
);
}
With parallelism:
- Sequential: 90 seconds (30s × 3)
- Parallel (3): 30 seconds (3 containers start simultaneously)
Example 2: API Testing
@Verifyica.ArgumentSupplier(parallelism = 10)
public static Collection<String> arguments() {
// Test 100 API endpoints
return generateEndpoints(); // Returns 100 endpoints
}
With parallelism=10 and virtual threads:
- Sequential: 1000 seconds (10s × 100)
- Parallel (10): 100 seconds (10 at a time)
Configuration Examples
Development Environment
# Low parallelism for easier debugging
verifyica.engine.class.parallelism=1
verifyica.engine.argument.parallelism=1
verifyica.engine.thread.type=platform
verifyica.engine.logger.level=DEBUG
CI/CD Environment
# High parallelism for speed
verifyica.engine.class.parallelism=8
verifyica.engine.argument.parallelism=4
verifyica.engine.thread.type=virtual
verifyica.engine.logger.level=INFO
Integration Testing
# Moderate parallelism, balanced for resources
verifyica.engine.class.parallelism=2
verifyica.engine.argument.parallelism=2
verifyica.engine.thread.type=platform
Next Steps