Punner
Punner is a new parallel JUnit test runner saves your waiting time:
- Usually we have multiple cpu cores.
- We usually have to write test cases contains "sleep" or "wait" to check async results.
Punner also provide good isolation for paralleled running test cases:
- Seperated & clear log outputs. All test logs will NOT be mixed together like other thread based parallel test runners, even in your favorite IntellJ.
- No multi-thread conflict. It is not encouraged to use static or global shared variables which may cause conflict in multiple thread scenario, but if your legacy code can work well with default(seqencial) test runner, it can work with Punner without modifications.
I have used Punner in some projects, usually it can make 2~15x speedup based on test case and cpu cores.
Install
mvn install
Usage
Punner Runner
If you want to enable Punner in your IDE's JUnit Launcher, you can use @RunWith
annotation.
Add Punner dependency in your pom file:
<dependency>
<groupId>com.github.marks-yag</groupId>
<artifactId>punner</artifactId>
<version>${version}</version>
</dependency>
Kotlin:
import com.github.yag.punner.core.Punner
@RunWith(Punner::class)
class Fun {}
Java:
import com.github.yag.punner.core.Punner
@RunWith(Runner.class)
class Fun {}
Then you can run your test cases in IDE with Punner.
Punner Maven Plugin
<!-- Disable default surefire based testing -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.20</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>com.github.marks-yag</groupId>
<artifactId>punner-maven-plugin</artifactId>
<version>${version}</version>
<configuration>
</configuration>
<executions>
<execution>
<id>test</id>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
</plugin>
Configurations
Configuration | Description | Default |
---|---|---|
parallelLevel | Parallel level of test execution, 'c' means cpu cores. | 2c |
overrideDefault | Override default test runner with Punner. | true |
includes | Include pattern of "{full-class-name}.{test-method-name}". Patterns start with "~" means the rest of string is a regex pattern, or the whole string is a wildcast pattern. | All test cases |
excludes | Exclude pattern of "{full-class-name}.{test-method-name}". Patterns start with "~" means the rest of string is a regex pattern, or the whole string is a wildcast pattern. | None |
skipTests | Skip test execution phase. | false |
Utilities
Punner also provide some useful utility function for unit test:
Eventually
eventually(5000) {
Assert.assertTrue(job.done())
}
Aways
always(5000) {
Assert.assertTrue(consistency.ok())
}
Delay
setTimeout(3000) {
queue.resize(10)
}
Probability
repeat(1000) {
probability(0.01) {
injectTimeout()
}.otherwise {
injectError()
}
}