Skip to content

Commit

Permalink
Merge pull request #151 from trivago/1.6.0
Browse files Browse the repository at this point in the history
1.6.0
  • Loading branch information
Benjamin Bischoff authored Dec 10, 2019
2 parents 4a1b0b6 + 4cd6a7b commit b8076dc
Show file tree
Hide file tree
Showing 10 changed files with 73 additions and 31 deletions.
14 changes: 13 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

Back to [Readme](README.md).

## [1.5.3] - UNRELEASED
## [1.6.0] - 2019-12-10

### Changed

* Cucable is now more resilient when trying to deal with unparsable features - these are skipped instead of stopping the overall execution.

### Fixed

* Utf-8 encoding error on linux (#150)
* Scenarios had too many tags when there were also feature tags (#145)

## [1.5.3] - 2019-09-09

### Added

Expand Down Expand Up @@ -271,6 +282,7 @@ Back to [Readme](README.md).
Initial project version on GitHub and Maven Central.
[1.6.0]: https://github.com/trivago/cucable-plugin/compare/1.5.3...1.6.0
[1.5.3]: https://github.com/trivago/cucable-plugin/compare/1.5.2...1.5.3
[1.5.2]: https://github.com/trivago/cucable-plugin/compare/1.5.1...1.5.2
[1.5.1]: https://github.com/trivago/cucable-plugin/compare/1.5.0...1.5.1
Expand Down
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@
[![codecov](https://codecov.io/gh/trivago/cucable-plugin/branch/master/graph/badge.svg)](https://codecov.io/gh/trivago/cucable-plugin)
[![Twitter URL](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/bischoffdev)

---

### Note:

This project is feature-complete. Expect only bug fixes at this time.
For new projects, you should consider using Cucumber's native parallelization feature instead.

Thanks to everyone using, testing and improving Cucable over the last years!

---

![Cucumber compatible](documentation/img/cucumber-compatible-black-64.png)

<!-- START doctoc generated TOC please keep comment here to allow auto update -->
Expand All @@ -16,6 +27,7 @@

- [Cucable Maven Plugin](#cucable-maven-plugin)
- [Cucumber 4](#cucumber-4)
- [Cucumber 5](#cucumber-5)
- [Repository Structure](#repository-structure)
- [Changelog](#changelog)
- [Maven dependency](#maven-dependency)
Expand Down Expand Up @@ -84,6 +96,10 @@ Even though Cucumber 4 supports basic parallel runs, Cucable has more options th
* You don't need any test framework changes because Cucable runs before the framework invocations
* You have full control over your runners because of template variables and custom placeholders

## Cucumber 5

* Cucumber 5 (using testng or junit 5) can natively run features and scenarios in parallel. Cucable __can__ be used but does not __have__ to be.

## Repository Structure

* [plugin-code](plugin-code) contains the full plugin source code.
Expand Down
2 changes: 1 addition & 1 deletion example-project/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

<groupId>com.trivago.rta</groupId>
<artifactId>cucable-test-project</artifactId>
<version>1.5.2</version>
<version>1.6.0</version>
<packaging>jar</packaging>

<properties>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,9 @@ Feature: MyTest1InTestFeature2
@scenario1Tag1
@scenario1Tag2
Scenario: Scenario 1 in MyTest1InTestFeature2
Given I do something
Given I do something

@Login
Scenario: Login
Given this is a given step
Given I am on a page with text 'İ'
8 changes: 4 additions & 4 deletions plugin-code/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>com.trivago.rta</groupId>
<artifactId>cucable-plugin</artifactId>
<version>1.5.3</version>
<version>1.6.0</version>
<url>https://github.com/trivago/cucable-plugin</url>

<name>Cucable Maven Plugin</name>
Expand Down Expand Up @@ -80,9 +80,9 @@
<tag.expressions.version>2.0.2</tag.expressions.version>
<apache.commons.version>3.9</apache.commons.version>

<mockito.version>3.0.0</mockito.version>
<junit5.vintage.version>5.5.1</junit5.vintage.version>
<openpojo.version>0.8.12</openpojo.version>
<mockito.version>3.2.0</mockito.version>
<junit5.vintage.version>5.6.0-M1</junit5.vintage.version>
<openpojo.version>0.8.13</openpojo.version>
</properties>

<profiles>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@ private String getRenderedFeatureFileContent(List<SingleScenario> singleScenario

for (SingleScenario singleScenario : singleScenarios) {
renderedContent.append(LINE_SEPARATOR);
addTags(renderedContent, singleScenario.getScenarioTags());
List<String> scenarioTags = singleScenario.getScenarioTags();
if (scenarioTags != null && firstScenario.getFeatureTags() != null) {
scenarioTags.removeAll(firstScenario.getFeatureTags());
}
addTags(renderedContent, scenarioTags);
addTags(renderedContent, singleScenario.getExampleTags());

addNameAndDescription(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,6 @@ private int generateRunnerClassesWithDesiredNumberOfFeatures(
* @throws CucablePluginException see {@link CucablePluginException}.
*/
private void generateRunnerClass(final List<String> generatedFeatureFileNames) throws CucablePluginException {

// The runner class name will be equal to the feature name if there is only one feature to run.
// Otherwise, a generated runner class name is used.
String runnerClassName;
Expand Down
4 changes: 2 additions & 2 deletions plugin-code/src/main/java/com/trivago/files/FileIO.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public class FileIO {
*/
public void writeContentToFile(String content, String filePath) throws FileCreationException {
try {
FileUtils.fileWrite(filePath, content);
FileUtils.fileWrite(filePath, "UTF-8", content);
} catch (IOException e) {
throw new FileCreationException(filePath);
}
Expand All @@ -53,7 +53,7 @@ public void writeContentToFile(String content, String filePath) throws FileCreat
*/
public String readContentFromFile(String filePath) throws MissingFileException {
try {
return FileUtils.fileRead(filePath);
return FileUtils.fileRead(filePath, "UTF-8");
} catch (IOException e) {
throw new MissingFileException(filePath);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,23 @@
package com.trivago.gherkin;

import com.trivago.exceptions.CucablePluginException;
import com.trivago.logging.CucableLogger;
import com.trivago.properties.PropertyManager;
import com.trivago.vo.DataTable;
import com.trivago.vo.SingleScenario;
import com.trivago.vo.Step;
import gherkin.AstBuilder;
import gherkin.Parser;
import gherkin.ParserException;
import gherkin.ast.Background;
import gherkin.ast.Examples;
import gherkin.ast.Feature;
import gherkin.ast.GherkinDocument;
import gherkin.ast.Scenario;
import gherkin.ast.ScenarioDefinition;
import gherkin.ast.ScenarioOutline;
import gherkin.ast.*;
import io.cucumber.tagexpressions.Expression;
import io.cucumber.tagexpressions.TagExpressionException;
import io.cucumber.tagexpressions.TagExpressionParser;

import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
Expand All @@ -52,16 +48,18 @@ public class GherkinDocumentParser {
private final GherkinToCucableConverter gherkinToCucableConverter;
private final GherkinTranslations gherkinTranslations;
private final PropertyManager propertyManager;
private final CucableLogger cucableLogger;

@Inject
GherkinDocumentParser(
final GherkinToCucableConverter gherkinToCucableConverter,
final GherkinTranslations gherkinTranslations,
final PropertyManager propertyManager
) {
final PropertyManager propertyManager,
final CucableLogger logger) {
this.gherkinToCucableConverter = gherkinToCucableConverter;
this.gherkinTranslations = gherkinTranslations;
this.propertyManager = propertyManager;
this.cucableLogger = logger;
}

/**
Expand All @@ -81,6 +79,10 @@ public List<SingleScenario> getSingleScenariosFromFeature(
GherkinDocument gherkinDocument = getGherkinDocumentFromFeatureFileContent(escapedFeatureContent);

Feature feature = gherkinDocument.getFeature();
if (feature == null) {
return Collections.emptyList();
}

String featureName = feature.getKeyword() + ": " + feature.getName();
String featureLanguage = feature.getLanguage();
String featureDescription = feature.getDescription();
Expand Down Expand Up @@ -161,7 +163,6 @@ public List<SingleScenario> getSingleScenariosFromFeature(
* @param featureLanguage The feature language this scenario outline belongs to.
* @param featureTags The feature tags of the parent feature.
* @param backgroundSteps Return a Cucable {@link SingleScenario} list.
* @throws CucablePluginException Thrown when the scenario outline does not contain an example table.
*/
private List<SingleScenario> getSingleScenariosFromOutline(
final ScenarioOutline scenarioOutline,
Expand All @@ -171,7 +172,7 @@ private List<SingleScenario> getSingleScenariosFromOutline(
final String featureDescription,
final List<String> featureTags,
final List<Step> backgroundSteps
) throws CucablePluginException {
) {

// Retrieve the translation of "Scenario" in the target language and add it to the scenario
String translatedScenarioKeyword = gherkinTranslations.getScenarioKeyword(featureLanguage);
Expand All @@ -185,7 +186,8 @@ private List<SingleScenario> getSingleScenariosFromOutline(
List<Step> steps = gherkinToCucableConverter.convertGherkinStepsToCucableSteps(scenarioOutline.getSteps());

if (scenarioOutline.getExamples().isEmpty()) {
throw new CucablePluginException("Scenario outline without examples table!");
cucableLogger.warn("Scenario outline without example table!");
return outlineScenarios;
}

for (Examples exampleTable : scenarioOutline.getExamples()) {
Expand Down Expand Up @@ -314,7 +316,7 @@ private GherkinDocument getGherkinDocumentFromFeatureFileContent(final String fe
}

if (gherkinDocument == null || gherkinDocument.getFeature() == null) {
throw new CucablePluginException("Could not parse features from gherkin document!");
cucableLogger.warn("No parsable gherkin.");
}

return gherkinDocument;
Expand All @@ -326,7 +328,7 @@ private GherkinDocument getGherkinDocumentFromFeatureFileContent(final String fe
*
* @param singleScenario a single scenario object.
* @return true if an include tag and no exclude tags are included in the source tag list and scenario name
* (if specified) matches.
* (if specified) matches.
*/
private boolean scenarioShouldBeIncluded(SingleScenario singleScenario) throws CucablePluginException {

Expand Down Expand Up @@ -354,10 +356,10 @@ private boolean scenarioShouldBeIncluded(SingleScenario singleScenario) throws C
/**
* Checks if a scenarioName value matches with the scenario name.
*
* @param language Feature file language ("en", "ro" etc).
* @param language Feature file language ("en", "ro" etc).
* @param stringToMatch the string that will be matched with the scenarioName value.
* @return index of the scenarioName value in the scenarioNames list if a match exists.
* -1 if no match exists.
* -1 if no match exists.
*/
public int matchScenarioWithScenarioNames(String language, String stringToMatch) {
List<String> scenarioNames = propertyManager.getScenarioNames();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.trivago.gherkin;

import com.trivago.exceptions.CucablePluginException;
import com.trivago.logging.CucableLogger;
import com.trivago.properties.PropertyManager;
import com.trivago.vo.DataTable;
import com.trivago.vo.SingleScenario;
Expand All @@ -15,25 +16,28 @@
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.*;
import static org.mockito.Mockito.times;

public class GherkinDocumentParserTest {

private GherkinDocumentParser gherkinDocumentParser;
private PropertyManager propertyManager;
private CucableLogger mockedLogger;

@Before
public void setup() {
GherkinToCucableConverter gherkinToCucableConverter = new GherkinToCucableConverter();
GherkinTranslations gherkinTranslations = new GherkinTranslations();
propertyManager = mock(PropertyManager.class);
gherkinDocumentParser = new GherkinDocumentParser(gherkinToCucableConverter, gherkinTranslations, propertyManager);
mockedLogger = mock(CucableLogger.class);
gherkinDocumentParser = new GherkinDocumentParser(gherkinToCucableConverter, gherkinTranslations, propertyManager, mockedLogger);
}

@Test(expected = CucablePluginException.class)
@Test
public void invalidFeatureTest() throws Exception {
gherkinDocumentParser.getSingleScenariosFromFeature("", "", null);
verify(mockedLogger, times(1)).warn("No parsable gherkin.");
}

@Test
Expand Down

0 comments on commit b8076dc

Please sign in to comment.