aslakhellesoy-cucumber 0.2.3.4 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -13,7 +13,17 @@ The Visitor API (which is used for formatters) has also changed slightly. Howeve
13
13
  do this in a backwards compatible way, so if you have custom formatters for Cucumber 0.2 they should
14
14
  still work.
15
15
 
16
+ One of the most significant new features is Tagged Hooks: http://wiki.github.com/aslakhellesoy/cucumber/hooks
17
+ This lets you associate Before and After blocks with specific scenarios.
18
+
19
+ We are also deprecating the step_list, step_pattern, feature_list, and feature_pattern accessors on
20
+ Cucumber::Rake::Task. These accessors will be completely removed in version 0.4. For complex settings
21
+ please rely on cucumber profiles in your rake tasks:
22
+ http://wiki.github.com/aslakhellesoy/cucumber/using-rake#profiles
23
+
16
24
  === New features
25
+ * Use Hooks with @tags (#229 Aslak Hellesøy)
26
+ * Rake task supports cucumber.yml profiles (#187 Ben Mabey)
17
27
  * Field value steps for Webrat (Jack Chen)
18
28
  * Added translation for Bulgarian (Krasimir Angelov)
19
29
  * Updated translation for Polish (#273 Grzegorz Marszałek)
@@ -26,6 +36,7 @@ still work.
26
36
  * Support description string for Backgrounds (#271 Joseph Wilk)
27
37
 
28
38
  === Bugfixes
39
+ * After methods not being executed when Background fails (#288 Luismi Cavallé)
29
40
  * Fixed dependency on internal files in rspec breaks cucumber w/ rspec-1.2.4 (#291 Aslak Hellesøy)
30
41
  * Fix color use when using autotest on Linux. (Hans de Graaff)
31
42
  * Fixed incorrect calculation of pystring indentation (#279 Eugene Naydanov)
data/Manifest.txt CHANGED
@@ -182,6 +182,8 @@ examples/tickets/features/177/1.feature
182
182
  examples/tickets/features/177/2.feature
183
183
  examples/tickets/features/177/3.feature
184
184
  examples/tickets/features/180.feature
185
+ examples/tickets/features/229/tagged_hooks.feature
186
+ examples/tickets/features/229/tagged_hooks.rb
185
187
  examples/tickets/features/236.feature
186
188
  examples/tickets/features/241.feature
187
189
  examples/tickets/features/246.feature
@@ -209,6 +211,7 @@ features/cucumber_cli.feature
209
211
  features/cucumber_cli_diff_disabled.feature
210
212
  features/cucumber_cli_outlines.feature
211
213
  features/custom_formatter.feature
214
+ features/rake_task.feature
212
215
  features/report_called_undefined_steps.feature
213
216
  features/snippet.feature
214
217
  features/step_definitions/cucumber_steps.rb
data/config/hoe.rb CHANGED
@@ -53,7 +53,7 @@ $hoe = Hoe.new(GEM_NAME, VERS) do |p|
53
53
  p.summary = DESCRIPTION
54
54
  p.url = HOMEPATH
55
55
  p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
56
- p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store', '**/*.class', '**/*.jar'] #An array of file patterns to delete on clean.
56
+ p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store', '**/*.class', '**/*.jar', '**/tmp'] #An array of file patterns to delete on clean.
57
57
 
58
58
  # == Optional
59
59
  p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
data/cucumber.yml CHANGED
@@ -1 +1 @@
1
- default: --format progress features
1
+ default: --format progress features --tags ~@pending
@@ -4,7 +4,7 @@ Feature: Passing background sample
4
4
  Given '10' cukes
5
5
 
6
6
  Scenario: passing background
7
- Then I should have '10' cukes
8
-
7
+ Then I should have '10' cukes
8
+
9
9
  Scenario: another passing background
10
10
  Then I should have '10' cukes
@@ -68,3 +68,13 @@ end
68
68
 
69
69
  Given /^another unused$/ do
70
70
  end
71
+
72
+ after_file = File.dirname(__FILE__) + '/../../tmp/after.txt'
73
+
74
+ Before('@after_file') do
75
+ FileUtils.rm(after_file) if File.exist?(after_file)
76
+ end
77
+
78
+ After('@after_file') do
79
+ FileUtils.touch(after_file)
80
+ end
@@ -0,0 +1,8 @@
1
+ Feature: Tagged hooks
2
+ In order to provide more flexible setups
3
+ I should be able to specify exactly
4
+ where hooks are executed
5
+
6
+ @i_am_so_special
7
+ Scenario: Yes I am
8
+ When special me goes to town
@@ -0,0 +1,14 @@
1
+ require 'spec/expectations'
2
+
3
+ Before('@i_am_so_special') do
4
+ @something_special = 10
5
+ end
6
+
7
+ After('@i_am_so_special') do
8
+ @something_special.should == 20
9
+ end
10
+
11
+ When /special me goes to town/ do
12
+ @something_special.should == 10
13
+ @something_special = 20
14
+ end
@@ -1,6 +1,7 @@
1
1
  require 'spec/expectations'
2
2
 
3
3
  require File.dirname(__FILE__) + '/../../../../features/step_definitions/cucumber_steps.rb'
4
+ require File.dirname(__FILE__) + '/../../../../features/support/env.rb'
4
5
 
5
6
  Given /^multiline string$/ do |string|
6
7
  @string = string
@@ -1,12 +1,5 @@
1
1
  require 'spec/expectations'
2
2
 
3
- World do
4
- Object.new
5
- end
6
-
7
- After do |scenario|
8
- end
9
-
10
3
  Given "be_empty" do
11
4
  [1,2].should_not be_empty
12
5
  end
@@ -93,6 +93,7 @@ Feature: backgrounds
93
93
  5 skipped steps
94
94
 
95
95
  """
96
+ And "examples/self_test/tmp/after.txt" should exist
96
97
 
97
98
  Scenario: run a feature with scenario outlines that has a background that fails
98
99
  When I run cucumber -q features/background/scenario_outline_failing_background.feature --require features
@@ -0,0 +1,132 @@
1
+ Feature: Rake task
2
+ In order to ease the development process
3
+ As a developer and CI server administrator
4
+ Cucumber features should be executable via Rake
5
+
6
+ Background:
7
+ Given a standard Cucumber project directory structure
8
+ And a file named "features/missing_step_definitions.feature" with:
9
+ """
10
+ Feature: Sample
11
+
12
+ Scenario: Wanted
13
+ Given I want to run this
14
+
15
+ Scenario: Unwanted
16
+ Given I don't want this ran
17
+ """
18
+
19
+
20
+ Scenario: rake task with a defined profile
21
+ Given the following profile is defined:
22
+ """
23
+ foo: --quiet --no-color features/missing_step_definitions.feature:3
24
+ """
25
+ And a file named "Rakefile" with:
26
+ """
27
+ $LOAD_PATH.unshift(CUCUMBER_LIB)
28
+ require 'cucumber/rake/task'
29
+
30
+ Cucumber::Rake::Task.new(:features) do |t|
31
+ t.profile = "foo"
32
+ end
33
+ """
34
+
35
+ When I run rake features
36
+ Then it should pass
37
+ And the output should contain
38
+ """
39
+ Feature: Sample
40
+
41
+ Scenario: Wanted
42
+ Given I want to run this
43
+
44
+ 1 scenario
45
+ 1 undefined step
46
+ """
47
+
48
+ Scenario: rake task with a defined profile and cucumber_opts
49
+ Given the following profile is defined:
50
+ """
51
+ bar: features/missing_step_definitions.feature:3
52
+ """
53
+ And a file named "Rakefile" with:
54
+ """
55
+ $LOAD_PATH.unshift(CUCUMBER_LIB)
56
+ require 'cucumber/rake/task'
57
+
58
+ Cucumber::Rake::Task.new(:features) do |t|
59
+ t.profile = "bar"
60
+ t.cucumber_opts = "--quiet --no-color"
61
+ end
62
+ """
63
+
64
+ When I run rake features
65
+ Then it should pass
66
+ And the output should contain
67
+ """
68
+ Feature: Sample
69
+
70
+ Scenario: Wanted
71
+ Given I want to run this
72
+
73
+ 1 scenario
74
+ 1 undefined step
75
+ """
76
+
77
+ Scenario: rake task with a defined profile and feature list
78
+ Given a file named "features/the_one_i_want_to_run.feature" with:
79
+ """
80
+ Feature: Desired
81
+
82
+ Scenario: Something
83
+ Given this is missing
84
+ """
85
+ Given the following profile is defined:
86
+ """
87
+ baz: --quiet --no-color
88
+ """
89
+ And a file named "Rakefile" with:
90
+ """
91
+ $LOAD_PATH.unshift(CUCUMBER_LIB)
92
+ require 'cucumber/rake/task'
93
+
94
+ Cucumber::Rake::Task.new(:features) do |t|
95
+ t.profile = "baz"
96
+ t.feature_list = ['features/the_one_i_want_to_run.feature']
97
+ end
98
+ """
99
+
100
+ When I run rake features
101
+ Then it should pass
102
+ And the output should contain
103
+ """
104
+ Feature: Desired
105
+
106
+ Scenario: Something
107
+ Given this is missing
108
+
109
+ 1 scenario
110
+ 1 undefined step
111
+ """
112
+
113
+ Scenario: deprecation warnings
114
+ Given a file named "Rakefile" with:
115
+ """
116
+ $LOAD_PATH.unshift(CUCUMBER_LIB)
117
+ require 'cucumber/rake/task'
118
+
119
+ Cucumber::Rake::Task.new(:features) do |t|
120
+ t.feature_list = ['features/missing_step_definitions.feature']
121
+ end
122
+ """
123
+ When I run rake features
124
+ Then it should pass
125
+ And STDERR should match
126
+ """
127
+ Cucumber::Rake::Task#feature_list is deprecated and will be removed in 0.4.0. Please use profiles for complex settings: http://wiki.github.com/aslakhellesoy/cucumber/using-rake#profiles
128
+ """
129
+
130
+
131
+
132
+
@@ -1,32 +1,46 @@
1
- require 'tempfile'
2
-
3
- Given /^I am in (.*)$/ do |dir|
4
- @dir = dir
1
+ Given /^I am in (.*)$/ do |example_dir_relative_path|
2
+ @current_dir = examples_dir(example_dir_relative_path)
5
3
  end
6
4
 
7
- When /^I run cucumber (.*)$/ do |cmd|
8
- @dir ||= 'self_test'
9
- full_dir ||= File.expand_path(File.dirname(__FILE__) + "/../../examples/#{@dir}")
10
- @stderr = Tempfile.new('cucumber')
11
- @stderr.close
12
- Dir.chdir(full_dir) do
13
- @full_cmd = "#{Cucumber::RUBY_BINARY} #{Cucumber::BINARY} --no-color #{cmd} 2> #{@stderr.path}"
14
- @out = `#{@full_cmd}`
15
- @status = $?.exitstatus
5
+ Given /^a standard Cucumber project directory structure$/ do
6
+ @current_dir = working_dir
7
+ in_current_dir do
8
+ FileUtils.mkdir_p 'features/support'
9
+ FileUtils.mkdir 'features/step_definitions'
16
10
  end
17
11
  end
18
12
 
19
- Then /^it should (fail|pass) with$/ do |success, output|
20
- @out.should == output
13
+ Given /^a file named "([^\"]*)" with:$/ do |file_name, file_content|
14
+ create_file(file_name, file_content)
15
+ end
16
+
17
+ Given /^the following profiles? (?:are|is) defined:$/ do |profiles|
18
+ create_file('cucumber.yml', profiles)
19
+ end
20
+
21
+ When /^I run cucumber (.*)$/ do |cucumber_opts|
22
+ run "#{Cucumber::RUBY_BINARY} #{Cucumber::BINARY} --no-color #{cucumber_opts}"
23
+ end
24
+
25
+ When /^I run rake (.*)$/ do |rake_opts|
26
+ run "rake #{rake_opts}"
27
+ end
28
+
29
+ Then /^it should (fail|pass)$/ do |success|
21
30
  if success == 'fail'
22
- @status.should_not == 0
31
+ last_exit_status.should_not == 0
23
32
  else
24
- @status.should == 0
33
+ last_exit_status.should == 0
25
34
  end
26
35
  end
27
36
 
37
+ Then /^it should (fail|pass) with$/ do |success, output|
38
+ last_stdout.should == output
39
+ Then("it should #{success}")
40
+ end
41
+
28
42
  Then /^the output should contain$/ do |text|
29
- @out.should include(text)
43
+ last_stdout.should include(text)
30
44
  end
31
45
 
32
46
  Then /^"(.*)" should contain$/ do |file, text|
@@ -38,5 +52,10 @@ Then /^"(.*)" should match$/ do |file, text|
38
52
  end
39
53
 
40
54
  Then /^STDERR should match$/ do |text|
41
- Then %{"#{@stderr.path}" should match}, text
55
+ last_stderr.should =~ /#{text}/
56
+ end
57
+
58
+ Then /^"(.*)" should exist$/ do |file|
59
+ File.exists?(file).should be_true
60
+ FileUtils.rm(file)
42
61
  end
@@ -1,8 +1,65 @@
1
1
  require 'rubygems'
2
+ require 'tempfile'
2
3
  require 'spec/expectations'
3
4
  require 'fileutils'
5
+ require 'forwardable'
4
6
 
5
- After do
6
- FileUtils.rm_rf 'examples/self_test/tmp'
7
- FileUtils.mkdir 'examples/self_test/tmp'
8
- end
7
+ class CucumberWorld
8
+ extend Forwardable
9
+ def_delegators CucumberWorld, :examples_dir, :self_test_dir, :working_dir, :cucumber_lib_dir
10
+
11
+ def self.examples_dir(subdir=nil)
12
+ @examples_dir ||= File.expand_path(File.join(File.dirname(__FILE__), '../../examples'))
13
+ subdir ? File.join(@examples_dir, subdir) : @examples_dir
14
+ end
15
+
16
+ def self.self_test_dir
17
+ @self_test_dir ||= examples_dir('self_test')
18
+ end
19
+
20
+ def self.working_dir
21
+ @working_dir ||= examples_dir('self_test/tmp')
22
+ end
23
+
24
+ def cucumber_lib_dir
25
+ @cucumber_lib_dir ||= File.expand_path(File.join(File.dirname(__FILE__), '../../lib'))
26
+ end
27
+
28
+ def initialize
29
+ @current_dir = self_test_dir
30
+ end
31
+
32
+ private
33
+ attr_reader :last_exit_status, :last_stdout, :last_stderr
34
+
35
+ def create_file(file_name, file_content)
36
+ file_content.gsub!("CUCUMBER_LIB", "'#{cucumber_lib_dir}'") # Some files, such as Rakefiles need to use the lib dir
37
+ in_current_dir do
38
+ File.open(file_name, 'w') { |f| f << file_content }
39
+ end
40
+ end
41
+
42
+ def in_current_dir(&block)
43
+ Dir.chdir(@current_dir, &block)
44
+ end
45
+
46
+ def run(command)
47
+ stderr_file = Tempfile.new('cucumber')
48
+ stderr_file.close
49
+ in_current_dir do
50
+ @last_stdout = `#{command} 2> #{stderr_file.path}`
51
+ @last_exit_status = $?.exitstatus
52
+ end
53
+ @last_stderr = IO.read(stderr_file.path)
54
+ end
55
+
56
+ end
57
+
58
+ World do
59
+ CucumberWorld.new
60
+ end
61
+
62
+ Before do
63
+ FileUtils.rm_rf CucumberWorld.working_dir
64
+ FileUtils.mkdir CucumberWorld.working_dir
65
+ end
@@ -5,7 +5,7 @@ end
5
5
 
6
6
  namespace :manifest do
7
7
  desc 'Recreate Manifest.txt to include ALL files'
8
- task :refresh do
8
+ task :refresh => :clobber do
9
9
  `rake check_manifest | patch -p0 > Manifest.txt`
10
10
  end
11
11
  end
@@ -24,9 +24,19 @@ module Cucumber
24
24
  def accept(visitor)
25
25
  visitor.visit_comment(@comment)
26
26
  visitor.visit_background_name(@keyword, @name, file_colon_line(@line), source_indent(text_length))
27
- visitor.step_mother.before_and_after(self)
27
+ visitor.step_mother.before(self)
28
28
  visitor.visit_steps(@step_invocations)
29
29
  @failed = @step_invocations.detect{|step_invocation| step_invocation.exception}
30
+ visitor.step_mother.after(self) if @failed
31
+ end
32
+
33
+ def accept_hook?(hook)
34
+ # TODO: When background is involved - no tag based hook filtering is occurring with
35
+ # the current implementation. All hooks will be executed. This is because of the line
36
+ # visitor.step_mother.before(self)
37
+ # in the #accept method above. Instead, we should really be passing the first scenario
38
+ # here. We currently don't have access to that, so a refactoring is in order to make that happen.
39
+ true
30
40
  end
31
41
 
32
42
  def failed?
@@ -28,6 +28,10 @@ module Cucumber
28
28
  @steps.max_line_length(self)
29
29
  end
30
30
 
31
+ def accept_hook?(hook)
32
+ @tags.accept_hook?(hook)
33
+ end
34
+
31
35
  # TODO: Remove when we use StepCollection everywhere
32
36
  def previous_step(step)
33
37
  i = @steps.index(step) || -1
@@ -15,6 +15,10 @@ module Cucumber
15
15
  nil
16
16
  end
17
17
 
18
+ def accept_hook?(hook)
19
+ @scenario_outline.accept_hook?(hook)
20
+ end
21
+
18
22
  def skip_invoke!
19
23
  example_rows.each do |cells|
20
24
  cells.skip_invoke!
@@ -62,6 +66,10 @@ module Cucumber
62
66
  end
63
67
  end
64
68
 
69
+ def accept_hook?(hook)
70
+ @table.accept_hook?(hook)
71
+ end
72
+
65
73
  private
66
74
 
67
75
  def header?
@@ -7,6 +7,10 @@ module Cucumber
7
7
  # This gets stored internally as <tt>["invoice", "release_2"]</tt>
8
8
  #
9
9
  class Tags
10
+ def self.strip_prefix(tag_name)
11
+ tag_name =~ /^@(.*)/ ? $1 : tag_name
12
+ end
13
+
10
14
  def initialize(line, tag_names)
11
15
  @line, @tag_names = line, tag_names
12
16
  end
@@ -16,7 +20,11 @@ module Cucumber
16
20
  visitor.visit_tag_name(tag_name)
17
21
  end
18
22
  end
19
-
23
+
24
+ def accept_hook?(hook)
25
+ hook.matches_tag_names?(@tag_names)
26
+ end
27
+
20
28
  def to_sexp
21
29
  @tag_names.map{|tag_name| [:tag, tag_name]}
22
30
  end
@@ -187,8 +187,8 @@ module Cucumber
187
187
  excludes = excludes.map{|tag| tag[1..-1]}
188
188
 
189
189
  # Strip @
190
- includes = includes.map{|tag| tag =~ /^@(.*)/ ? $1 : tag}
191
- excludes = excludes.map{|tag| tag =~ /^@(.*)/ ? $1 : tag}
190
+ includes = includes.map{|tag| Ast::Tags.strip_prefix(tag)}
191
+ excludes = excludes.map{|tag| Ast::Tags.strip_prefix(tag)}
192
192
  [includes, excludes]
193
193
  end
194
194
 
@@ -92,7 +92,11 @@ module Cucumber
92
92
 
93
93
  def enable_diffing
94
94
  if configuration.diff_enabled? && defined?(::Spec)
95
- require 'spec/runner/differs/default'
95
+ begin
96
+ require 'spec/runner/differs/default' # RSpec >=1.2.4
97
+ rescue ::LoadError
98
+ require 'spec/expectations/differs/default' # RSpec <=1.2.3
99
+ end
96
100
  options = OpenStruct.new(:diff_format => :unified, :context_lines => 3)
97
101
  ::Spec::Expectations.differ = ::Spec::Expectations::Differs::Default.new(options)
98
102
  end
@@ -216,7 +216,7 @@ module Cucumber
216
216
  end
217
217
 
218
218
  def has_tags?(tags)
219
- tag_names.detect{|tag_name| tags.index(tag_name)}
219
+ (tag_names & tags).any?
220
220
  end
221
221
 
222
222
  def build
@@ -224,7 +224,7 @@ module Cucumber
224
224
  end
225
225
 
226
226
  def tag_names
227
- ts.elements.map{|e| e.tag.tag_name.text_value}
227
+ @tag_names ||= ts.elements.map{|e| e.tag.tag_name.text_value}
228
228
  end
229
229
  end
230
230
 
@@ -46,7 +46,7 @@ module Cucumber
46
46
  end
47
47
 
48
48
  def has_tags?(tags)
49
- tag_names.detect{|tag_name| tags.index(tag_name)}
49
+ (tag_names & tags).any?
50
50
  end
51
51
 
52
52
  def build
@@ -54,7 +54,7 @@ module Cucumber
54
54
  end
55
55
 
56
56
  def tag_names
57
- ts.elements.map{|e| e.tag.tag_name.text_value}
57
+ @tag_names ||= ts.elements.map{|e| e.tag.tag_name.text_value}
58
58
  end
59
59
  }
60
60
  end
@@ -27,26 +27,45 @@ module Cucumber
27
27
  class Task
28
28
  LIB = File.expand_path(File.dirname(__FILE__) + '/../..') # :nodoc:
29
29
 
30
+ # TODO: remove depreated accessors for 0.4.0
31
+ def self.deprecate_accessor(attribute) # :nodoc:
32
+ attr_reader attribute
33
+ class_eval <<-EOF, __FILE__, __LINE__ + 1
34
+ def #{attribute}=(value)
35
+ @#{attribute} = value
36
+ warn("Cucumber::Rake::Task##{attribute} is deprecated and will be removed in 0.4.0. Please use profiles for complex settings: http://wiki.github.com/aslakhellesoy/cucumber/using-rake#profiles")
37
+ end
38
+ EOF
39
+ end
40
+
30
41
  # Directories to add to the Ruby $LOAD_PATH
31
42
  attr_accessor :libs
32
43
  # Name of the cucumber binary to use for running features. Defaults to Cucumber::BINARY
33
44
  attr_accessor :binary
34
45
  # Array of paths to specific step definition files to use
35
- attr_accessor :step_list
46
+ deprecate_accessor :step_list
36
47
  # File pattern for finding step definitions. Defaults to
37
48
  # 'features/**/*.rb'.
38
- attr_accessor :step_pattern
49
+ deprecate_accessor :step_pattern
39
50
  # Array of paths to specific features to run.
40
- attr_accessor :feature_list
51
+ deprecate_accessor :feature_list
41
52
  # File pattern for finding features to run. Defaults to
42
- # 'features/**/*.feature'. Can be overriden by the FEATURE environment variable.
43
- attr_accessor :feature_pattern
53
+ # 'features/**/*.feature'. Can be overridden by the FEATURE environment variable.
54
+ deprecate_accessor :feature_pattern
44
55
  # Extra options to pass to the cucumber binary. Can be overridden by the CUCUMBER_OPTS environment variable.
45
56
  attr_accessor :cucumber_opts
46
57
  # Run cucumber with RCov?
47
58
  attr_accessor :rcov
48
59
  # Extra options to pass to rcov
49
60
  attr_accessor :rcov_opts
61
+ # Define what profile to be used. When used with cucumber_opts it is simply appended to it. Will be ignored when CUCUMBER_OPTS is used.
62
+ def profile=(profile)
63
+ @profile = profile
64
+ unless feature_list
65
+ @feature_list = [] # Don't use accessor to avoid deprecation warning.
66
+ end
67
+ end
68
+ attr_reader :profile
50
69
 
51
70
  # Define a Rake
52
71
  def initialize(task_name = "features", desc = "Run Features with Cucumber")
@@ -75,7 +94,7 @@ module Cucumber
75
94
  def arguments_for_ruby_execution(task_args = nil) # :nodoc:
76
95
  lib_args = ['"%s"' % libs.join(File::PATH_SEPARATOR)]
77
96
  cucumber_bin = ['"%s"' % binary]
78
- cuc_opts = [(ENV['CUCUMBER_OPTS'] || cucumber_opts)]
97
+ cuc_opts = [(ENV['CUCUMBER_OPTS'] || cucumber_opts_with_profile)]
79
98
 
80
99
  step_files(task_args).each do |step_file|
81
100
  cuc_opts << '--require'
@@ -92,6 +111,10 @@ module Cucumber
92
111
  args
93
112
  end
94
113
 
114
+ def cucumber_opts_with_profile # :nodoc:
115
+ @profile ? "#{cucumber_opts} --profile #{@profile}" : cucumber_opts
116
+ end
117
+
95
118
  def feature_files(task_args = nil) # :nodoc:
96
119
  if ENV['FEATURE']
97
120
  FileList[ ENV['FEATURE'] ]
@@ -67,6 +67,21 @@ module Cucumber
67
67
  # so #register_step_definition (and more interestingly - its aliases) are
68
68
  # available from the top-level.
69
69
  module StepMother
70
+ class Hook
71
+ def initialize(tag_names, proc)
72
+ @tag_names = tag_names.map{|tag| Ast::Tags.strip_prefix(tag)}
73
+ @proc = proc
74
+ end
75
+
76
+ def matches_tag_names?(tag_names)
77
+ @tag_names.empty? || (@tag_names & tag_names).any?
78
+ end
79
+
80
+ def execute_in(world, scenario, location)
81
+ world.cucumber_instance_exec(false, location, scenario, &@proc)
82
+ end
83
+ end
84
+
70
85
  class << self
71
86
  def alias_adverb(adverb)
72
87
  adverb = adverb.gsub(/\s/, '')
@@ -114,12 +129,26 @@ module Cucumber
114
129
 
115
130
  # Registers a Before proc. You can call this method as many times as you
116
131
  # want (typically from ruby scripts under <tt>support</tt>).
117
- def Before(&proc)
118
- (@before_procs ||= []) << proc
132
+ def Before(*tag_names, &proc)
133
+ register_hook(:before, tag_names, proc)
134
+ end
135
+
136
+ def After(*tag_names, &proc)
137
+ register_hook(:after, tag_names, proc)
119
138
  end
120
139
 
121
- def After(&proc)
122
- (@after_procs ||= []).unshift(proc)
140
+ def register_hook(phase, tags, proc)
141
+ hook = Hook.new(tags, proc)
142
+ hooks[phase] << hook
143
+ hook
144
+ end
145
+
146
+ def hooks
147
+ @hooks ||= Hash.new {|hash, phase| hash[phase] = []}
148
+ end
149
+
150
+ def hooks_for(phase, scenario)
151
+ hooks[phase].select{|hook| scenario.accept_hook?(hook)}
123
152
  end
124
153
 
125
154
  # Registers any number of +world_modules+ (Ruby Modules) and/or a Proc.
@@ -197,16 +226,22 @@ module Cucumber
197
226
  end
198
227
 
199
228
  def before_and_after(scenario, skip=false)
200
- unless current_world || skip
229
+ before(scenario) unless skip
230
+ yield
231
+ after(scenario) unless skip
232
+ scenario_visited(scenario)
233
+ end
234
+
235
+ def before(scenario)
236
+ unless current_world
201
237
  new_world!
202
238
  execute_before(scenario)
203
239
  end
204
- if block_given?
205
- yield
206
- execute_after(scenario) unless skip
207
- nil_world!
208
- scenario_visited(scenario)
209
- end
240
+ end
241
+
242
+ def after(scenario)
243
+ execute_after(scenario)
244
+ nil_world!
210
245
  end
211
246
 
212
247
  private
@@ -268,14 +303,14 @@ module Cucumber
268
303
  end
269
304
 
270
305
  def execute_before(scenario)
271
- (@before_procs ||= []).each do |proc|
272
- @current_world.cucumber_instance_exec(false, 'Before', scenario, &proc)
306
+ hooks_for(:before, scenario).each do |hook|
307
+ hook.execute_in(@current_world, scenario, 'Before')
273
308
  end
274
309
  end
275
310
 
276
311
  def execute_after(scenario)
277
- (@after_procs ||= []).each do |proc|
278
- @current_world.cucumber_instance_exec(false, 'After', scenario, &proc)
312
+ hooks_for(:after, scenario).each do |hook|
313
+ hook.execute_in(@current_world, scenario, 'After')
279
314
  end
280
315
  end
281
316
 
@@ -1,9 +1,9 @@
1
1
  module Cucumber #:nodoc:
2
2
  class VERSION #:nodoc:
3
3
  MAJOR = 0
4
- MINOR = 2
5
- TINY = 3
6
- PATCH = 4 # Set to nil for official release
4
+ MINOR = 3
5
+ TINY = 0
6
+ PATCH = nil # Set to nil for official release
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY, PATCH].compact.join('.')
9
9
  end
@@ -1,6 +1,10 @@
1
1
  require File.dirname(__FILE__) + '/../../spec_helper'
2
2
  require 'yaml'
3
- require 'spec/runner/differs/default'
3
+ begin
4
+ require 'spec/runner/differs/default' # RSpec >=1.2.4
5
+ rescue ::LoadError
6
+ require 'spec/expectations/differs/default' # RSpec <=1.2.3
7
+ end
4
8
 
5
9
  module Cucumber
6
10
  module Cli
@@ -133,5 +133,16 @@ Use Ruby modules instead to extend your worlds. See the #World RDoc.
133
133
 
134
134
  })
135
135
  end
136
+
137
+ it "should find before hooks" do
138
+ fish = @step_mother.Before('@fish'){}
139
+ meat = @step_mother.Before('@meat'){}
140
+
141
+ scenario = mock('Scenario')
142
+ scenario.should_receive(:accept_hook?).with(fish).and_return(true)
143
+ scenario.should_receive(:accept_hook?).with(meat).and_return(false)
144
+
145
+ @step_mother.hooks_for(:before, scenario).should == [fish]
146
+ end
136
147
  end
137
148
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aslakhellesoy-cucumber
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3.4
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - "Aslak Helles\xC3\xB8y"
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-04-13 00:00:00 -07:00
12
+ date: 2009-04-14 00:00:00 -07:00
13
13
  default_executable: cucumber
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -269,6 +269,8 @@ files:
269
269
  - examples/tickets/features/177/2.feature
270
270
  - examples/tickets/features/177/3.feature
271
271
  - examples/tickets/features/180.feature
272
+ - examples/tickets/features/229/tagged_hooks.feature
273
+ - examples/tickets/features/229/tagged_hooks.rb
272
274
  - examples/tickets/features/236.feature
273
275
  - examples/tickets/features/241.feature
274
276
  - examples/tickets/features/246.feature
@@ -296,6 +298,7 @@ files:
296
298
  - features/cucumber_cli_diff_disabled.feature
297
299
  - features/cucumber_cli_outlines.feature
298
300
  - features/custom_formatter.feature
301
+ - features/rake_task.feature
299
302
  - features/report_called_undefined_steps.feature
300
303
  - features/snippet.feature
301
304
  - features/step_definitions/cucumber_steps.rb