diff --git a/junitperf-junit5/src/main/java/com/github/noconnor/junitperf/JUnitPerfInterceptor.java b/junitperf-junit5/src/main/java/com/github/noconnor/junitperf/JUnitPerfInterceptor.java index f8be057..d5d58d4 100644 --- a/junitperf-junit5/src/main/java/com/github/noconnor/junitperf/JUnitPerfInterceptor.java +++ b/junitperf-junit5/src/main/java/com/github/noconnor/junitperf/JUnitPerfInterceptor.java @@ -46,11 +46,11 @@ public class JUnitPerfInterceptor implements InvocationInterceptor, TestInstance @Override public void postProcessTestInstance(Object testInstance, ExtensionContext context) throws Exception { - + SuiteRegistry.register(context); - + JUnitPerfReportingConfig reportingConfig = findTestActiveConfigField(testInstance, context); - + if (nonNull(reportingConfig)) { activeReporters = reportingConfig.getReportGenerators(); activeStatisticsCalculator = reportingConfig.getStatisticsCalculatorSupplier().get(); @@ -134,12 +134,12 @@ protected JUnitPerfTest getJUnitPerfTestDetails(Method method, ExtensionContext JUnitPerfTest classAnnotation = method.getDeclaringClass().getAnnotation(JUnitPerfTest.class); JUnitPerfTest suiteAnnotation = SuiteRegistry.getPerfTestData(ctxt); // Precedence: method, then class, then suite - JUnitPerfTest specifiedAnnotation = nonNull(methodAnnotation) ? methodAnnotation : classAnnotation; + JUnitPerfTest specifiedAnnotation = nonNull(methodAnnotation) ? methodAnnotation : classAnnotation; return nonNull(specifiedAnnotation) ? specifiedAnnotation : suiteAnnotation; } protected EvaluationContext createEvaluationContext(Method method, boolean isAsync) { - EvaluationContext ctx = new EvaluationContext(method.getName(), nanoTime(), isAsync); + EvaluationContext ctx = new EvaluationContext(method.getName(), nanoTime(), isAsync); ctx.setGroupName(method.getDeclaringClass().getSimpleName()); return ctx; } @@ -158,14 +158,23 @@ private static void warnIfNonStatic(Field field) { } private static JUnitPerfReportingConfig findTestActiveConfigField(Object testInstance, ExtensionContext ctxt) throws IllegalAccessException { - for (Field field : testInstance.getClass().getDeclaredFields()) { + Class testClass = testInstance.getClass(); + JUnitPerfReportingConfig config = scanForReportingConfig(testInstance, testClass); + return isNull(config) ? SuiteRegistry.getReportingConfig(ctxt) : config; + } + + private static JUnitPerfReportingConfig scanForReportingConfig(Object testInstance, Class testClass) throws IllegalAccessException { + if (isNull(testClass)) { + return null; + } + for (Field field : testClass.getDeclaredFields()) { if (field.isAnnotationPresent(JUnitPerfTestActiveConfig.class)) { warnIfNonStatic(field); field.setAccessible(true); return (JUnitPerfReportingConfig) field.get(testInstance); } } - return SuiteRegistry.getReportingConfig(ctxt); + return scanForReportingConfig(testInstance, testClass.getSuperclass()); } } diff --git a/junitperf-junit5/src/test/java/com/github/noconnor/junitperf/JUnitPerfInterceptorTest.java b/junitperf-junit5/src/test/java/com/github/noconnor/junitperf/JUnitPerfInterceptorTest.java index 9dd2ba2..ab91fb6 100644 --- a/junitperf-junit5/src/test/java/com/github/noconnor/junitperf/JUnitPerfInterceptorTest.java +++ b/junitperf-junit5/src/test/java/com/github/noconnor/junitperf/JUnitPerfInterceptorTest.java @@ -231,13 +231,34 @@ void whenASuiteAnnotationsAreAvailable_thenSuiteAnnotationsShouldBeUsed() throws } - private static void mockActiveSuite(ExtensionContext extensionContextMock, Class suiteClass) { - when(extensionContextMock.getRoot()).thenReturn(extensionContextMock); - when(extensionContextMock.getUniqueId()).thenReturn(buildSuiteId(suiteClass)); - } + @Test + void whenAChildClassInheritsFromABaseClassWithReportingConfig_thenChildClassShouldHaveAccessToReportingConfig() throws Throwable { + SampleChildTest test = new SampleChildTest(); + + Method methodMock = test.getClass().getMethod("someTestMethod"); + PerformanceEvaluationStatement statementMock = mock(PerformanceEvaluationStatement.class); + Invocation invocationMock = mock(Invocation.class); + ReflectiveInvocationContext invocationContextMock = mock(ReflectiveInvocationContext.class); + ExtensionContext extensionContextMock = mockTestContext(); + + when(extensionContextMock.getRequiredTestMethod()).thenReturn(methodMock); + when(extensionContextMock.getRequiredTestClass()).thenReturn((Class) test.getClass()); + when(statementBuilderMock.build()).thenReturn(statementMock); + + interceptor.postProcessTestInstance(test, extensionContextMock); + interceptor.statementBuilder = statementBuilderMock; + interceptor.interceptTestMethod(invocationMock, invocationContextMock, extensionContextMock); + + assertTrue(interceptor.measurementsStartTimeMs > 0); + + assertEquals(1, interceptor.activeReporters.size()); + assertEquals( SampleBaseTest.config.getReportGenerators(), interceptor.activeReporters); + + EvaluationContext context = captureEvaluationContext(); + assertEquals(120, context.getConfiguredExecutionTarget()); + assertEquals(15, context.getConfiguredThreads()); + assertEquals(67, context.getRequiredThroughput()); - private static String buildSuiteId(Class clazz) { - return "[engine:junit-platform-suite]/[suite:" + clazz.getName() + "]/[engine:junit-jupiter]"; } @Test @@ -250,6 +271,15 @@ void whenInterceptorSupportsParameterIsCalled_thenParameterTypeShouldBeChecked() void whenInterceptorResolveParameterIsCalled_thenTestContextSupplierShouldBeReturned() { assertTrue(interceptor.resolveParameter(null, null) instanceof TestContextSupplier); } + + private static void mockActiveSuite(ExtensionContext extensionContextMock, Class suiteClass) { + when(extensionContextMock.getRoot()).thenReturn(extensionContextMock); + when(extensionContextMock.getUniqueId()).thenReturn(buildSuiteId(suiteClass)); + } + + private static String buildSuiteId(Class clazz) { + return "[engine:junit-platform-suite]/[suite:" + clazz.getName() + "]/[engine:junit-jupiter]"; + } private static ParameterContext mockTestContextSupplierParameterType() throws NoSuchMethodException { Method methodMock = SampleAsyncAnnotatedTest.class.getMethod("someTestMethod", TestContextSupplier.class); @@ -355,5 +385,22 @@ public static class SuiteSampleTest { .reportGenerator(new ConsoleReportGenerator()) .build(); } + + public static class SampleBaseTest { + @JUnitPerfTestActiveConfig + public static final JUnitPerfReportingConfig config = JUnitPerfReportingConfig.builder() + .reportGenerator(new HtmlReportGenerator()) + .build(); + } + + @Disabled + @JUnitPerfTest( threads = 15, totalExecutions = 120) + @JUnitPerfTestRequirement(executionsPerSec = 67) + public static class SampleChildTest extends SampleBaseTest { + @Test + public void someTestMethod() { + assertTrue(true); + } + } } \ No newline at end of file