diff --git a/CHANGELOG.md b/CHANGELOG.md index f70086f6..f6ad01ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. Back to [Readme](README.md). +## [3.4.0] - 2023-08-10 + +### Fixed +* Background steps were not considered in the overall scenario outcome [#319] +* Background steps were not shown in the bar charts + +### Changed +* Skipped scenarios are now determined to the official Cucumber guidelines +* Charts show small bars for steps with a time of 0 instead of none at all +* Before and after hooks are not shown in the step charts anymore + ## [3.3.1] - 2023-08-08 ### Fixed @@ -751,6 +762,7 @@ steps with status `pending` or `undefined` (default value is `false`) (#74) Initial project version on GitHub and Maven Central. +[3.4.0]: https://github.com/trivago/cluecumber-report-plugin/tree/3.4.0 [3.3.1]: https://github.com/trivago/cluecumber-report-plugin/tree/3.3.1 [3.3.0]: https://github.com/trivago/cluecumber-report-plugin/tree/3.3.0 [3.2.2]: https://github.com/trivago/cluecumber-report-plugin/tree/3.2.2 diff --git a/core/pom.xml b/core/pom.xml index 5f38fbbf..baab4519 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -6,13 +6,13 @@ 4.0.0 cluecumber-core - 3.3.1 + 3.4.0 jar cluecumber-parent com.trivago.rta - 3.3.1 + 3.4.0 Cluecumber Core diff --git a/engine/pom.xml b/engine/pom.xml index 02180278..1ff117ef 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -8,11 +8,11 @@ cluecumber-parent com.trivago.rta - 3.3.1 + 3.4.0 cluecumber-engine - 3.3.1 + 3.4.0 jar Cluecumber Engine diff --git a/engine/src/main/java/com/trivago/cluecumber/engine/constants/Status.java b/engine/src/main/java/com/trivago/cluecumber/engine/constants/Status.java index 4cd73205..ce98f9cb 100644 --- a/engine/src/main/java/com/trivago/cluecumber/engine/constants/Status.java +++ b/engine/src/main/java/com/trivago/cluecumber/engine/constants/Status.java @@ -32,6 +32,7 @@ import java.util.Arrays; import java.util.List; +import java.util.Set; /** * Enum to manage all states for steps and scenarios. @@ -65,7 +66,7 @@ public enum Status { /** * The three basic states: passed, failed and skipped. */ - public static final List BASIC_STATES = Arrays.asList(Status.PASSED, Status.FAILED, Status.SKIPPED); + public static final List BASIC_STATES = Arrays.asList(Status.FAILED, Status.SKIPPED, Status.PASSED); private final String status; @@ -79,10 +80,37 @@ public enum Status { * @param status The status string. * @return The matching {@link Status} enum. */ - public static Status fromString(String status) { + public static Status fromString(final String status) { return valueOf(status.toUpperCase()); } + public Status basicStatus() { + switch (this) { + case PASSED: + return Status.PASSED; + case FAILED: + return Status.FAILED; + default: + return Status.SKIPPED; + } + } + + /** + * Return the highest status from the given list of states. + * + * @return The status string. + */ + public static Status getHighestBasicState(Set allStates) { + for (Status basicState : BASIC_STATES) { + for (Status allState : allStates) { + if (allState.basicStatus() == basicState) { + return basicState; + } + } + } + return FAILED; + } + /** * Return the status string from this enum. * diff --git a/engine/src/main/java/com/trivago/cluecumber/engine/json/pojo/Element.java b/engine/src/main/java/com/trivago/cluecumber/engine/json/pojo/Element.java index 0d56be98..0fc4fa39 100644 --- a/engine/src/main/java/com/trivago/cluecumber/engine/json/pojo/Element.java +++ b/engine/src/main/java/com/trivago/cluecumber/engine/json/pojo/Element.java @@ -22,6 +22,8 @@ import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; /** * This represents a scenarios. @@ -358,73 +360,17 @@ public boolean isSkipped() { * @return The overall status. */ public Status getStatus() { - int totalSteps = steps.size(); - - if (totalSteps == 0) { - return Status.SKIPPED; - } - - // If any hooks fail, report the scenario as failed - for (ResultMatch beforeHook : before) { - if (beforeHook.isFailed()) { - return Status.FAILED; - } - } - for (ResultMatch afterHook : after) { - if (afterHook.isFailed()) { - return Status.FAILED; - } + Set allStates = before.stream().map(ResultMatch::getStatus).collect(Collectors.toSet()); + backgroundSteps.stream().map(ResultMatch::getStatus).forEach(allStates::add); + steps.stream().map(ResultMatch::getStatus).forEach(allStates::add); + after.stream().map(ResultMatch::getStatus).forEach(allStates::add); + + if (failOnPendingOrUndefined && allStates.size() == 1 + && allStates.iterator().next().basicStatus() == Status.SKIPPED) { + return Status.FAILED; } - // If all steps have the same status, return this as the scenario status. - for (Status status : Status.BASIC_STATES) { - int stepsWithCertainStatusCount = 0; - for (Step step : steps) { - if (step.getConsolidatedStatus() == status) { - stepsWithCertainStatusCount++; - } - - // If any step hooks fail, report scenario as failed. - for (ResultMatch beforeStepHook : step.getBefore()) { - if (beforeStepHook.isFailed()) { - return Status.FAILED; - } - } - for (ResultMatch afterStepHook : step.getAfter()) { - if (afterStepHook.isFailed()) { - return Status.FAILED; - } - } - } - - if (totalSteps == stepsWithCertainStatusCount) { - if (status == Status.SKIPPED) { - if (failOnPendingOrUndefined) { - return Status.FAILED; - } - } - return status; - } - } - - // If at least one step passed and the other steps are skipped, return skipped (or failed if failOnPendingOrUndefined is true). - if (getTotalNumberOfPassedSteps() >= 0 && - (getTotalNumberOfSkippedSteps() + getTotalNumberOfPassedSteps()) == getTotalNumberOfSteps()) { - if (failOnPendingOrUndefined) { - return Status.FAILED; - } - return Status.SKIPPED; - } - - // If all steps are skipped return skipped (or failed if failOnPendingOrUndefined is true). - if (getTotalNumberOfSkippedSteps() == totalSteps) { - if (failOnPendingOrUndefined) { - return Status.FAILED; - } - return Status.SKIPPED; - } - - return Status.FAILED; + return Status.getHighestBasicState(allStates); } /** @@ -534,7 +480,7 @@ public void setScenarioIndex(final int scenarioIndex) { * @return The number of steps. */ public int getTotalNumberOfSteps() { - return getSteps().size(); + return getAllStepsIncludingBackgroundSteps().size(); } /** @@ -571,7 +517,7 @@ public int getTotalNumberOfSkippedSteps() { * @return The number of step. */ private int getNumberOfStepsWithStatus(final Status status) { - return (int) getSteps().stream().filter(step -> step.getConsolidatedStatus() == status).count(); + return (int) getAllStepsIncludingBackgroundSteps().stream().filter(step -> step.getConsolidatedStatus() == status).count(); } /** @@ -685,8 +631,7 @@ public boolean hasStepHooksWithContent() { */ public List getAllResultMatches() { List resultMatches = new ArrayList<>(getBefore()); - resultMatches.addAll(getBackgroundSteps()); - resultMatches.addAll(getSteps()); + resultMatches.addAll(getAllStepsIncludingBackgroundSteps()); resultMatches.addAll(getAfter()); return resultMatches; } @@ -753,4 +698,10 @@ public String getFeatureUri() { public void setFeatureUri(String featureUri) { this.featureUri = featureUri; } + + public List getAllStepsIncludingBackgroundSteps() { + List combinedSteps = new ArrayList<>(backgroundSteps); + combinedSteps.addAll(steps); + return combinedSteps; + } } diff --git a/engine/src/main/java/com/trivago/cluecumber/engine/json/pojo/ResultMatch.java b/engine/src/main/java/com/trivago/cluecumber/engine/json/pojo/ResultMatch.java index 61b49935..c288a23e 100644 --- a/engine/src/main/java/com/trivago/cluecumber/engine/json/pojo/ResultMatch.java +++ b/engine/src/main/java/com/trivago/cluecumber/engine/json/pojo/ResultMatch.java @@ -201,19 +201,8 @@ public boolean hasContent() { * @return The basic {@link Status} enum. */ public Status getConsolidatedStatus() { - switch (getStatus()) { - case PASSED: - return Status.PASSED; - case SKIPPED: - case PENDING: - case AMBIGUOUS: - case UNDEFINED: - return Status.SKIPPED; - case FAILED: - default: - return Status.FAILED; - } - } + return getStatus().basicStatus(); + } /** * Get the string of the basic status. diff --git a/engine/src/main/java/com/trivago/cluecumber/engine/rendering/pages/charts/ChartJsonConverter.java b/engine/src/main/java/com/trivago/cluecumber/engine/rendering/pages/charts/ChartJsonConverter.java index 566020e2..4c1bfa38 100644 --- a/engine/src/main/java/com/trivago/cluecumber/engine/rendering/pages/charts/ChartJsonConverter.java +++ b/engine/src/main/java/com/trivago/cluecumber/engine/rendering/pages/charts/ChartJsonConverter.java @@ -17,6 +17,7 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; import com.trivago.cluecumber.engine.rendering.pages.charts.pojos.Chart; import javax.inject.Inject; diff --git a/engine/src/main/java/com/trivago/cluecumber/engine/rendering/pages/charts/pojos/Dataset.java b/engine/src/main/java/com/trivago/cluecumber/engine/rendering/pages/charts/pojos/Dataset.java index e42c11f9..c4dce728 100644 --- a/engine/src/main/java/com/trivago/cluecumber/engine/rendering/pages/charts/pojos/Dataset.java +++ b/engine/src/main/java/com/trivago/cluecumber/engine/rendering/pages/charts/pojos/Dataset.java @@ -15,6 +15,7 @@ */ package com.trivago.cluecumber.engine.rendering.pages.charts.pojos; +import java.util.ArrayList; import java.util.List; diff --git a/engine/src/main/java/com/trivago/cluecumber/engine/rendering/pages/pojos/pagecollections/AllStepsPageCollection.java b/engine/src/main/java/com/trivago/cluecumber/engine/rendering/pages/pojos/pagecollections/AllStepsPageCollection.java index e4c463d5..49e2fd20 100644 --- a/engine/src/main/java/com/trivago/cluecumber/engine/rendering/pages/pojos/pagecollections/AllStepsPageCollection.java +++ b/engine/src/main/java/com/trivago/cluecumber/engine/rendering/pages/pojos/pagecollections/AllStepsPageCollection.java @@ -20,10 +20,7 @@ import com.trivago.cluecumber.engine.rendering.pages.pojos.ResultCount; import com.trivago.cluecumber.engine.rendering.pages.pojos.Times; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * Page collection for the step overview page. @@ -129,7 +126,11 @@ private void calculateStepResultCounts(final List reports) { if (reports == null) return; reports.forEach(report -> report.getElements().forEach(element -> { int scenarioIndex = element.getScenarioIndex(); - element.getSteps().forEach(step -> { + + List steps = new ArrayList<>(element.getBackgroundSteps()); + steps.addAll(element.getSteps()); + + steps.forEach(step -> { ResultCount stepResultCount = stepResultCounts.getOrDefault(step, new ResultCount()); updateResultCount(stepResultCount, step.getStatus()); stepResultCounts.put(step, stepResultCount); diff --git a/engine/src/main/java/com/trivago/cluecumber/engine/rendering/pages/renderering/AllScenariosPageRenderer.java b/engine/src/main/java/com/trivago/cluecumber/engine/rendering/pages/renderering/AllScenariosPageRenderer.java index 32e65b68..e64a011e 100644 --- a/engine/src/main/java/com/trivago/cluecumber/engine/rendering/pages/renderering/AllScenariosPageRenderer.java +++ b/engine/src/main/java/com/trivago/cluecumber/engine/rendering/pages/renderering/AllScenariosPageRenderer.java @@ -122,13 +122,13 @@ public String getRenderedContentByStepFilter( AllScenariosPageCollection allScenariosPageCollectionClone = getAllScenariosPageCollectionClone(allScenariosPageCollection); allScenariosPageCollectionClone.setStepFilter(step); - allScenariosPageCollectionClone.getReports().forEach(report -> { + for (Report report : allScenariosPageCollectionClone.getReports()) { List elements = report.getElements() .stream() - .filter(element -> element.getSteps().contains(step)) + .filter(element -> element.getSteps().contains(step) || element.getBackgroundSteps().contains(step)) .collect(Collectors.toList()); report.setElements(elements); - }); + } addChartJsonToReportDetails(allScenariosPageCollectionClone); return processedContent(template, allScenariosPageCollectionClone, propertyManager.getNavigationLinks()); diff --git a/engine/src/main/java/com/trivago/cluecumber/engine/rendering/pages/renderering/AllStepsPageRenderer.java b/engine/src/main/java/com/trivago/cluecumber/engine/rendering/pages/renderering/AllStepsPageRenderer.java index 9217d48a..d24f89f3 100644 --- a/engine/src/main/java/com/trivago/cluecumber/engine/rendering/pages/renderering/AllStepsPageRenderer.java +++ b/engine/src/main/java/com/trivago/cluecumber/engine/rendering/pages/renderering/AllStepsPageRenderer.java @@ -82,7 +82,7 @@ public String getRenderedContent( return processedContent(template, allStepsPageCollection, propertyManager.getNavigationLinks()); } - private void addChartJsonToReportDetails(final AllStepsPageCollection allTagsPageCollection) { + private void addChartJsonToReportDetails(final AllStepsPageCollection allStepsPageCollection) { List passed = new ArrayList<>(); List failed = new ArrayList<>(); @@ -90,7 +90,7 @@ private void addChartJsonToReportDetails(final AllStepsPageCollection allTagsPag Map urlLookup = new HashMap<>(); int maximumNumberOfRuns = 0; - for (Map.Entry entry : allTagsPageCollection.getStepResultCounts().entrySet()) { + for (Map.Entry entry : allStepsPageCollection.getStepResultCounts().entrySet()) { urlLookup.put( entry.getKey().returnNameWithArgumentPlaceholders(), Settings.PAGES_DIRECTORY + Settings.STEP_SCENARIO_PAGE_FRAGMENT + @@ -104,7 +104,7 @@ private void addChartJsonToReportDetails(final AllStepsPageCollection allTagsPag } } - List keys = allTagsPageCollection.getStepResultCounts() + List keys = allStepsPageCollection.getStepResultCounts() .keySet() .stream() .map(Step::returnNameWithArgumentPlaceholders) @@ -113,7 +113,7 @@ private void addChartJsonToReportDetails(final AllStepsPageCollection allTagsPag Chart chart = new StackedBarChartBuilder(chartConfiguration) .setLabels(keys) - .setxAxisLabel(allTagsPageCollection.getTotalNumberOfSteps() + " Steps") + .setxAxisLabel(allStepsPageCollection.getTotalNumberOfSteps() + " Steps") .setyAxisStepSize(maximumNumberOfRuns) .setyAxisLabel("Number of Usages") .addValues(passed, Status.PASSED) @@ -122,7 +122,7 @@ private void addChartJsonToReportDetails(final AllStepsPageCollection allTagsPag .build(); - allTagsPageCollection.getReportDetails().setChartJson(convertChartToJson(chart)); - allTagsPageCollection.getReportDetails().setChartUrlLookup(urlLookup); + allStepsPageCollection.getReportDetails().setChartJson(convertChartToJson(chart)); + allStepsPageCollection.getReportDetails().setChartUrlLookup(urlLookup); } } diff --git a/engine/src/main/java/com/trivago/cluecumber/engine/rendering/pages/renderering/ScenarioDetailsPageRenderer.java b/engine/src/main/java/com/trivago/cluecumber/engine/rendering/pages/renderering/ScenarioDetailsPageRenderer.java index 548e54ae..7cb33038 100644 --- a/engine/src/main/java/com/trivago/cluecumber/engine/rendering/pages/renderering/ScenarioDetailsPageRenderer.java +++ b/engine/src/main/java/com/trivago/cluecumber/engine/rendering/pages/renderering/ScenarioDetailsPageRenderer.java @@ -20,7 +20,6 @@ import com.trivago.cluecumber.engine.constants.Status; import com.trivago.cluecumber.engine.exceptions.CluecumberException; import com.trivago.cluecumber.engine.json.pojo.Element; -import com.trivago.cluecumber.engine.json.pojo.ResultMatch; import com.trivago.cluecumber.engine.json.pojo.Step; import com.trivago.cluecumber.engine.properties.PropertyManager; import com.trivago.cluecumber.engine.rendering.pages.charts.ChartJsonConverter; @@ -91,9 +90,7 @@ private void addChartJsonToReportDetails(final ScenarioDetailsPageCollection sce Element element = scenarioDetailsPageCollection.getElement(); List labels = new ArrayList<>(); - element.getBefore().stream().map(ResultMatch::getGlueMethodName).forEach(labels::add); - element.getSteps().stream().map(Step::getName).forEach(labels::add); - element.getAfter().stream().map(ResultMatch::getGlueMethodName).forEach(labels::add); + element.getAllStepsIncludingBackgroundSteps().stream().map(Step::getName).forEach(labels::add); final List passedValues = getValuesByStatus(element, Status.PASSED); final List failedValues = getValuesByStatus(element, Status.FAILED); @@ -139,9 +136,13 @@ private void addChartJsonToReportDetails(final ScenarioDetailsPageCollection sce private List getValuesByStatus(final Element element, final Status status) { List values = new ArrayList<>(); - element.getAllResultMatches().forEach(resultMatch -> { + element.getAllStepsIncludingBackgroundSteps().forEach(resultMatch -> { if (resultMatch.getConsolidatedStatus() == status) { - values.add(resultMatch.getResult().getDurationInMilliseconds() / 1000f); + float time = resultMatch.getResult().getDurationInMilliseconds() / 1000f; + if (time == 0) { + time = 0.1f; + } + values.add(time); } else { values.add(0f); } diff --git a/engine/src/main/java/com/trivago/cluecumber/engine/rendering/pages/visitors/StepVisitor.java b/engine/src/main/java/com/trivago/cluecumber/engine/rendering/pages/visitors/StepVisitor.java index b5ae7565..63895828 100644 --- a/engine/src/main/java/com/trivago/cluecumber/engine/rendering/pages/visitors/StepVisitor.java +++ b/engine/src/main/java/com/trivago/cluecumber/engine/rendering/pages/visitors/StepVisitor.java @@ -90,6 +90,7 @@ public void visit(final AllScenariosPageCollection allScenariosPageCollection) t Settings.STEP_SUMMARY_PAGE + Settings.HTML_FILE_EXTENSION); // Scenarios by step pages + for (Step step : allStepsPageCollection.getSteps()) { fileIO.writeContentToFile( allScenariosPageRenderer.getRenderedContentByStepFilter( diff --git a/engine/src/main/resources/template/snippets/js.ftl b/engine/src/main/resources/template/snippets/js.ftl index 76b5f4a8..4a426f7f 100644 --- a/engine/src/main/resources/template/snippets/js.ftl +++ b/engine/src/main/resources/template/snippets/js.ftl @@ -49,10 +49,9 @@ limitations under the License. // Chart <#if (reportDetails.chartJson?has_content)> var canvas = document.getElementById('chart-area'); - var ctx = canvas.getContext("2d"); - var chart = new Chart(ctx, ${reportDetails.chartJson}); - - var original; + const ctx = canvas.getContext("2d"); + const chart = new Chart(ctx, ${reportDetails.chartJson}); + let original; if (chart.config.type === "pie") { original = Chart.defaults.pie.legend.onClick; chart.options.onClick = function (evt, elements) { @@ -89,7 +88,7 @@ limitations under the License. }; function toggleVisibilityByStatus(statusText, show) { - var card = $("#card_" + statusText); + const card = $("#card_" + statusText); if (card !== undefined) { if (show) { card.show(); @@ -98,7 +97,7 @@ limitations under the License. } } - var row = $(".table-row-" + statusText); + const row = $(".table-row-" + statusText); if (row !== undefined) { if (show) { row.show(); diff --git a/examples/core-example/pom.xml b/examples/core-example/pom.xml index 38eb6dc6..5209a35b 100644 --- a/examples/core-example/pom.xml +++ b/examples/core-example/pom.xml @@ -6,7 +6,7 @@ blog.softwaretester core-example - 3.3.1 + 3.4.0 pom diff --git a/examples/maven-example/.gitignore b/examples/maven-example/.gitignore index 5cede485..755b4ebb 100644 --- a/examples/maven-example/.gitignore +++ b/examples/maven-example/.gitignore @@ -1,4 +1,5 @@ target/ cluecumber-test-project.iml json2 -json3 \ No newline at end of file +json3 +json/skip2.json \ No newline at end of file diff --git a/examples/maven-example/pom.xml b/examples/maven-example/pom.xml index c66468c0..daa09f54 100644 --- a/examples/maven-example/pom.xml +++ b/examples/maven-example/pom.xml @@ -6,7 +6,7 @@ blog.softwaretester maven-example - 3.3.1 + 3.4.0 pom diff --git a/makefile b/makefile index 26676b4a..82b558ac 100644 --- a/makefile +++ b/makefile @@ -1,4 +1,4 @@ build-and-test: - mvn clean install + mvn clean install -DskipTests=true mvn verify -f=examples/maven-example open examples/maven-example/target/cluecumber-report/index.html \ No newline at end of file diff --git a/maven/pom.xml b/maven/pom.xml index 2d99b558..bd9ef457 100644 --- a/maven/pom.xml +++ b/maven/pom.xml @@ -7,12 +7,12 @@ cluecumber-maven maven-plugin - 3.3.1 + 3.4.0 cluecumber-parent com.trivago.rta - 3.3.1 + 3.4.0 Cluecumber Maven diff --git a/pom.xml b/pom.xml index 47f2bb61..9865478d 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ com.trivago.rta cluecumber-parent - 3.3.1 + 3.4.0 pom Cluecumber Parent