aslakhellesoy-cucumber 0.2.3.4 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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