preface
The last section introduced junitPerf based on junit4, but you can see that the way you define variables is still not elegant enough.
Does that make it more natural for users to use?
Yes, junit5 brings us even more power.
Read more:
On Performance Testing
Junit4 based on junit4 analysis junitperf source code, junit4 99% of people do not know the secret!
No comparison, no harm
Let’s first review how junit4 is written:
public class HelloWorldTest {
@Rule
public JunitPerfRule junitPerfRule = new JunitPerfRule();
/** * single thread, 1000ms, default output test results in HTML *@throws InterruptedException if any
*/
@Test
@JunitPerfConfig(duration = 1000)
public void helloWorldTest(a) throws InterruptedException {
System.out.println("hello world");
Thread.sleep(20); }}Copy the code
Let’s see how junit5 is written:
public class HelloWorldTest {
@JunitPerfConfig(duration = 1000)
public void helloTest(a) throws InterruptedException {
Thread.sleep(100);
System.out.println("Hello Junit5"); }}Copy the code
JunitPerfRule magically disappeared? How does all this work?
Let’s unravel the mystery of junit5.
Junit5’s more powerful features
@JunitPerfConfig
We just specified a simple @junitperfConfig annotation, so the problem must be in that annotation.
The definition is as follows:
import java.lang.annotation.*;
/** * Execute interface * for each test method condition configuration *@author bbhou
* @version 1.0.0
* @since1.0.0 * /
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})
@ExtendWith(PerfConfigProvider.class)
@TestTemplate
public @interface JunitPerfConfig {
// Attribute omission
}
Copy the code
@Retention and @Target are common Java annotations and will not be covered here.
Let’s focus on the remaining two notes.
@TestTemplate
We used to write a @test annotation when we were writing unit tests, and you’ll notice that junit5 omitted even this annotation.
So where did he go?
The answer is that the @testTemplate annotation, which is used to identify the method as a unit test, is very flexible and powerful.
@ExtendWith
This annotation enables our annotation.
If you look at the name, it’s an extension, the implementation of the extension, which is the class PerfConfigProvider that we specified
PerfConfigProvider
Let’s take a look at the PerfConfigProvider implementation.
public class PerfConfigProvider implements TestTemplateInvocationContextProvider {
@Override
public boolean supportsTestTemplate(ExtensionContext context) {
return context.getTestMethod()
.filter(m -> AnnotationSupport.isAnnotated(m, JunitPerfConfig.class))
.isPresent();
}
@Override
public Stream<TestTemplateInvocationContext> provideTestTemplateInvocationContexts(ExtensionContext context) {
return Stream.of(newPerfConfigContext(context)); }}Copy the code
The implementation is very simple, starting with a filter.
The @junitperfConfig annotation takes effect only if the method is defined.
Here is the context PerfConfigContext for our custom implementation.
PerfConfigContext
PerfConfigContext TestTemplateInvocationContext is achieved, and the native ExtensionContext has carried on the simple packaging.
public class PerfConfigContext implements TestTemplateInvocationContext {
// Omit the internal attributes
@Override
public List<Extension> getAdditionalExtensions(a) {
return Collections.singletonList(
(TestInstancePostProcessor) (testInstance, context) -> {
final Class clazz = testInstance.getClass();
// Group test contexts by test class
ACTIVE_CONTEXTS.putIfAbsent(clazz, new ArrayList<>());
EvaluationContext evaluationContext = new EvaluationContext(testInstance,
method,
DateUtil.getCurrentDateTimeStr());
evaluationContext.loadConfig(perfConfig);
evaluationContext.loadRequire(perfRequire);
StatisticsCalculator statisticsCalculator = perfConfig.statistics().newInstance();
Set<Reporter> reporterSet = getReporterSet();
ACTIVE_CONTEXTS.get(clazz).add(evaluationContext);
try {
new PerformanceEvaluationStatement(evaluationContext,
statisticsCalculator,
reporterSet,
ACTIVE_CONTEXTS.get(clazz),
clazz).evaluate();
} catch (Throwable throwable) {
throw newJunitPerfRuntimeException(throwable); }}); }}Copy the code
At this point, we find ourselves back on the same page as junit4.
Do not understand the small partners can go to see the original implementation, here do not repeat.
The rest is consistent with the original junit4 implementation.
summary
You can see that junit5 gives us a much more flexible extension that allows us to define our own annotations.
This annotation is used to make the user no different from the original junit5 annotation.
Have to sigh a sentence, the Yangtze River after the wave push the wave before, before the wave died on the beach.
The resources
Github.com/houbb/junit…
Github.com/junit-team/…