Skip to content

Commit

Permalink
Support tags on scenario outline examples
Browse files Browse the repository at this point in the history
closes #456
resolves #305
  • Loading branch information
charlierudolph committed Nov 16, 2015
1 parent 68e84d4 commit 95c6f29
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Feature: Target specific scenarios
As a developer running features
I want an easy way to run specific scenarios
I want an easy way to run specific scenarios by line
So that I don't waste time running my whole test suite when I don't need to

Background:
Expand Down
103 changes: 103 additions & 0 deletions features/target_specific_scenarios_by_tag.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
Feature: Target specific scenarios
As a developer running features
I want an easy way to run specific scenarios by tag
So that I don't waste time running my whole test suite when I don't need to

Background:
Given a file named "features/a.feature" with:
"""
Feature: some feature
@a
Scenario: first scenario
When a step is passing
@b
Scenario Outline: second scenario
When a step is <STATUS>
@c
Examples:
| STATUS |
| passing |
| pending |
@d
Examples:
| STATUS |
| undefined |
"""
And a file named "features/step_definitions/cucumber_steps.js" with:
"""
var cucumberSteps = function() {
this.When(/^a step is passing$/, function() { });
this.When(/^a step is pending$/, function(callback) { callback.pending() });
};
module.exports = cucumberSteps;
"""

Scenario: run a single scenario
When I run cucumber.js with `--tags @a`
Then it outputs this text:
"""
Feature: some feature
@a
Scenario: first scenario # features/a.feature:3
When a step is passing # features/step_definitions/cucumber_steps.js:2
1 scenario (1 passed)
1 step (1 passed)
<duration-stat>
"""
And the exit status should be 0

Scenario: run a single scenario outline
When I run cucumber.js with `--tags @b`
Then it outputs this text:
"""
Feature: some feature
@b @c
Scenario Outline: second scenario # features/a.feature:13
When a step is passing # features/step_definitions/cucumber_steps.js:2
@b @c
Scenario Outline: second scenario # features/a.feature:14
When a step is pending # features/step_definitions/cucumber_steps.js:3
@b @d
Scenario Outline: second scenario # features/a.feature:19
When a step is undefined
3 scenarios (1 undefined, 1 pending, 1 passed)
3 steps (1 undefined, 1 pending, 1 passed)
<duration-stat>
You can implement step definitions for undefined steps with these snippets:
this.When(/^a step is (.*)$/, function (status, callback) {
// Write code here that turns the phrase above into concrete actions
callback.pending();
});
"""
And the exit status should be 0

Scenario: run a single scenario outline examples
When I run cucumber.js with `--tags @c`
Then it outputs this text:
"""
Feature: some feature
@b @c
Scenario Outline: second scenario # features/a.feature:13
When a step is passing # features/step_definitions/cucumber_steps.js:2
@b @c
Scenario Outline: second scenario # features/a.feature:14
When a step is pending # features/step_definitions/cucumber_steps.js:3
2 scenarios (1 pending, 1 passed)
2 steps (1 pending, 1 passed)
<duration-stat>
"""
And the exit status should be 0
6 changes: 6 additions & 0 deletions lib/cucumber/ast/assembler.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ function Assembler(features, filter) {
element.addTags(revealedTags);
},

applyStashedTagsToExamples: function applyStashedTagsToExamples(examples) {
var revealedTags = self.revealTags();
examples.setTags(revealedTags);
},

