Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions cucumber-bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@
<properties>
<ci-environment.version>10.0.1</ci-environment.version>
<cucumber-expressions.version>18.0.1</cucumber-expressions.version>
<cucumber-json-formatter.version>0.1.3</cucumber-json-formatter.version>
<cucumber-json-formatter.version>0.1.4-SNAPSHOT</cucumber-json-formatter.version>
<gherkin.version>34.0.0</gherkin.version>
<html-formatter.version>21.13.0</html-formatter.version>
<junit-xml-formatter.version>0.8.1</junit-xml-formatter.version>
<junit-xml-formatter.version>0.8.2-SNAPSHOT</junit-xml-formatter.version>
<messages.version>29.0.1</messages.version>
<pretty-formatter.version>2.1.0</pretty-formatter.version>
<query.version>13.6.0</query.version>
<pretty-formatter.version>2.1.1-SNAPSHOT</pretty-formatter.version>
<query.version>14.0.0</query.version>
<tag-expressions.version>6.1.2</tag-expressions.version>
<testng-xml-formatter.version>0.5.0</testng-xml-formatter.version>
<testng-xml-formatter.version>0.5.1-SNAPSHOT</testng-xml-formatter.version>
</properties>

<dependencyManagement>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,37 @@
package io.cucumber.core.plugin;

import io.cucumber.messages.types.Envelope;
import io.cucumber.messages.types.Snippet;
import io.cucumber.messages.types.Suggestion;
import io.cucumber.plugin.ColorAware;
import io.cucumber.plugin.ConcurrentEventListener;
import io.cucumber.plugin.event.EventPublisher;
import io.cucumber.plugin.event.SnippetsSuggestedEvent;
import io.cucumber.plugin.event.TestRunFinished;
import io.cucumber.query.Query;
import io.cucumber.query.Repository;

import java.io.OutputStream;
import java.io.PrintStream;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import static io.cucumber.query.Repository.RepositoryFeature.INCLUDE_GHERKIN_DOCUMENT;
import static io.cucumber.query.Repository.RepositoryFeature.INCLUDE_SUGGESTIONS;

