diff --git a/serenity-cucumber/src/main/java/io/cucumber/core/plugin/LineFilters.java b/serenity-cucumber/src/main/java/io/cucumber/core/plugin/LineFilters.java index 71320a15e0..0950fd1531 100644 --- a/serenity-cucumber/src/main/java/io/cucumber/core/plugin/LineFilters.java +++ b/serenity-cucumber/src/main/java/io/cucumber/core/plugin/LineFilters.java @@ -2,7 +2,7 @@ import io.cucumber.messages.types.Examples; import io.cucumber.messages.types.TableRow; -import net.serenitybdd.cucumber.CucumberWithSerenity; +import net.serenitybdd.cucumber.CucumberWithSerenityRuntime; import java.net.URI; import java.util.HashMap; @@ -29,7 +29,7 @@ public Optional getURIForFeaturePath(URI featurePath) { } private Map> newLineFilters() { - Map> lineFiltersFromRuntime = CucumberWithSerenity.currentRuntimeOptions().getLineFilters(); + Map> lineFiltersFromRuntime = CucumberWithSerenityRuntime.currentRuntimeOptions().getLineFilters(); if (lineFiltersFromRuntime == null) { return new HashMap<>(); } else { diff --git a/serenity-cucumber/src/main/java/io/cucumber/core/plugin/SerenityReporter.java b/serenity-cucumber/src/main/java/io/cucumber/core/plugin/SerenityReporter.java index c7f4497e23..6675123285 100644 --- a/serenity-cucumber/src/main/java/io/cucumber/core/plugin/SerenityReporter.java +++ b/serenity-cucumber/src/main/java/io/cucumber/core/plugin/SerenityReporter.java @@ -16,7 +16,7 @@ import net.serenitybdd.core.Serenity; import net.serenitybdd.core.SerenityListeners; import net.serenitybdd.core.SerenityReports; -import net.serenitybdd.cucumber.CucumberWithSerenity; +import net.serenitybdd.cucumber.CucumberWithSerenityRuntime; import net.serenitybdd.cucumber.formatting.ScenarioOutlineDescription; import net.serenitybdd.cucumber.util.PathUtils; import net.serenitybdd.cucumber.util.StepDefinitionAnnotationReader; @@ -33,7 +33,6 @@ import net.thucydides.core.webdriver.ThucydidesWebDriverSupport; import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; -import org.junit.internal.AssumptionViolatedException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -491,10 +490,10 @@ private boolean testRunHasFilterTags() { } private List getCucumberRuntimeTags() { - if (CucumberWithSerenity.currentRuntimeOptions() == null) { + if (CucumberWithSerenityRuntime.currentRuntimeOptions() == null) { return new ArrayList<>(); } else { - return CucumberWithSerenity.currentRuntimeOptions().getTagExpressions(); + return CucumberWithSerenityRuntime.currentRuntimeOptions().getTagExpressions(); } } @@ -914,7 +913,11 @@ private Optional latestTestOutcome() { } private boolean isAssumptionFailure(Throwable rootCause) { - return (AssumptionViolatedException.class.isAssignableFrom(rootCause.getClass())); + try { + return (Class.forName("org.junit.internal.AssumptionViolatedException").isAssignableFrom(rootCause.getClass())); + } catch (ClassNotFoundException e) { + return false; + } } private String stepTitleFrom(io.cucumber.messages.types.Step currentStep, TestStep testStep) { diff --git a/serenity-cucumber/src/main/java/io/cucumber/junit/CucumberSerenityRunner.java b/serenity-cucumber/src/main/java/io/cucumber/junit/CucumberSerenityRunner.java index 8c0829db2a..63685564a2 100644 --- a/serenity-cucumber/src/main/java/io/cucumber/junit/CucumberSerenityRunner.java +++ b/serenity-cucumber/src/main/java/io/cucumber/junit/CucumberSerenityRunner.java @@ -14,14 +14,13 @@ import io.cucumber.core.runtime.*; import io.cucumber.plugin.Plugin; import io.cucumber.tagexpressions.Expression; +import net.serenitybdd.cucumber.CucumberWithSerenityRuntime; import net.serenitybdd.cucumber.SerenityOptions; import net.serenitybdd.cucumber.suiteslicing.CucumberSuiteSlicer; import net.serenitybdd.cucumber.suiteslicing.ScenarioFilter; import net.serenitybdd.cucumber.suiteslicing.TestStatistics; import net.serenitybdd.cucumber.suiteslicing.WeightedCucumberScenarios; import net.serenitybdd.cucumber.util.PathUtils; -import net.serenitybdd.cucumber.util.Splitter; -import net.thucydides.core.ThucydidesSystemProperty; import net.thucydides.core.guice.Injectors; import net.thucydides.core.steps.StepEventBus; import net.thucydides.core.util.EnvironmentVariables; @@ -61,7 +60,6 @@ public class CucumberSerenityRunner extends ParentRunner> { private List> children; private final EventBus bus; - private static ThreadLocal RUNTIME_OPTIONS = new ThreadLocal<>(); private final List features; private final Plugins plugins; @@ -80,29 +78,11 @@ public CucumberSerenityRunner(Class clazz) throws InitializationError { Assertions.assertNoCucumberAnnotatedMethods(clazz); // Parse the options early to provide fast feedback about invalid options - RuntimeOptions propertiesFileOptions = new CucumberPropertiesParser() - .parse(CucumberProperties.fromPropertiesFile()) - .build(); - - RuntimeOptions annotationOptions = new CucumberOptionsAnnotationParser() + RuntimeOptions runtimeOptions = CucumberWithSerenityRuntime.buildRuntimeOptions( + propertiesFileOptions -> new CucumberOptionsAnnotationParser() .withOptionsProvider(new JUnitCucumberOptionsProvider()) .parse(clazz) - .build(propertiesFileOptions); - - RuntimeOptions environmentOptions = new CucumberPropertiesParser() - .parse(CucumberProperties.fromEnvironment()) - .build(annotationOptions); - - RuntimeOptions runtimeOptions = new CucumberPropertiesParser() - .parse(CucumberProperties.fromSystemProperties()) - .build(environmentOptions); - - RuntimeOptionsBuilder runtimeOptionsBuilder = new RuntimeOptionsBuilder(); - Collection tagFilters = environmentSpecifiedTags(runtimeOptions.getTagExpressions()); - for (String tagFilter : tagFilters) { - runtimeOptionsBuilder.addTagFilter(new LiteralExpression(tagFilter)); - } - runtimeOptionsBuilder.build(runtimeOptions); + .build(propertiesFileOptions)); // Next parse the junit options JUnitOptions junitPropertiesFileOptions = new JUnitOptionsParser() @@ -124,7 +104,7 @@ public CucumberSerenityRunner(Class clazz) throws InitializationError { this.bus = synchronize(new TimeServiceEventBus(Clock.systemUTC(), UUID::randomUUID)); - setRuntimeOptions(runtimeOptions); + CucumberWithSerenityRuntime.setRuntimeOptions(runtimeOptions); // Parse the features early. Don't proceed when there are lexer errors FeatureParser parser = new FeatureParser(bus::generateId); @@ -180,65 +160,6 @@ private Map fromSystemPropertiesAndOptionsAnnotationIn(Class claz } } - - - private static RuntimeOptions DEFAULT_RUNTIME_OPTIONS; - - public static void setRuntimeOptions(RuntimeOptions runtimeOptions) { - RUNTIME_OPTIONS.set(runtimeOptions); - DEFAULT_RUNTIME_OPTIONS = runtimeOptions; - } - - public static RuntimeOptions currentRuntimeOptions() { - return (RUNTIME_OPTIONS.get() != null) ? RUNTIME_OPTIONS.get() : DEFAULT_RUNTIME_OPTIONS; - } - - private static Collection environmentSpecifiedTags(List existingTags) { - EnvironmentVariables environmentVariables = Injectors.getInjector().getInstance(EnvironmentVariables.class); - String tagsExpression = ThucydidesSystemProperty.TAGS.from(environmentVariables, ""); - List existingTagsValues = existingTags.stream().map(Object::toString).collect(toList()); - return Splitter.on(",").trimResults().omitEmptyStrings().splitToList(tagsExpression).stream() - .map(CucumberSerenityRunner::toCucumberTag).filter(t -> !existingTagsValues.contains(t)).collect(toList()); - } - - private static String toCucumberTag(String from) { - String tag = from.replaceAll(":", "="); - if (tag.startsWith("~@") || tag.startsWith("@")) { - return tag; - } - if (tag.startsWith("~")) { - return "~@" + tag.substring(1); - } - - return "@" + tag; - } - - public static Runtime createSerenityEnabledRuntime(/*ResourceLoader resourceLoader,*/ - Supplier classLoaderSupplier, - RuntimeOptions runtimeOptions, - Configuration systemConfiguration) { - RuntimeOptionsBuilder runtimeOptionsBuilder = new RuntimeOptionsBuilder(); - Collection allTagFilters = environmentSpecifiedTags(runtimeOptions.getTagExpressions()); - for (String tagFilter : allTagFilters) { - runtimeOptionsBuilder.addTagFilter(new LiteralExpression(tagFilter)); - } - runtimeOptionsBuilder.build(runtimeOptions); - setRuntimeOptions(runtimeOptions); - - - EventBus bus = new TimeServiceEventBus(Clock.systemUTC(), UUID::randomUUID); - FeatureParser parser = new FeatureParser(bus::generateId); - FeaturePathFeatureSupplier featureSupplier = new FeaturePathFeatureSupplier(classLoaderSupplier, runtimeOptions, parser); - - SerenityReporter serenityReporter = new SerenityReporter(systemConfiguration); - Runtime runtime = Runtime.builder().withClassLoader(classLoaderSupplier).withRuntimeOptions(runtimeOptions). - withAdditionalPlugins(serenityReporter). - withEventBus(bus).withFeatureSupplier(featureSupplier). - build(); - - return runtime; - } - private static void addSerenityReporterPlugin(Plugins plugins, SerenityReporter plugin) { for (Plugin currentPlugin : plugins.getPlugins()) { if (currentPlugin instanceof SerenityReporter) { @@ -303,7 +224,7 @@ public void setScheduler(RunnerScheduler scheduler) { public List> getChildren() { try { EnvironmentVariables environmentVariables = Injectors.getInjector().getInstance(EnvironmentVariables.class); - RuntimeOptions runtimeOptions = currentRuntimeOptions(); + RuntimeOptions runtimeOptions = CucumberWithSerenityRuntime.currentRuntimeOptions(); List tagFilters = runtimeOptions.getTagExpressions(); List featurePaths = runtimeOptions.getFeaturePaths(); int batchNumber = environmentVariables.getPropertyAsInteger(SERENITY_BATCH_NUMBER, 1); diff --git a/serenity-cucumber/src/main/java/io/cucumber/junit/LiteralExpression.java b/serenity-cucumber/src/main/java/io/cucumber/junit/LiteralExpression.java index f2da475069..c684fb446a 100644 --- a/serenity-cucumber/src/main/java/io/cucumber/junit/LiteralExpression.java +++ b/serenity-cucumber/src/main/java/io/cucumber/junit/LiteralExpression.java @@ -8,7 +8,7 @@ public class LiteralExpression implements Expression { private final String value; - LiteralExpression(String value) { + public LiteralExpression(String value) { this.value = value; } diff --git a/serenity-cucumber/src/main/java/net/serenitybdd/cucumber/CucumberWithSerenityRuntime.java b/serenity-cucumber/src/main/java/net/serenitybdd/cucumber/CucumberWithSerenityRuntime.java index d8eca1b3ec..036cc0a728 100644 --- a/serenity-cucumber/src/main/java/net/serenitybdd/cucumber/CucumberWithSerenityRuntime.java +++ b/serenity-cucumber/src/main/java/net/serenitybdd/cucumber/CucumberWithSerenityRuntime.java @@ -1,12 +1,30 @@ package net.serenitybdd.cucumber; +import io.cucumber.core.eventbus.EventBus; +import io.cucumber.core.feature.FeatureParser; +import io.cucumber.core.options.CucumberProperties; +import io.cucumber.core.options.CucumberPropertiesParser; import io.cucumber.core.options.RuntimeOptions; +import io.cucumber.core.options.RuntimeOptionsBuilder; import io.cucumber.core.plugin.SerenityReporter; +import io.cucumber.core.runtime.FeaturePathFeatureSupplier; import io.cucumber.core.runtime.Runtime; +import io.cucumber.core.runtime.TimeServiceEventBus; +import io.cucumber.junit.LiteralExpression; +import net.serenitybdd.cucumber.util.Splitter; +import net.thucydides.core.ThucydidesSystemProperty; import net.thucydides.core.guice.Injectors; +import net.thucydides.core.util.EnvironmentVariables; import net.thucydides.core.webdriver.Configuration; +import static java.util.stream.Collectors.toList; + +import java.time.Clock; +import java.util.Collection; +import java.util.List; +import java.util.UUID; +import java.util.function.Function; import java.util.function.Supplier; @@ -19,18 +37,91 @@ public static Runtime using(Supplier classLoaderSupplier, } - private static Runtime createSerenityEnabledRuntime(Supplier classLoaderSupplier, - RuntimeOptions runtimeOptions, - Configuration systemConfiguration) { - //ClassFinder resolvedClassFinder = Optional.ofNullable(classFinder).orElse(new ResourceLoaderClassFinder(resourceLoader, classLoader)); - SerenityReporter reporter = new SerenityReporter(systemConfiguration); - //Runtime runtime = Runtime.builder().withResourceLoader(resourceLoader).withClassFinder(resolvedClassFinder). - // withClassLoader(classLoader).withRuntimeOptions(runtimeOptions).withAdditionalPlugins(reporter).build(); + public static Runtime createSerenityEnabledRuntime(/*ResourceLoader resourceLoader,*/ + Supplier classLoaderSupplier, + RuntimeOptions runtimeOptions, + Configuration systemConfiguration) { + RuntimeOptionsBuilder runtimeOptionsBuilder = new RuntimeOptionsBuilder(); + Collection allTagFilters = environmentSpecifiedTags(runtimeOptions.getTagExpressions()); + for (String tagFilter : allTagFilters) { + runtimeOptionsBuilder.addTagFilter(new LiteralExpression(tagFilter)); + } + runtimeOptionsBuilder.build(runtimeOptions); + setRuntimeOptions(runtimeOptions); + + + EventBus bus = new TimeServiceEventBus(Clock.systemUTC(), UUID::randomUUID); + FeatureParser parser = new FeatureParser(bus::generateId); + FeaturePathFeatureSupplier featureSupplier = new FeaturePathFeatureSupplier(classLoaderSupplier, runtimeOptions, parser); + + SerenityReporter serenityReporter = new SerenityReporter(systemConfiguration); + Runtime runtime = Runtime.builder().withClassLoader(classLoaderSupplier).withRuntimeOptions(runtimeOptions). + withAdditionalPlugins(serenityReporter). + withEventBus(bus).withFeatureSupplier(featureSupplier). + build(); + + return runtime; + } - Runtime runtime = Runtime.builder(). - withClassLoader(classLoaderSupplier). - withRuntimeOptions(runtimeOptions). - withAdditionalPlugins(reporter).build(); - return runtime; - } + public static ThreadLocal RUNTIME_OPTIONS = new ThreadLocal<>(); + public static RuntimeOptions DEFAULT_RUNTIME_OPTIONS = buildRuntimeOptions(null); + + + public static RuntimeOptions buildRuntimeOptions(Function configurer) { + RuntimeOptions propertiesFileOptions = new CucumberPropertiesParser() + .parse(CucumberProperties.fromPropertiesFile()) + .build(); + + RuntimeOptions annotationOptions = configurer != null ? + configurer.apply(propertiesFileOptions) : propertiesFileOptions; + + RuntimeOptions environmentOptions = new CucumberPropertiesParser() + .parse(CucumberProperties.fromEnvironment()) + .build(annotationOptions); + + RuntimeOptions runtimeOptions = new CucumberPropertiesParser() + .parse(CucumberProperties.fromSystemProperties()) + .addDefaultSummaryPrinterIfNotDisabled() + .build(environmentOptions); + + RuntimeOptionsBuilder runtimeOptionsBuilder = new RuntimeOptionsBuilder(); + Collection tagFilters = environmentSpecifiedTags(runtimeOptions.getTagExpressions()); + for (String tagFilter : tagFilters) { + runtimeOptionsBuilder.addTagFilter(new LiteralExpression(tagFilter)); + } + runtimeOptionsBuilder.build(runtimeOptions); + return runtimeOptions; + } + + + public static void setRuntimeOptions(RuntimeOptions runtimeOptions) { + RUNTIME_OPTIONS.set(runtimeOptions); + } + + + public static RuntimeOptions currentRuntimeOptions() { + return (RUNTIME_OPTIONS.get() != null) ? RUNTIME_OPTIONS.get() : DEFAULT_RUNTIME_OPTIONS; + } + + + private static Collection environmentSpecifiedTags(List existingTags) { + EnvironmentVariables environmentVariables = Injectors.getInjector().getInstance(EnvironmentVariables.class); + String tagsExpression = ThucydidesSystemProperty.TAGS.from(environmentVariables, ""); + List existingTagsValues = existingTags.stream().map(Object::toString).collect(toList()); + return Splitter.on(",").trimResults().omitEmptyStrings().splitToList(tagsExpression).stream() + .map(CucumberWithSerenityRuntime::toCucumberTag).filter(t -> !existingTagsValues.contains(t)).collect(toList()); + } + + + public static String toCucumberTag(String from) { + String tag = from.replaceAll(":", "="); + if (tag.startsWith("~@") || tag.startsWith("@")) { + return tag; + } + if (tag.startsWith("~")) { + return "~@" + tag.substring(1); + } + + return "@" + tag; + } } diff --git a/serenity-cucumber/src/main/java/net/serenitybdd/cucumber/cli/Main.java b/serenity-cucumber/src/main/java/net/serenitybdd/cucumber/cli/Main.java index 267e82e201..a0acb126a4 100644 --- a/serenity-cucumber/src/main/java/net/serenitybdd/cucumber/cli/Main.java +++ b/serenity-cucumber/src/main/java/net/serenitybdd/cucumber/cli/Main.java @@ -4,7 +4,6 @@ import io.cucumber.core.options.RuntimeOptions; import io.cucumber.core.resource.ClassLoaders; import io.cucumber.core.runtime.Runtime; -import net.serenitybdd.cucumber.CucumberWithSerenity; import net.serenitybdd.cucumber.CucumberWithSerenityRuntime; import java.io.IOException; @@ -21,7 +20,7 @@ public static void main(String[] argv) throws Throwable { public static byte run(String[] argv, Supplier classLoaderSupplier) throws IOException { RuntimeOptions runtimeOptions = new CommandlineOptionsParser(System.out).parse(argv).build() ; - CucumberWithSerenity.setRuntimeOptions(runtimeOptions); + CucumberWithSerenityRuntime.setRuntimeOptions(runtimeOptions); Runtime runtime = CucumberWithSerenityRuntime.using(classLoaderSupplier, runtimeOptions); runtime.run(); diff --git a/serenity-cucumber/src/main/java/net/serenitybdd/cucumber/integration/intellij/CucumberWithSerenityRuntimeMain.java b/serenity-cucumber/src/main/java/net/serenitybdd/cucumber/integration/intellij/CucumberWithSerenityRuntimeMain.java index 2ae2f84edb..23d50ac61a 100644 --- a/serenity-cucumber/src/main/java/net/serenitybdd/cucumber/integration/intellij/CucumberWithSerenityRuntimeMain.java +++ b/serenity-cucumber/src/main/java/net/serenitybdd/cucumber/integration/intellij/CucumberWithSerenityRuntimeMain.java @@ -4,7 +4,7 @@ import io.cucumber.core.options.RuntimeOptions; import io.cucumber.core.resource.ClassLoaders; import io.cucumber.core.runtime.Runtime; -import net.serenitybdd.cucumber.CucumberWithSerenity; +import net.serenitybdd.cucumber.CucumberWithSerenityRuntime; import net.thucydides.core.guice.Injectors; import net.thucydides.core.webdriver.Configuration; @@ -42,7 +42,7 @@ public static byte run(String[] argv, Supplier classLoaderSupplier) //ResourceLoader resourceLoader = new MultiLoader(classLoader); Configuration systemConfiguration = Injectors.getInjector().getInstance(Configuration.class); //Supplier classLoader = ClassLoaders::getDefaultClassLoader; - Runtime serenityRuntime = CucumberWithSerenity.createSerenityEnabledRuntime(/*resourceLoader,*/ + Runtime serenityRuntime = CucumberWithSerenityRuntime.createSerenityEnabledRuntime(/*resourceLoader,*/ classLoaderSupplier, runtimeOptions, systemConfiguration); diff --git a/serenity-cucumber/src/main/java/net/serenitybdd/cucumber/model/StoredFeatureFile.java b/serenity-cucumber/src/main/java/net/serenitybdd/cucumber/model/StoredFeatureFile.java index f91ce90ea7..0f2025fbb2 100644 --- a/serenity-cucumber/src/main/java/net/serenitybdd/cucumber/model/StoredFeatureFile.java +++ b/serenity-cucumber/src/main/java/net/serenitybdd/cucumber/model/StoredFeatureFile.java @@ -1,6 +1,6 @@ package net.serenitybdd.cucumber.model; -import net.serenitybdd.cucumber.CucumberWithSerenity; +import net.serenitybdd.cucumber.CucumberWithSerenityRuntime; import java.io.File; import java.io.IOException; @@ -47,7 +47,7 @@ public File onTheFileSystem() { public File fromTheConfiguredPaths() throws IOException { - for(URI uri : CucumberWithSerenity.currentRuntimeOptions().getFeaturePaths()) { + for(URI uri : CucumberWithSerenityRuntime.currentRuntimeOptions().getFeaturePaths()) { if (Files.exists(candidatePath(uri, featureFileName))) { return candidatePath(uri, featureFileName).toFile(); } diff --git a/serenity-cucumber/src/test/java/io/cucumber/junit/CucumberRunner.java b/serenity-cucumber/src/test/java/io/cucumber/junit/CucumberRunner.java index 8d39e38b4f..69eb6e5a71 100644 --- a/serenity-cucumber/src/test/java/io/cucumber/junit/CucumberRunner.java +++ b/serenity-cucumber/src/test/java/io/cucumber/junit/CucumberRunner.java @@ -5,7 +5,7 @@ import io.cucumber.core.options.RuntimeOptionsBuilder; import io.cucumber.core.resource.ClassLoaders; import io.cucumber.core.runtime.Runtime; -import net.serenitybdd.cucumber.CucumberWithSerenity; +import net.serenitybdd.cucumber.CucumberWithSerenityRuntime; import net.thucydides.core.configuration.SystemPropertiesConfiguration; import net.thucydides.core.util.EnvironmentVariables; import net.thucydides.core.util.SystemEnvironmentVariables; @@ -43,7 +43,7 @@ public static Runtime serenityRunnerForCucumberTestRunner(Class testClass, Configuration systemConfiguration = new SystemPropertiesConfiguration(environmentVariables); systemConfiguration.setOutputDirectory(outputDirectory); Supplier classLoaderSupplier = ClassLoaders::getDefaultClassLoader; - return CucumberWithSerenity.createSerenityEnabledRuntime(classLoaderSupplier, annotationOptions, systemConfiguration); + return CucumberWithSerenityRuntime.createSerenityEnabledRuntime(classLoaderSupplier, annotationOptions, systemConfiguration); } public static Runtime serenityRunnerForCucumberTestRunner(Class testClass, Configuration systemConfiguration) { @@ -58,7 +58,7 @@ public static Runtime serenityRunnerForCucumberTestRunner(Class testClass, Confi RuntimeOptions runtimeOptionsBuilder = new RuntimeOptionsBuilder().build(annotationOptions); Supplier classLoaderSupplier = ClassLoaders::getDefaultClassLoader; - return CucumberWithSerenity.createSerenityEnabledRuntime( classLoaderSupplier, runtimeOptionsBuilder, systemConfiguration); + return CucumberWithSerenityRuntime.createSerenityEnabledRuntime( classLoaderSupplier, runtimeOptionsBuilder, systemConfiguration); } }