diff --git a/.run/mvn clean test - without nightly.run.xml b/.run/mvn clean test - without nightly.run.xml deleted file mode 100644 index fc51b3a56..000000000 --- a/.run/mvn clean test - without nightly.run.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.run/test.run.xml b/.run/test.run.xml new file mode 100644 index 000000000..85238672c --- /dev/null +++ b/.run/test.run.xml @@ -0,0 +1,15 @@ + + + + + \ No newline at end of file diff --git a/README.md b/README.md index 9d92cd033..ab2fbf572 100644 --- a/README.md +++ b/README.md @@ -103,9 +103,9 @@ a single test (method) - the tests have to function independently of their surro has to either succeed in all three scenarios or it must fail each time. Everything else indicates an invalid test setup._ +Tests which require a running SIRIUS framework should use [`SiriusExtension`](src/test/java/sirius/kernel/SiriusExtension.java). + For testing, we heavily rely on **Docker** (especially when external systems like databases are required). SIRIUS has a build-in helper to start and stop **docker-compose** setups. See [DockerHelper](src/main/java/sirius/kernel/DockerHelper.java) for a list of supported configuration -settings or refer the [test setup](https://github.com/scireum/sirius-db/tree/main/src/test/resources) -of [sirius-db](https://github.com/scireum/sirius-db) and its -[TestSuite](https://github.com/scireum/sirius-db/blob/main/src/test/java/TestSuite.java) as an elaborate example. +settings or refer the [test setup](https://github.com/scireum/sirius-db/tree/main/src/test/resources) of [sirius-db](https://github.com/scireum/sirius-db) as an elaborate example. diff --git a/pom.xml b/pom.xml index 50580e08e..a2d44660d 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.scireum sirius-parent - 14.3.3 + 15.0.0 sirius-kernel SIRIUS kernel diff --git a/src/test/java/sirius/kernel/BaseSpecification.groovy b/src/test/java/sirius/kernel/BaseSpecification.groovy deleted file mode 100644 index 937a742a9..000000000 --- a/src/test/java/sirius/kernel/BaseSpecification.groovy +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Made with all the love in the world - * by scireum in Remshalden, Germany - * - * Copyright by scireum GmbH - * http://www.scireum.de - info@scireum.de - */ - -package sirius.kernel - -import sirius.kernel.async.CallContext -import spock.lang.Specification - -/** - * Base class for all specs that require the Sirius framework to be setup. - */ -class BaseSpecification extends Specification { - - /* - * Executed before each class. Will ensure that Sirius is ready - */ - def setupSpec() { - TestHelper.setUp(getClass()) - } - - /* - * Will be executed once before every spec method - */ - def setup() { - CallContext.initialize() - } - - -} diff --git a/src/test/java/sirius/kernel/Scenario.java b/src/test/java/sirius/kernel/Scenario.java deleted file mode 100644 index 5e4c0a82b..000000000 --- a/src/test/java/sirius/kernel/Scenario.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Made with all the love in the world - * by scireum in Remshalden, Germany - * - * Copyright by scireum GmbH - * http://www.scireum.de - info@scireum.de - */ - -package sirius.kernel; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Repeatable; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Describes an alternative execution scenario for all tests. - *

- * Applying this annotation to the main TestSuite which must be - * executed using {@link ScenarioSuite}, another test run is created. - *

- * This run will enhance the system configuration by the file given in - * {@link #file()}. Additionally the tests to be executed can be filtered - * using a regex in {@link #includes()} and {@link #excludes()}. - */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -@Repeatable(Scenarios.class) -public @interface Scenario { - - /** - * Contains the name of the configuration file to load. - *

- * All settings provided here will overwrite those in test.conf and - * also the system configuration. - * - * @return the scenario configuration - */ - String file(); - - /** - * Contains a regular expression which filters the tests (fully qualified class names) - * to be executed. - * - * @return the filter regex or an empty string to execute all classes - */ - String includes() default ""; - - /** - * Contains a regular expression which filters the tests (fully qualified class names) - * to be ignored and therefore not executed. - * - * @return the filter regex or an empty string to execute all classes - */ - String excludes() default ""; - -} diff --git a/src/test/java/sirius/kernel/ScenarioSuite.java b/src/test/java/sirius/kernel/ScenarioSuite.java deleted file mode 100644 index bdfb2c15a..000000000 --- a/src/test/java/sirius/kernel/ScenarioSuite.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Made with all the love in the world - * by scireum in Remshalden, Germany - * - * Copyright by scireum GmbH - * http://www.scireum.de - info@scireum.de - */ - -package sirius.kernel; - -import com.googlecode.junittoolbox.WildcardPatternSuite; -import org.junit.jupiter.api.Tag; -import org.junit.runner.Description; -import org.junit.runner.Runner; -import org.junit.runner.notification.Failure; -import org.junit.runner.notification.RunNotifier; -import org.junit.runners.model.InitializationError; -import org.junit.runners.model.RunnerBuilder; -import org.spockframework.runtime.RunContext; -import org.spockframework.runtime.SpecInfoBuilder; -import org.spockframework.runtime.Sputnik; -import org.spockframework.runtime.model.FeatureInfo; -import org.spockframework.runtime.model.SpecInfo; -import sirius.kernel.commons.Strings; - -import javax.annotation.Nonnull; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Pattern; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -/** - * Provides a special test suite which executes all tests in all {@link Scenario scenarios}. - *

- * This approach can be used to execute the same tests in multiple environments (e.g. by - * provisioning different containers via {@link DockerHelper}). - *

- * As this is a subclass of {@link WildcardPatternSuite} an appropriate - * {@code @SuiteClasses} annotation must be present. - */ -public class ScenarioSuite extends WildcardPatternSuite { - - private static final Map scopeSettings = new HashMap<>(); - private final List scenarios; - - private static class ScenarioRunner extends Runner { - - public static final Description FRAMEWORK_SETUP = - Description.createTestDescription(Sirius.class, "Framework setup"); - public static final Description FRAMEWORK_TEARDOWN = - Description.createTestDescription(Sirius.class, "Framework teardown"); - private final String scenarioFile; - private final String includes; - private final String excludes; - private final List allTests; - - protected ScenarioRunner(String scenarioFile, String includes, String excludes, List allTests) { - this.scenarioFile = scenarioFile; - this.includes = includes; - this.excludes = excludes; - this.allTests = allTests; - } - - protected List getEffectiveTests() { - Stream stream = allTests.stream(); - - // Filter on includes / excludes defined by @Scenario - if (Strings.isFilled(includes)) { - Pattern filterPattern = Pattern.compile(includes); - stream = stream.filter(r -> filterPattern.matcher(r.getDescription().getClassName()).matches()); - } - if (Strings.isFilled(excludes)) { - Pattern filterPattern = Pattern.compile(excludes); - stream = stream.filter(r -> !filterPattern.matcher(r.getDescription().getClassName()).matches()); - } - - return stream.collect(Collectors.toList()); - } - - @Override - public Description getDescription() { - Description description = Description.createSuiteDescription(determineScenarioName()); - description.addChild(FRAMEWORK_SETUP); - getEffectiveTests().forEach(runner -> description.addChild(runner.getDescription())); - description.addChild(FRAMEWORK_TEARDOWN); - return description; - } - - @Nonnull - public String determineScenarioName() { - if (Strings.isEmpty(scenarioFile)) { - return "Main Scenario"; - } - - return "Scenario: " + scenarioFile.replace(".conf", ""); - } - - @Override - public void run(RunNotifier runNotifier) { - System.setProperty(Sirius.SIRIUS_TEST_SCENARIO_PROPERTY, scenarioFile == null ? "" : scenarioFile); - runNotifier.fireTestStarted(FRAMEWORK_SETUP); - try { - // In case of a configured scenario, ensure framework shutdown - if (scenarioFile != null) { - TestHelper.performTearDown(); - } - TestHelper.setUp(ScenarioSuite.class); - } catch (Exception exception) { - runNotifier.fireTestFailure(new Failure(FRAMEWORK_SETUP, exception)); - } finally { - runNotifier.fireTestFinished(FRAMEWORK_SETUP); - } - - try { - getEffectiveTests().forEach(runner -> run(runNotifier, runner)); - } finally { - runNotifier.fireTestStarted(FRAMEWORK_TEARDOWN); - try { - TestHelper.tearDown(ScenarioSuite.class); - } catch (Exception exception) { - runNotifier.fireTestFailure(new Failure(FRAMEWORK_TEARDOWN, exception)); - } finally { - runNotifier.fireTestFinished(FRAMEWORK_TEARDOWN); - } - } - } - - private void run(RunNotifier runNotifier, Runner runner) { - if (ignoreUnrollFeatures(runNotifier, runner)) { - return; - } - - // Ignore tests with nightly tags. - // CAVEAT: this only work when annotated on class level, like the former scope - // This interception breaks surefires test counting - Tag tag = runner.getDescription().getTestClass().getAnnotation(Tag.class); - if (tag != null && !isScopeEnabled(tag.value())) { - runNotifier.fireTestIgnored(runner.getDescription()); - return; - } - - runner.run(runNotifier); - } - - /** - * Warn if {@link spock.lang.Unroll} is used as it crushes the output of JUNIT in every sane IDE. - *

- * Checks if a given suite is run via Sputnik and therefore based on Spock. If so, we check - * if an Unroll annotation is present and abort the spec if so. - *

- * This is done as the output generated by Unroll completely screws the output as shown - * in the JUNIT views in any sane IDE. Also, Unroll provides no real benefit except than - * generating more output (which is pointless if it ends up anywhere in the UI). - * - * @param runNotifier the notifier used for reporting - * @param runner the runner to check - * @return true if an invalid spec was found, false otherwise - */ - private boolean ignoreUnrollFeatures(RunNotifier runNotifier, Runner runner) { - if (!(runner instanceof Sputnik)) { - return false; - } - - SpecInfo spec = (new SpecInfoBuilder(runner.getDescription().getTestClass())).build(); - RunContext.get().createExtensionRunner(spec).run(); - if (spec.getAllFeatures().stream().anyMatch(FeatureInfo::isReportIterations)) { - runNotifier.fireTestIgnored(runner.getDescription()); - runNotifier.fireTestFailure(new Failure(Description.TEST_MECHANISM, - new IllegalStateException( - "@Unroll not supported by ScenarioSuite: " - + runner.getDescription().getTestClass()))); - return true; - } - - return false; - } - } - - /** - * Creates a new suite. - *

- * Use {@literal @RunWith(ScenarioSuite)} for a test suite. - * - * @param klass the test suite to execute - * @param builder the builder used to build the suite - * @throws InitializationError in case of an error during initialization - */ - public ScenarioSuite(Class klass, RunnerBuilder builder) throws InitializationError { - super(klass, builder); - this.scenarios = Arrays.asList(klass.getAnnotationsByType(Scenario.class)); - } - - @Override - protected List getChildren() { - List tests = super.getChildren(); - List result = new ArrayList<>(); - result.add(new ScenarioRunner(null, null, null, tests)); - if (scenarios != null) { - scenarios.stream() - .map(scenario -> new ScenarioRunner(scenario.file(), - scenario.includes(), - scenario.excludes(), - tests)) - .forEach(result::add); - } - - return result; - } - - /** - * Determines if the given test scope is enabled. - *

- * This evaluates against a JUnit groups that must be active. We test this by checking for exclusion - * of the group. - * - * @param scope the scope to check - * @return true if the scope is enabled, false otherwise - */ - public static boolean isScopeEnabled(String scope) { - if (Strings.isEmpty(scope)) { - return true; - } - - return scopeSettings.computeIfAbsent(scope, ignored -> { - // NOTE: this is potentially dangerous, as it works on one potentiall input property and not the - // actual system activated groups, but should work until spock will be removed - return !System.getProperty("test.excluded.groups", "").contains(scope); - }); - } -} diff --git a/src/test/java/sirius/kernel/Scenarios.java b/src/test/java/sirius/kernel/Scenarios.java deleted file mode 100644 index a5fdf0107..000000000 --- a/src/test/java/sirius/kernel/Scenarios.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Made with all the love in the world - * by scireum in Remshalden, Germany - * - * Copyright by scireum GmbH - * http://www.scireum.de - info@scireum.de - */ - -package sirius.kernel; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Used to provide several {@link Scenario scenarios} for a test suite. - */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -public @interface Scenarios { - /** - * The scenarios to execute. - * - * @return the scenarios to execute - */ - Scenario[] value(); -} diff --git a/src/test/java/sirius/kernel/SiriusExtension.java b/src/test/java/sirius/kernel/SiriusExtension.java index c250e9a83..634608691 100644 --- a/src/test/java/sirius/kernel/SiriusExtension.java +++ b/src/test/java/sirius/kernel/SiriusExtension.java @@ -16,8 +16,6 @@ /** * JUnit 5 extension to support the Sirius framework lifecycle. Annotated test classes will be provisioned with * a running framework and a cleared {@link CallContext} before each test. - *

- * Note: This currently does not support {@link sirius.kernel.Scenario scenarios}. */ public class SiriusExtension implements BeforeAllCallback, BeforeEachCallback { diff --git a/src/test/kotlin/sirius/kernel/nls/FormatterTest.kt b/src/test/kotlin/sirius/kernel/nls/FormatterTest.kt index ebed00c73..d4caa154f 100644 --- a/src/test/kotlin/sirius/kernel/nls/FormatterTest.kt +++ b/src/test/kotlin/sirius/kernel/nls/FormatterTest.kt @@ -8,8 +8,8 @@ package sirius.kernel.nls -import org.junit.Assert.assertThrows import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows import org.junit.jupiter.api.extension.ExtendWith import sirius.kernel.SiriusExtension import sirius.kernel.commons.Context @@ -77,7 +77,7 @@ class FormatterTest { fun `format fails when using unknown parameter`() { val pattern = "Test \${foo}" - assertThrows(IllegalArgumentException::class.java) { + assertThrows { Formatter.create(pattern).smartFormat() } } @@ -86,7 +86,7 @@ class FormatterTest { fun `format fails for missing curly bracket`() { val pattern = "Test \${foo" - assertThrows(IllegalArgumentException::class.java) { + assertThrows { Formatter.create(pattern).smartFormat() } } @@ -95,7 +95,7 @@ class FormatterTest { fun `format fails for missing square bracket`() { val pattern = "Test [\${foo}" - assertThrows(IllegalArgumentException::class.java) { + assertThrows { Formatter.create(pattern).smartFormat() } } @@ -104,7 +104,7 @@ class FormatterTest { fun `smartFormat fails for additional square bracket`() { val pattern = "Test [\${foo}]]" - assertThrows(IllegalArgumentException::class.java) { + assertThrows { Formatter.create(pattern).smartFormat() } }