From a928cc19ef21e759a60dce0f032c3276c47f437b Mon Sep 17 00:00:00 2001 From: Richard Richter Date: Tue, 3 Mar 2020 00:17:20 +0100 Subject: [PATCH] AbstractUnitTest/AbstractIntegrationTest refactored to new context --- .../test/util/AbstractSpringTest.java | 38 ++++------ .../test/AbstractIntegrationTest.java | 33 ++++---- ....java => MidpointTestContextWithTask.java} | 30 ++++---- .../tools/testng/AbstractUnitTest.java | 39 ++++------ ...tTestMixin.java => MidpointTestMixin.java} | 76 +++++++++++++------ 5 files changed, 110 insertions(+), 106 deletions(-) rename repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/{MidpointTestMethodContext.java => MidpointTestContextWithTask.java} (70%) rename tools/test-ng/src/main/java/com/evolveum/midpoint/tools/testng/{UnitTestMixin.java => MidpointTestMixin.java} (64%) diff --git a/infra/test-util/src/main/java/com/evolveum/midpoint/test/util/AbstractSpringTest.java b/infra/test-util/src/main/java/com/evolveum/midpoint/test/util/AbstractSpringTest.java index ab0fe6c306e..e2c0f904d23 100644 --- a/infra/test-util/src/main/java/com/evolveum/midpoint/test/util/AbstractSpringTest.java +++ b/infra/test-util/src/main/java/com/evolveum/midpoint/test/util/AbstractSpringTest.java @@ -9,26 +9,26 @@ import java.lang.reflect.Field; import java.lang.reflect.Modifier; -import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.springframework.test.context.testng.AbstractTestNGSpringContextTests; import org.testng.ITestResult; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; -import com.evolveum.midpoint.tools.testng.UnitTestMixin; +import com.evolveum.midpoint.tools.testng.MidpointTestContext; +import com.evolveum.midpoint.tools.testng.MidpointTestMixin; +import com.evolveum.midpoint.tools.testng.SimpleMidpointTestContext; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; /** - * Base test class for tests integrated with Spring providing {@link UnitTestMixin} implementation. + * Base test class for tests integrated with Spring providing {@link MidpointTestMixin} implementation. * Can be extended by any unit test class that would otherwise extend * {@link AbstractTestNGSpringContextTests}. */ public abstract class AbstractSpringTest extends AbstractTestNGSpringContextTests - implements UnitTestMixin { - - private static final ThreadLocal TEST_CONTEXT_THREAD_LOCAL = new ThreadLocal<>(); + implements MidpointTestMixin { /** * Hides parent's logger, but that one is from commons-logging and we don't want that. @@ -37,18 +37,15 @@ public abstract class AbstractSpringTest extends AbstractTestNGSpringContextTest @BeforeMethod public void startTestContext(ITestResult testResult) { - Class testClass = testResult.getMethod().getTestClass().getRealClass(); - String testMethodName = testResult.getMethod().getMethodName(); - displayTestTitle(testClass.getSimpleName() + "." + testMethodName); - - TEST_CONTEXT_THREAD_LOCAL.set(testResult); + SimpleMidpointTestContext context = SimpleMidpointTestContext.create(testResult); + displayTestTitle(context.getTestName()); } @AfterMethod public void finishTestContext(ITestResult testResult) { - TEST_CONTEXT_THREAD_LOCAL.remove(); - - displayDefaultTestFooter(testResult); + SimpleMidpointTestContext context = SimpleMidpointTestContext.get(); + SimpleMidpointTestContext.destroy(); + displayDefaultTestFooter(context.getTestName(), testResult); } @Override @@ -56,17 +53,10 @@ public Trace logger() { return logger; } - @NotNull - public String contextName() { - ITestResult context = TEST_CONTEXT_THREAD_LOCAL.get(); - return context != null - ? getClass().getSimpleName() + "." + context.getMethod().getMethodName() - : getClass().getSimpleName(); - } - @Override - public String getTestNameShort() { - return TEST_CONTEXT_THREAD_LOCAL.get().getMethod().getMethodName(); + @Nullable + public MidpointTestContext getTestContext() { + return SimpleMidpointTestContext.get(); } /** diff --git a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/AbstractIntegrationTest.java b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/AbstractIntegrationTest.java index d28d4c26ad3..06708a49342 100644 --- a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/AbstractIntegrationTest.java +++ b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/AbstractIntegrationTest.java @@ -37,6 +37,7 @@ import ch.qos.logback.classic.LoggerContext; import org.apache.commons.lang.SystemUtils; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.opends.server.types.Entry; import org.opends.server.types.SearchResultEntry; import org.slf4j.LoggerFactory; @@ -107,6 +108,7 @@ import com.evolveum.midpoint.test.ldap.OpenDJController; import com.evolveum.midpoint.test.util.*; import com.evolveum.midpoint.tools.testng.CurrentTestResultHolder; +import com.evolveum.midpoint.tools.testng.MidpointTestContext; import com.evolveum.midpoint.util.*; import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; @@ -224,6 +226,12 @@ public void initSystem() throws Exception { TestUtil.assertSuccessOrWarning("initSystem failed (result)", result, 1); } + @Override + @Nullable + public MidpointTestContext getTestContext() { + return MidpointTestContextWithTask.get(); + } + /** * Test class initialization. */ @@ -242,7 +250,7 @@ protected void postInitSystem(Task initTask, OperationResult initResult) throws /** * Creates test method context which includes customized {@link Task} * (see {@link #createTask(String)}) and other test related info wrapped as - * {@link MidpointTestMethodContext} and stores it in thread-local variable for future access. + * {@link MidpointTestContextWithTask} and stores it in thread-local variable for future access. * This implementation fully overrides version from {@link AbstractSpringTest}. */ @BeforeMethod @@ -268,7 +276,7 @@ public void startTestContext(ITestResult testResult) { // (I.e. not via the test context.) // task.setResult(result); - MidpointTestMethodContext.create(testClass, testMethodName, task, task.getResult()); + MidpointTestContextWithTask.create(testClass, testMethodName, task, task.getResult()); // TODO inttest: remove after fix in TracerImpl TestNameHolder.setCurrentTestName(contextName()); } @@ -279,10 +287,10 @@ public void startTestContext(ITestResult testResult) { */ @AfterMethod public void finishTestContext(ITestResult testResult) { - MidpointTestMethodContext context = MidpointTestMethodContext.get(); - MidpointTestMethodContext.destroy(); // let's destroy it before anything else in this method + MidpointTestContextWithTask context = MidpointTestContextWithTask.get(); + MidpointTestContextWithTask.destroy(); // let's destroy it before anything else in this method - displayDefaultTestFooter(testResult); + displayDefaultTestFooter(context.getTestName(), testResult); Task task = context.getTask(); if (task != null) { @@ -333,7 +341,7 @@ public void setPredefinedTestMethodTracing(PredefinedTestMethodTracing predefine * Returns default pre-created test-method-scoped {@link Task}. */ protected Task getTestTask() { - return MidpointTestMethodContext.get().getTask(); + return MidpointTestContextWithTask.get().getTask(); } /** @@ -373,7 +381,6 @@ protected Task createTask() { return createPlainTask(null); } - /** * Subclasses may override this if test task needs additional customization. * Each task used or created by the test is customized - this applies to default @@ -383,16 +390,6 @@ protected void customizeTask(Task task) { // nothing by default } - @NotNull - public String contextName() { - MidpointTestMethodContext context = MidpointTestMethodContext.get(); - return context != null ? context.getTestName() : getClass().getSimpleName(); - } - - public String getTestNameShort() { - return MidpointTestMethodContext.get().getTestNameShort(); - } - /** * Creates new subresult for default pre-created test-method-scoped {@link Task}. */ @@ -420,7 +417,7 @@ protected OperationResult createOperationalResult(String nameSuffix) { * after method, only displayed. */ protected OperationResult getTestOperationResult() { - return MidpointTestMethodContext.get().getResult(); + return MidpointTestContextWithTask.get().getResult(); } public S_ItemEntry deltaFor(Class objectClass) throws SchemaException { diff --git a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/MidpointTestMethodContext.java b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/MidpointTestContextWithTask.java similarity index 70% rename from repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/MidpointTestMethodContext.java rename to repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/MidpointTestContextWithTask.java index dfdf346909f..615e2fe610f 100644 --- a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/MidpointTestMethodContext.java +++ b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/MidpointTestContextWithTask.java @@ -9,6 +9,7 @@ import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.tools.testng.MidpointTestContext; /** * Value object carrying test context information like task, result and method name. @@ -16,9 +17,10 @@ * Static methods are used for creating the context and working with it via {@link ThreadLocal}. * It is important to to call {@link #destroy()} at the end (in some after-method). */ -public final class MidpointTestMethodContext { +public final class MidpointTestContextWithTask implements MidpointTestContext { - private static final ThreadLocal TEST_CONTEXT_THREAD_LOCAL = new ThreadLocal<>(); + private static final ThreadLocal TEST_CONTEXT_THREAD_LOCAL = + new ThreadLocal<>(); /** * Actual test class - not abstract (where method may be implemented) but executed test class. @@ -40,7 +42,7 @@ public final class MidpointTestMethodContext { */ private final OperationResult result; - private MidpointTestMethodContext( + private MidpointTestContextWithTask( Class testClass, String methodName, Task task, OperationResult result) { this.testClass = testClass; @@ -49,17 +51,13 @@ private MidpointTestMethodContext( this.result = result; } - /** - * Returns name of the test - which is "class-simple-name.method". - */ - public String getTestName() { - return testClass.getSimpleName() + "." + methodName; + @Override + public Class getTestClass() { + return testClass; } - /** - * Returns short name of the test - which is method name. - */ - public String getTestNameShort() { + @Override + public String getTestMethodName() { return methodName; } @@ -71,16 +69,16 @@ public OperationResult getResult() { return result; } - public static MidpointTestMethodContext create( + public static MidpointTestContextWithTask create( Class testClass, String methodName, Task task, OperationResult result) { - MidpointTestMethodContext ctx = - new MidpointTestMethodContext(testClass, methodName, task, result); + MidpointTestContextWithTask ctx = + new MidpointTestContextWithTask(testClass, methodName, task, result); TEST_CONTEXT_THREAD_LOCAL.set(ctx); return ctx; } - public static MidpointTestMethodContext get() { + public static MidpointTestContextWithTask get() { return TEST_CONTEXT_THREAD_LOCAL.get(); } diff --git a/tools/test-ng/src/main/java/com/evolveum/midpoint/tools/testng/AbstractUnitTest.java b/tools/test-ng/src/main/java/com/evolveum/midpoint/tools/testng/AbstractUnitTest.java index 6e54b72cfdb..1437c01a8a1 100644 --- a/tools/test-ng/src/main/java/com/evolveum/midpoint/tools/testng/AbstractUnitTest.java +++ b/tools/test-ng/src/main/java/com/evolveum/midpoint/tools/testng/AbstractUnitTest.java @@ -6,7 +6,7 @@ */ package com.evolveum.midpoint.tools.testng; -import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.ITestResult; @@ -14,47 +14,34 @@ import org.testng.annotations.BeforeMethod; /** - * Base test class providing basic {@link UnitTestMixin} implementation. + * Base test class providing basic {@link MidpointTestMixin} implementation. * Can be extended by any unit test class that otherwise doesn't extend anything. */ -public abstract class AbstractUnitTest implements UnitTestMixin { - - private static final ThreadLocal TEST_CONTEXT_THREAD_LOCAL = new ThreadLocal<>(); +public abstract class AbstractUnitTest implements MidpointTestMixin { protected final Logger logger = LoggerFactory.getLogger(getClass()); @BeforeMethod public void startTestContext(ITestResult testResult) { - Class testClass = testResult.getMethod().getTestClass().getRealClass(); - String testMethodName = testResult.getMethod().getMethodName(); - displayTestTitle(testClass.getSimpleName() + "." + testMethodName); - - TEST_CONTEXT_THREAD_LOCAL.set(testResult); + SimpleMidpointTestContext context = SimpleMidpointTestContext.create(testResult); + displayTestTitle(context.getTestName()); } @AfterMethod public void finishTestContext(ITestResult testResult) { - TEST_CONTEXT_THREAD_LOCAL.remove(); - - displayDefaultTestFooter(testResult); - } - - @Override - public Logger logger() { - return logger; + SimpleMidpointTestContext context = SimpleMidpointTestContext.get(); + SimpleMidpointTestContext.destroy(); + displayDefaultTestFooter(context.getTestName(), testResult); } @Override - @NotNull - public String contextName() { - ITestResult context = TEST_CONTEXT_THREAD_LOCAL.get(); - return context != null - ? getTestName(context) - : getClass().getSimpleName(); + @Nullable + public MidpointTestContext getTestContext() { + return SimpleMidpointTestContext.get(); } @Override - public String getTestNameShort() { - return TEST_CONTEXT_THREAD_LOCAL.get().getMethod().getMethodName(); + public Logger logger() { + return logger; } } diff --git a/tools/test-ng/src/main/java/com/evolveum/midpoint/tools/testng/UnitTestMixin.java b/tools/test-ng/src/main/java/com/evolveum/midpoint/tools/testng/MidpointTestMixin.java similarity index 64% rename from tools/test-ng/src/main/java/com/evolveum/midpoint/tools/testng/UnitTestMixin.java rename to tools/test-ng/src/main/java/com/evolveum/midpoint/tools/testng/MidpointTestMixin.java index f542cdb2aaa..b61ead2766a 100644 --- a/tools/test-ng/src/main/java/com/evolveum/midpoint/tools/testng/UnitTestMixin.java +++ b/tools/test-ng/src/main/java/com/evolveum/midpoint/tools/testng/MidpointTestMixin.java @@ -6,14 +6,17 @@ */ package com.evolveum.midpoint.tools.testng; +import java.util.Objects; + import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.testng.ITestResult; /** * Mixin with various utility methods, mostly related to test header/footer/section output/logging. */ -public interface UnitTestMixin { +public interface MidpointTestMixin { String TEST_LOG_PREFIX = "=====[ "; String TEST_LOG_SUFFIX = " ]======================================"; @@ -27,46 +30,75 @@ public interface UnitTestMixin { String TEST_LOG_SECTION_SUFFIX = " --------------------------------------"; /** - * Context name is "class-simple-name.method" if test method context is available, - * otherwise it is just simple name of the test class. - * This also works as "getTestName" including (short) class name when - * {@link #getTestNameShort()} is too short and/or class name is required. + * Context name is {@link #getTestName()} if test method context is available, + * otherwise it is just a simple name of the test class. *

- * This is particularly useful for code that may run outside of test method. + * This is particularly useful for code that may run outside of test method scope + * or in another thread where context is not available. */ - @NotNull String contextName(); + @NotNull + default String contextName() { + MidpointTestContext context = getTestContext(); + return context != null + ? context.getTestName() + : getClass().getSimpleName(); + } /** - * Returns test name (as "class-simple-name.method") from {@link ITestResult}. + * Returns {@link MidpointTestContext#getTestName()}. + * This fails if test-method context is not available. */ - @NotNull - default String getTestName(ITestResult context) { - return context.getTestClass().getRealClass().getSimpleName() - + "." + context.getMethod().getMethodName(); + default String getTestName() { + return testContext().getTestName(); + } + + /** + * Returns {@link MidpointTestContext#getTestNameShort()}. + * This fails if test-method context is not available. + */ + default String getTestNameShort() { + return testContext().getTestNameShort(); } /** - * Returns short test name - typically just a method name (without class). - * See also {@link #contextName()} if class name is required. + * Returns {@link MidpointTestContext#getTestNameLong()}. * This fails if test-method context is not available. */ - String getTestNameShort(); + default String getTestNameLong() { + return testContext().getTestNameLong(); + } /** * Returns test class logger. */ Logger logger(); - default void displayTestTitle(String testName) { - System.out.println(TEST_OUT_PREFIX + testName + TEST_OUT_SUFFIX); - logger().info(TEST_LOG_PREFIX + testName + TEST_LOG_SUFFIX); + /** + * Returns {@link MidpointTestContext} from current test-method context + * or {@code null} if context is not available - it should not fail. + *

+ * This method should be implemented by supporting classes, but not used in tests in general. + * It is used for default implementations of various testName*() methods. + */ + @Nullable MidpointTestContext getTestContext(); + + @Deprecated + @NotNull + // TODO switch to private after ditching JDK 8, DON'T USE/DON'T OVERRIDE! + /*private*/ default MidpointTestContext testContext() { + return Objects.requireNonNull(getTestContext(), + "Current test-method context MUST NOT be null"); + } + + default void displayTestTitle(String testTitle) { + System.out.println(TEST_OUT_PREFIX + testTitle + TEST_OUT_SUFFIX); + logger().info(TEST_LOG_PREFIX + testTitle + TEST_LOG_SUFFIX); } - default void displayDefaultTestFooter(ITestResult testResult) { + default void displayDefaultTestFooter(String testTitle, ITestResult testResult) { long testMsDuration = testResult.getEndMillis() - testResult.getStartMillis(); - String testName = getTestName(testResult); - System.out.println(TEST_OUT_FOOTER_PREFIX + testName + " FINISHED in " + testMsDuration + " ms" + TEST_OUT_FOOTER_SUFFIX); - logger().info(TEST_LOG_PREFIX + testName + " FINISHED in " + testMsDuration + " ms" + TEST_LOG_SUFFIX); + System.out.println(TEST_OUT_FOOTER_PREFIX + testTitle + " FINISHED in " + testMsDuration + " ms" + TEST_OUT_FOOTER_SUFFIX); + logger().info(TEST_LOG_PREFIX + testTitle + " FINISHED in " + testMsDuration + " ms" + TEST_LOG_SUFFIX); } /**