public final class DefaultSummaryPrinter implements ColorAware, ConcurrentEventListener {

private final Set<String> snippets = new LinkedHashSet<>();
private final Repository repository = Repository.builder()
.feature(INCLUDE_GHERKIN_DOCUMENT, true)
.feature(INCLUDE_SUGGESTIONS, true)
.build();
private final Query query = new Query(repository);

private final Stats stats;
private final PrintStream out;

Expand All @@ -25,20 +41,15 @@ public DefaultSummaryPrinter() {

DefaultSummaryPrinter(OutputStream out, Locale locale) {
this.out = new PrintStream(out);
this.stats = new Stats(locale);
this.stats = new Stats(query, locale);
}

@Override
public void setEventPublisher(EventPublisher publisher) {
stats.setEventPublisher(publisher);
publisher.registerHandlerFor(SnippetsSuggestedEvent.class, this::handleSnippetsSuggestedEvent);
publisher.registerHandlerFor(Envelope.class, repository::update);
publisher.registerHandlerFor(TestRunFinished.class, event -> print());
}

private void handleSnippetsSuggestedEvent(SnippetsSuggestedEvent event) {
this.snippets.addAll(event.getSuggestion().getSnippets());
}

private void print() {
out.println();
printStats();
Expand All @@ -65,15 +76,25 @@ private void printErrors() {
}

private void printSnippets() {
Set<Snippet> snippets = query.findAllTestCaseFinished().stream()
.map(query::findPickleBy)
.filter(Optional::isPresent)
.map(Optional::get)
.map(query::findSuggestionsBy)
.flatMap(Collection::stream)
.map(Suggestion::getSnippets)
.flatMap(Collection::stream)
.collect(Collectors.toCollection(LinkedHashSet::new));

if (snippets.isEmpty()) {
return;
}

out.println();
out.println("You can implement missing steps with the snippets below:");
out.println();
for (String snippet : snippets) {
out.println(snippet);
for (Snippet snippet : snippets) {
out.println(snippet.getCode());
out.println();
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,65 +1,52 @@
package io.cucumber.core.plugin;

import io.cucumber.core.feature.FeatureWithLines;
import io.cucumber.messages.types.Envelope;
import io.cucumber.messages.types.TestCaseFinished;
import io.cucumber.messages.types.TestStepResult;
import io.cucumber.messages.types.TestStepResultStatus;
import io.cucumber.plugin.ConcurrentEventListener;
import io.cucumber.plugin.event.EventPublisher;
import io.cucumber.plugin.event.TestCase;
import io.cucumber.plugin.event.TestCaseFinished;
import io.cucumber.plugin.event.TestRunFinished;
import io.cucumber.query.Query;
import io.cucumber.query.Repository;

import java.io.File;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collection;
import java.nio.charset.StandardCharsets;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

import static io.cucumber.core.feature.FeatureWithLines.create;
import static io.cucumber.query.Repository.RepositoryFeature.INCLUDE_GHERKIN_DOCUMENT;
import static java.util.Objects.requireNonNull;

/**
* Formatter for reporting all failed test cases and print their locations
* Failed means: results that make the exit code non-zero.
* Formatter for reporting all failed test cases and print their locations.
*/
public final class RerunFormatter implements ConcurrentEventListener {

private final UTF8PrintWriter out;
private final Map<URI, Collection<Integer>> featureAndFailedLinesMapping = new LinkedHashMap<>();
private final PrintWriter writer;
private final Map<String, Set<Integer>> featureAndFailedLinesMapping = new LinkedHashMap<>();
private final Repository repository = Repository.builder()
.feature(INCLUDE_GHERKIN_DOCUMENT, true)
.build();
private final Query query = new Query(repository);

public RerunFormatter(OutputStream out) {
this.out = new UTF8PrintWriter(out);
this.writer = createPrintWriter(out);
}

@Override
public void setEventPublisher(EventPublisher publisher) {
publisher.registerHandlerFor(TestCaseFinished.class, this::handleTestCaseFinished);
publisher.registerHandlerFor(TestRunFinished.class, event -> finishReport());
}

private void handleTestCaseFinished(TestCaseFinished event) {
if (!event.getResult().getStatus().isOk()) {
recordTestFailed(event.getTestCase());
}
}

private void finishReport() {
for (Map.Entry<URI, Collection<Integer>> entry : featureAndFailedLinesMapping.entrySet()) {
FeatureWithLines featureWithLines = create(relativize(entry.getKey()), entry.getValue());
out.println(featureWithLines.toString());
}

out.close();
}

private void recordTestFailed(TestCase testCase) {
URI uri = testCase.getUri();
Collection<Integer> failedTestCaseLines = getFailedTestCaseLines(uri);
failedTestCaseLines.add(testCase.getLocation().getLine());
}

private Collection<Integer> getFailedTestCaseLines(URI uri) {
return featureAndFailedLinesMapping.computeIfAbsent(uri, k -> new ArrayList<>());
private static PrintWriter createPrintWriter(OutputStream out) {
return new PrintWriter(
new OutputStreamWriter(
requireNonNull(out),
StandardCharsets.UTF_8));
}

static URI relativize(URI uri) {
Expand All @@ -79,4 +66,46 @@ static URI relativize(URI uri) {
throw new IllegalArgumentException(e.getMessage(), e);
}
}

@Override
public void setEventPublisher(EventPublisher publisher) {
publisher.registerHandlerFor(Envelope.class, event -> {
repository.update(event);
event.getTestCaseFinished().ifPresent(this::handleTestCaseFinished);
event.getTestRunFinished().ifPresent(testRunFinished -> finishReport());
});
}

private void handleTestCaseFinished(TestCaseFinished event) {
TestStepResultStatus testStepResultStatus = query.findMostSevereTestStepResultBy(event)
.map(TestStepResult::getStatus)
// By definition
.orElse(TestStepResultStatus.PASSED);

if (testStepResultStatus == TestStepResultStatus.PASSED
|| testStepResultStatus == TestStepResultStatus.SKIPPED) {
return;
}

query.findPickleBy(event).ifPresent(pickle -> {
Set<Integer> lines = featureAndFailedLinesMapping
.computeIfAbsent(pickle.getUri(), s -> new HashSet<>());
query.findLocationOf(pickle).ifPresent(location -> {
// TODO: Messages are silly
lines.add((int) (long) location.getLine());
});
});
}

private void finishReport() {
for (Map.Entry<String, Set<Integer>> entry : featureAndFailedLinesMapping.entrySet()) {
String key = entry.getKey();
// TODO: Should these be relative?
FeatureWithLines featureWithLines = create(relativize(URI.create(key)), entry.getValue());
writer.println(featureWithLines);
}

writer.close();
}

}
Loading
Loading