insertBackground: function insertBackground(background) {
self.setCurrentFeatureElement(background);
var currentFeature = self.getCurrentFeature();
Expand Down Expand Up @@ -85,6 +90,7 @@ function Assembler(features, filter) {
var currentFeatureElement = self.getCurrentFeatureElement();
if (!currentFeatureElement.isScenarioOutline())
throw new Error('Examples are allowed inside scenario outlines only');
self.applyStashedTagsToExamples(examples);
currentFeatureElement.addExamples(examples);
self.setCurrentStep(examples);
},
Expand Down
9 changes: 9 additions & 0 deletions lib/cucumber/ast/examples.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
function Examples(keyword, name, description, line) {
var Cucumber = require('../../cucumber');
var dataTable;
var tags = [];

var self = {
setTags: function addTags(newTags) {
tags = newTags;
},

getTags: function getTags() {
return tags;
},

getKeyword: function getKeyword() {
return keyword;
},
Expand Down
2 changes: 0 additions & 2 deletions lib/cucumber/ast/feature.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,7 @@ function Feature(keyword, name, description, uri, line) {
var scenarios = scenarioOutline.buildScenarios();
var scenarioOutlineIndex = featureElements.indexOf(scenarioOutline);
featureElements.removeAtIndex(scenarioOutlineIndex);
var scenarioOutlineTags = scenarioOutline.getTags();
scenarios.forEach(function (scenario, index) {
scenario.addTags(scenarioOutlineTags);
self.insertFeatureElement(scenarioOutlineIndex + index, scenario);
});
},
Expand Down
7 changes: 5 additions & 2 deletions lib/cucumber/ast/scenario_outline.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ function ScenarioOutline(keyword, name, description, uri, line) {
examplesCollection.add(examples);
};

function buildScenario(example, rowLine) {
function buildScenario(example, rowLine, examplesTags) {
var newName = self.applyExampleRowToScenarioName(example, name);
var newSteps = self.applyExampleRowToSteps(example, self.getSteps());
var subScenario = Cucumber.Ast.Scenario(keyword, newName, description, uri, rowLine, line);
subScenario.setSteps(newSteps);
subScenario.addTags(self.getTags());
subScenario.addTags(examplesTags);
return subScenario;
}

Expand All @@ -26,11 +28,12 @@ function ScenarioOutline(keyword, name, description, uri, line) {
examplesCollection.forEach(function (examples) {
var exampleRows = examples.getDataTable().getRows();
var keys = exampleRows.shift().raw();
var tags = examples.getTags();
exampleRows.forEach(function (exampleRow) {
var data = exampleRow.raw();
var rowLine = exampleRow.getLine();
var hash = _.zipObject(keys, data);
scenarios.add(buildScenario(hash, rowLine));
scenarios.add(buildScenario(hash, rowLine, tags));
});
});

Expand Down
2 changes: 1 addition & 1 deletion spec/cucumber/ast/assembler_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ describe("Cucumber.Ast.Assembler", function () {
var examples, currentFeatureElement;

beforeEach(function () {
examples = createSpy("examples");
examples = createSpyWithStubs("examples", {setTags: null});
currentFeatureElement = createSpyWithStubs("current feature element", {isScenarioOutline: true, addExamples: null});
spyOn(assembler, 'getCurrentFeatureElement').and.returnValue(currentFeatureElement);
spyOn(assembler, 'setCurrentStep');
Expand Down
8 changes: 0 additions & 8 deletions spec/cucumber/ast/feature_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,10 +200,6 @@ describe("Cucumber.Ast.Feature", function () {
expect(scenarioCollection.removeAtIndex).toHaveBeenCalledWith(scenarioOutlineIndex);
});

it("gets the tags from the scenario outline just once", function () {
expect(scenarioOutline.getTags).toHaveBeenCalledTimes(1);
});

it ("iterates over the scenarios", function () {
expect(scenarios.forEach).toHaveBeenCalled();
expect(scenarios.forEach).toHaveBeenCalledWithAFunctionAsNthParameter(1);
Expand All @@ -220,10 +216,6 @@ describe("Cucumber.Ast.Feature", function () {
userFunction (scenario, index);
});

it("adds the scenario outline's tags to the scenario", function () {
expect(scenario.addTags).toHaveBeenCalledWith(scenarioOutlineTags);
});

it("inserts the scenario into the scenario collection", function () {
expect(feature.insertFeatureElement).toHaveBeenCalledWith(scenarioOutlineIndex + index, scenario);
});
Expand Down

0 comments on commit 95c6f29

Please sign in to comment.