Skip to content

Commit

Permalink
Fix #39 There should be one single When step per scenario
Browse files Browse the repository at this point in the history
  • Loading branch information
racodond committed Dec 14, 2016
1 parent 0722874 commit ae55aa4
Show file tree
Hide file tree
Showing 11 changed files with 188 additions and 2 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ Number of features.
* Tags should comply with a naming convention
* Tags should not be set on Examples
* Then steps should follow a regular expression
* There should be one single When step per scenario
* Unused variables should be removed
* Useless tags should be removed
* When steps should follow a regular expression
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* SonarQube Gherkin Analyzer
* Copyright (C) 2016-2016 David RACODON
* [email protected]
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.gherkin.checks;

import com.google.common.collect.ImmutableList;
import org.sonar.check.Priority;
import org.sonar.check.Rule;
import org.sonar.plugins.gherkin.api.tree.BasicScenarioTree;
import org.sonar.plugins.gherkin.api.tree.StepTree;
import org.sonar.plugins.gherkin.api.tree.Tree;
import org.sonar.plugins.gherkin.api.visitors.SubscriptionVisitorCheck;
import org.sonar.plugins.gherkin.api.visitors.issue.PreciseIssue;
import org.sonar.squidbridge.annotations.ActivatedByDefault;
import org.sonar.squidbridge.annotations.SqaleConstantRemediation;

import java.util.List;
import java.util.stream.Collectors;

@Rule(
key = "one-single-when-per-scenario",
name = "There should be one single When step per scenario",
priority = Priority.MAJOR,
tags = {Tags.DESIGN})
@SqaleConstantRemediation("15min")
@ActivatedByDefault
public class OneSingleWhenPerScenarioCheck extends SubscriptionVisitorCheck {

@Override
public List<Tree.Kind> nodesToVisit() {
return ImmutableList.of(Tree.Kind.SCENARIO, Tree.Kind.SCENARIO_OUTLINE);
}

@Override
public void visitNode(Tree tree) {
List<StepTree> whenSteps = ((BasicScenarioTree) tree).steps()
.stream()
.filter(s -> s.type() == StepTree.StepType.WHEN)
.collect(Collectors.toList());

if (whenSteps.size() > 1) {
PreciseIssue issue = addPreciseIssue(whenSteps.get(0), "Merge all the When steps or split the scenario up in multiple scenarios.");
for (int i = 1; i < whenSteps.size(); i++) {
issue.secondary(whenSteps.get(i), "When step");
}
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<p>
There should be one single <code>When</code> step per scenario. If you feel compelled to add more, it is usually a
sign that you should split the scenario up in multiple scenarios or that some <code>When</code> steps could be
converted into <code>Given</code> steps.
</p>

<h2>Noncompliant Code Example</h2>
<pre>
Scenario: Add a nice bike to my cart
Given I am a customer
When I go to the nice bike product page
And I add the nice bike to my cart # Noncompliant
Then I should see the nice bike in my cart
</pre>

<h2>Compliant Solution</h2>
<pre>
Scenario: Add a nice bike to my cart
Given I am a customer
And I am on the nice bike product page
When I add the nice bike to my cart
Then I should see the nice bike in my cart
</pre>
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* SonarQube Gherkin Analyzer
* Copyright (C) 2016-2016 David RACODON
* [email protected]
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.gherkin.checks;

import org.junit.Test;
import org.sonar.gherkin.checks.verifier.GherkinCheckVerifier;

public class OneSingleWhenPerScenarioCheckTest {

@Test
public void test() {
GherkinCheckVerifier.verify(new OneSingleWhenPerScenarioCheck(), CheckTestUtils.getTestFile("one-single-when-per-scenario.feature"));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Feature: My feature One single when step per scenario
Blabla...

Scenario Outline: Scenario 1 - One single when step per scenario
Given Blabla given...
# Noncompliant [[sc=5;ec=33;secondary=+1]] {{Merge all the When steps or split the scenario up in multiple scenarios.}}
When Blabla when... <number>
And Blabla when and blabla when
Then Blabla then...
Examples:
| number |
| 1 |
| 2 |

Scenario: Scenario 2 - One single when step per scenario
Given Blabla given...
# Noncompliant [[sc=5;ec=24;secondary=+1]] {{Merge all the When steps or split the scenario up in multiple scenarios.}}
When Blabla when...
When Blabla when and blabla when...
Then Blabla then...
20 changes: 20 additions & 0 deletions its/ruling/projects/custom/one-single-when-per-scenario.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Feature: My feature One single when step per scenario
Blabla...

Scenario Outline: Scenario 1 - One single when step per scenario
Given Blabla given...
# Noncompliant [[sc=5;ec=33;secondary=+1]] {{Merge all the When steps or split the scenario up in multiple scenarios.}}
When Blabla when... <number>
And Blabla when and blabla when
Then Blabla then...
Examples:
| number |
| 1 |
| 2 |

Scenario: Scenario 2 - One single when step per scenario
Given Blabla given...
# Noncompliant [[sc=5;ec=24;secondary=+1]] {{Merge all the When steps or split the scenario up in multiple scenarios.}}
When Blabla when...
When Blabla when and blabla when...
Then Blabla then...
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
'project:custom/duplicated-steps/duplicates-in-background-and-scenarios.feature':[
19,
],
'project:custom/duplicated-steps/duplicates-in-scenarios.feature':[
17,
],
'project:custom/one-single-when-per-scenario.feature':[
7,
18,
],
'project:custom/steps-right-order.feature':[
6,
],
'project:custom/use-and-but.feature':[
25,
],
'project:custom/when-step-regular-expression.feature':[
7,
],
}
3 changes: 3 additions & 0 deletions its/ruling/tests/src/test/expected/gherkin-use-and-but.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
{
'project:custom/one-single-when-per-scenario.feature':[
19,
],
'project:custom/use-and-but.feature':[
7,
14,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ public static Collection<Class> getChecks() {
NoScenarioCheck.class,
NoStepCheck.class,
NoTagExamplesCheck.class,
OneSingleWhenPerScenarioCheck.class,
OnlyGivenStepsInBackgroundCheck.class,
ParsingErrorCheck.class,
SpellingCheck.class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public void should_create_sonarqube_way_profile() {

assertThat(profile.getName()).isEqualTo("SonarQube Way");
assertThat(profile.getLanguage()).isEqualTo("gherkin");
assertThat(profile.getActiveRulesByRepository("gherkin")).hasSize(35);
assertThat(profile.getActiveRulesByRepository("gherkin")).hasSize(36);
assertThat(validation.hasErrors()).isFalse();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public void test() {

assertThat(repository.name()).isEqualTo("SonarQube");
assertThat(repository.language()).isEqualTo("gherkin");
assertThat(repository.rules()).hasSize(44);
assertThat(repository.rules()).hasSize(45);

RulesDefinition.Rule lineLengthRule = repository.rule(TabCharacterCheck.class.getAnnotation(Rule.class).key());
assertThat(lineLengthRule).isNotNull();
Expand Down

0 comments on commit ae55aa4

Please sign in to comment.