Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

Combine tags on feature with tags on scenario to find if a scenario should run #107

Merged
merged 3 commits into from May 22, 2012
View
@@ -136,9 +136,52 @@ use private methods, mix in modules or whatever!
Then run your feature again running `spinach` and watch it all turn green! :)
-By default Spinach will ignore Scenarios marked with the tag `@wip`. Those are
-meant to be work in progress, scenarios that are pending while you work on
-them. To explicitly run those, use the `--tags` option:
+## Tags
+
+Feature and Scenarios can be marked with tags in the form: `@tag`. Tags can be
+used for different purpose:
+
+- applying some action using hooks (eg: @javascript, @transaction, @vcr)
+
+ # When using Capybara, you can switch the driver to use another one with
+ # javascript capabilities (Selenium, Poltergeist, capybara-webkit, ...)
+ #
+ # Spinach already integrates with Capybara if you `require spinach/capybara`
+ # in your `feature/support/env.rb`.
+ #
+ # This example is extracted from this intrgration.
+ Spinach.hooks.on_tag("javascript") do
+ ::Capybara.current_driver = ::Capybara.javascript_driver
+ end
+
+- filtering (eg: @module-a, @customer, @admin, @bug-12, @feat-1)
+
+ Given the following feature:
+
+ @feat-1
+ Feature: So something great
+
+ Scenario: Make it possible
+
+ @bug-12
+ Scenario: Ensure no regression on this
+
+ Then you can run all Scenarios in your suite related to `@feat-1` using:
+
+ spinach --tags @feat-1
+
+ Or only Scenarios related to `@feat-1` and `@bug-12` using:
+
+ spinach --tags @feat-1,@bug-12
+
+ Or only Scenarios related to `@feat-1` excluding `@bug-12` using:
+
+ spinach --tags @feat-1,~@bug-12
+
+By default Spinach will ignore Scenarios marked with the tag `@wip` or whose
+Feature is marked with the tag `@wip`. Those are meant to be work in progress,
+scenarios that are pending while you work on them. To explicitly run those, use
+the `--tags` option:
spinach --tags @wip
View
@@ -1,11 +1,12 @@
module Spinach
class Feature
attr_accessor :line
- attr_accessor :name, :scenarios
+ attr_accessor :name, :scenarios, :tags
attr_accessor :background
def initialize
@scenarios = []
+ @tags = []
end
def background_steps
@@ -38,6 +38,11 @@ def visit(ast)
def visit_Feature(node)
@feature.name = node.name
node.background.accept(self) if node.background
+
+ @current_tag_set = @feature
+ node.tags.each { |tag| tag.accept(self) }
+ @current_tag_set = nil
+
node.scenarios.each { |scenario| scenario.accept(self) }
end
@@ -69,9 +74,9 @@ def visit_Scenario(node)
scenario.name = node.name
scenario.line = node.line
- @current_scenario = scenario
+ @current_tag_set = scenario
node.tags.each { |tag| tag.accept(self) }
- @current_scenario = nil
+ @current_tag_set = nil
@current_step_set = scenario
node.steps.each { |step| step.accept(self) }
@@ -87,7 +92,7 @@ def visit_Scenario(node)
#
# @api public
def visit_Tag(node)
- @current_scenario.tags << node.name
+ @current_tag_set.tags << node.name
end
# Adds the step to the current scenario.
@@ -55,6 +55,14 @@ def run
private
+ def feature_tags
+ if @feature.respond_to?(:tags)
+ @feature.tags
+ else
+ []
+ end
+ end
+
def run_scenarios!
scenarios.each_with_index do |scenario, current_scenario_index|
if run_scenario?(scenario, current_scenario_index)
@@ -65,7 +73,8 @@ def run_scenarios!
end
def run_scenario?(scenario, current_scenario_index)
- match_line(current_scenario_index) && TagsMatcher.match(scenario.tags)
+ match_line(current_scenario_index) &&
+ TagsMatcher.match(feature_tags | scenario.tags)
end
def match_line(current_scenario_index)
@@ -1,4 +1,4 @@
-require 'test_helper'
+require_relative '../../test_helper'
module Spinach
class Parser
@@ -24,15 +24,28 @@ class Parser
describe '#visit_Feature' do
before do
@background = stub_everything
+ @tags = [stub_everything, stub_everything, stub_everything]
@scenarios = [stub_everything, stub_everything, stub_everything]
- @node = stub(scenarios: @scenarios, name: 'Go shopping', background: @background)
+ @node = stub(
+ scenarios: @scenarios,
+ name: 'Go shopping',
+ background: @background,
+ tags: @tags
+ )
end
it 'sets the name' do
visitor.visit_Feature(@node)
visitor.feature.name.must_equal 'Go shopping'
end
+ it 'sets the tags' do
+ @tags.each do |step|
+ step.expects(:accept).with visitor
+ end
+ visitor.visit_Feature(@node)
+ end
+
it 'iterates over its children' do
@scenarios.each do |scenario|
scenario.expects(:accept).with visitor
@@ -114,22 +114,22 @@
describe "when running for specific tags configured" do
before do
- @feature = stub('feature', name: 'Feature')
+ @feature = stub('feature', name: 'Feature', tags: ["feature_tag"])
Spinach.stubs(:find_step_definitions).returns(true)
- @scenario = stub(line: 4, tags: [])
+ @scenario = stub(line: 4, tags: ["scenario_tag"])
@feature.stubs(:scenarios).returns [@scenario]
end
it "runs matching scenario" do
- Spinach::TagsMatcher.stubs(:match).returns true
+ Spinach::TagsMatcher.expects(:match).with(["feature_tag", "scenario_tag"]).returns true
Spinach::Runner::ScenarioRunner.expects(:new).with(@scenario).returns stub(run: true)
@runner = Spinach::Runner::FeatureRunner.new(@feature)
@runner.run
end
it "skips scenarios that do not match" do
- Spinach::TagsMatcher.stubs(:match).returns false
+ Spinach::TagsMatcher.expects(:match).with(["feature_tag", "scenario_tag"]).returns false
Spinach::Runner::ScenarioRunner.expects(:new).never
@runner = Spinach::Runner::FeatureRunner.new(@feature)