kosmas58-cucumber 0.2.3.3 → 0.3.9.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (210) hide show
  1. data/History.txt +203 -3
  2. data/Manifest.txt +0 -346
  3. data/README.txt +0 -21
  4. data/Rakefile +3 -1
  5. data/bin/cucumber +12 -1
  6. data/config/hoe.rb +6 -5
  7. data/cucumber.yml +3 -1
  8. data/examples/cs/Rakefile +1 -1
  9. data/examples/cs/features/addition.feature +5 -5
  10. data/examples/cs/features/step_definitons/calculator_steps.rb +2 -2
  11. data/examples/dos_line_endings/Rakefile +1 -1
  12. data/examples/dos_line_endings/features/dos_line_endings.feature +9 -9
  13. data/examples/i18n/Rakefile +1 -1
  14. data/examples/i18n/ar/Rakefile +1 -1
  15. data/examples/i18n/bg/Rakefile +6 -0
  16. data/examples/i18n/bg/features/addition.feature +11 -0
  17. data/examples/i18n/bg/features/consecutive_calculations.feature +18 -0
  18. data/examples/i18n/bg/features/division.feature +16 -0
  19. data/examples/i18n/bg/features/step_definitons/calculator_steps.rb +24 -0
  20. data/examples/i18n/bg/features/support/env.rb +6 -0
  21. data/examples/i18n/bg/features/support/world.rb +8 -0
  22. data/examples/i18n/bg/lib/calculator.rb +24 -0
  23. data/examples/i18n/cat/Rakefile +6 -0
  24. data/examples/i18n/cat/features/step_definitons/calculator_steps.rb +21 -0
  25. data/examples/i18n/cat/features/suma.feature +16 -0
  26. data/examples/i18n/cat/lib/calculadora.rb +16 -0
  27. data/examples/i18n/da/Rakefile +1 -1
  28. data/examples/i18n/de/Rakefile +1 -1
  29. data/examples/i18n/en/Rakefile +1 -1
  30. data/examples/i18n/en-lol/Rakefile +1 -1
  31. data/examples/i18n/es/Rakefile +1 -1
  32. data/examples/i18n/et/Rakefile +1 -1
  33. data/examples/i18n/fi/Rakefile +1 -1
  34. data/examples/i18n/fr/Rakefile +1 -1
  35. data/examples/i18n/fr/features/addition.feature +4 -4
  36. data/examples/i18n/fr/features/step_definitions/calculatrice_steps.rb +1 -1
  37. data/examples/i18n/fr/lib/calculatrice.rb +1 -1
  38. data/examples/i18n/he/Rakefile +6 -0
  39. data/examples/i18n/he/features/addition.feature +16 -0
  40. data/examples/i18n/he/features/division.feature +9 -0
  41. data/examples/i18n/he/features/step_definitons/calculator_steps.rb +24 -0
  42. data/examples/i18n/he/lib/calculator.rb +14 -0
  43. data/examples/i18n/hu/Rakefile +6 -0
  44. data/examples/i18n/hu/features/addition.feature +16 -0
  45. data/examples/i18n/hu/features/division.feature +9 -0
  46. data/examples/i18n/hu/features/step_definitons/calculator_steps.rb +25 -0
  47. data/examples/i18n/hu/lib/calculator.rb +14 -0
  48. data/examples/i18n/id/Rakefile +1 -1
  49. data/examples/i18n/it/Rakefile +1 -1
  50. data/examples/i18n/ja/Rakefile +1 -1
  51. data/examples/i18n/ja/features/addition.feature +1 -1
  52. data/examples/i18n/ja/features/division.feature +1 -1
  53. data/examples/i18n/ja/features/step_definitons/calculator_steps.rb +1 -1
  54. data/examples/i18n/ko/Rakefile +1 -1
  55. data/examples/i18n/lt/Rakefile +1 -1
  56. data/examples/i18n/lt/features/addition.feature +2 -3
  57. data/examples/i18n/lv/Rakefile +6 -0
  58. data/examples/i18n/lv/features/addition.feature +16 -0
  59. data/examples/i18n/lv/features/division.feature +9 -0
  60. data/examples/i18n/lv/features/step_definitons/calculator_steps.rb +24 -0
  61. data/examples/i18n/lv/lib/calculator.rb +14 -0
  62. data/examples/i18n/no/Rakefile +1 -1
  63. data/examples/i18n/pl/Rakefile +6 -0
  64. data/examples/i18n/pl/features/addition.feature +16 -0
  65. data/examples/i18n/pl/features/division.feature +9 -0
  66. data/examples/i18n/pl/features/step_definitons/calculator_steps.rb +24 -0
  67. data/examples/i18n/pl/features/support/env.rb +6 -0
  68. data/examples/i18n/pl/lib/calculator.rb +14 -0
  69. data/examples/i18n/pt/Rakefile +1 -1
  70. data/examples/i18n/pt/features/step_definitions/calculadora_steps.rb +3 -7
  71. data/examples/i18n/pt/features/support/env.rb +6 -0
  72. data/examples/i18n/ro/Rakefile +1 -1
  73. data/examples/i18n/ru/Rakefile +1 -1
  74. data/examples/i18n/se/Rakefile +1 -1
  75. data/examples/i18n/sk/Rakefile +1 -1
  76. data/examples/i18n/zh-CN/Rakefile +1 -1
  77. data/examples/i18n/zh-TW/Rakefile +1 -1
  78. data/examples/java/README.textile +2 -6
  79. data/examples/java/build.xml +33 -0
  80. data/examples/java/features/step_definitons/hello_steps.rb +0 -2
  81. data/examples/junit/features/one_passing_one_failing.feature +8 -0
  82. data/examples/junit/features/pending.feature +5 -0
  83. data/examples/junit/features/step_definitions/steps.rb +11 -0
  84. data/examples/selenium/Rakefile +1 -1
  85. data/examples/selenium_webrat/Rakefile +1 -1
  86. data/examples/selenium_webrat/config.ru +0 -0
  87. data/examples/selenium_webrat/features/search.feature +1 -1
  88. data/examples/selenium_webrat/features/step_definitons/search_steps.rb +2 -2
  89. data/examples/selenium_webrat/features/support/env.rb +7 -3
  90. data/examples/self_test/features/background/background_tagged_before_on_outline.feature +12 -0
  91. data/examples/self_test/features/background/failing_background.feature +1 -0
  92. data/examples/self_test/features/background/passing_background.feature +2 -2
  93. data/examples/self_test/features/multiline_name.feature +27 -0
  94. data/examples/self_test/features/sample.feature +2 -0
  95. data/examples/self_test/features/search_sample.feature +32 -0
  96. data/examples/self_test/features/step_definitions/sample_steps.rb +11 -0
  97. data/examples/self_test/features/support/env.rb +17 -1
  98. data/examples/sinatra/Rakefile +1 -1
  99. data/examples/test_unit/Rakefile +1 -1
  100. data/examples/tickets/Rakefile +3 -3
  101. data/examples/tickets/features/229/tagged_hooks.feature +8 -0
  102. data/examples/tickets/features/229/tagged_hooks.rb +14 -0
  103. data/examples/tickets/features/236.feature +9 -9
  104. data/examples/tickets/features/272/hooks.feature +26 -0
  105. data/examples/tickets/features/272/hooks_steps.rb +53 -0
  106. data/examples/tickets/features/279/py_string_indent.feature +25 -0
  107. data/examples/tickets/features/279/py_string_indent.steps.rb +12 -0
  108. data/examples/tickets/features/279/wrong.feature_ +11 -0
  109. data/examples/tickets/features/301/filter_background_tagged_hooks.feature +6 -0
  110. data/examples/tickets/features/301/filter_background_tagged_hooks_steps.rb +12 -0
  111. data/examples/tickets/features/306/only_background.feature +4 -0
  112. data/examples/tickets/features/step_definitons/tickets_steps.rb +0 -7
  113. data/examples/watir/Rakefile +1 -1
  114. data/examples/watir/features/search.feature +4 -1
  115. data/examples/watir/features/step_definitons/search_steps.rb +2 -4
  116. data/features/after_block_exceptions.feature +99 -0
  117. data/features/after_step_block_exceptions.feature +101 -0
  118. data/features/background.feature +105 -38
  119. data/features/cucumber_cli.feature +201 -64
  120. data/features/cucumber_cli_diff_disabled.feature +6 -4
  121. data/features/cucumber_cli_outlines.feature +60 -35
  122. data/features/custom_formatter.feature +3 -3
  123. data/features/exclude_files.feature +20 -0
  124. data/features/expand.feature +48 -0
  125. data/features/html_formatter/a.html +1632 -0
  126. data/features/html_formatter.feature +7 -0
  127. data/features/junit_formatter.feature +62 -0
  128. data/features/multiline_names.feature +43 -0
  129. data/features/rake_task.feature +150 -0
  130. data/features/report_called_undefined_steps.feature +4 -3
  131. data/features/snippet.feature +2 -3
  132. data/features/step_definitions/cucumber_steps.rb +98 -15
  133. data/features/support/env.rb +78 -3
  134. data/features/usage.feature +32 -19
  135. data/features/work_in_progress.feature +148 -0
  136. data/gem_tasks/deployment.rake +1 -1
  137. data/gem_tasks/rspec.rake +9 -2
  138. data/lib/cucumber/ast/background.rb +19 -7
  139. data/lib/cucumber/ast/comment.rb +4 -0
  140. data/lib/cucumber/ast/feature.rb +7 -1
  141. data/lib/cucumber/ast/feature_element.rb +24 -9
  142. data/lib/cucumber/ast/features.rb +4 -0
  143. data/lib/cucumber/ast/outline_table.rb +74 -4
  144. data/lib/cucumber/ast/py_string.rb +5 -1
  145. data/lib/cucumber/ast/scenario.rb +31 -7
  146. data/lib/cucumber/ast/scenario_outline.rb +17 -9
  147. data/lib/cucumber/ast/step.rb +8 -5
  148. data/lib/cucumber/ast/step_collection.rb +14 -1
  149. data/lib/cucumber/ast/step_invocation.rb +29 -15
  150. data/lib/cucumber/ast/table.rb +9 -1
  151. data/lib/cucumber/ast/tags.rb +9 -1
  152. data/lib/cucumber/ast/visitor.rb +6 -2
  153. data/lib/cucumber/cli/configuration.rb +134 -105
  154. data/lib/cucumber/cli/main.rb +35 -12
  155. data/lib/cucumber/core_ext/proc.rb +9 -13
  156. data/lib/cucumber/formatter/ansicolor.rb +1 -1
  157. data/lib/cucumber/formatter/console.rb +36 -14
  158. data/lib/cucumber/formatter/cucumber.css +31 -12
  159. data/lib/cucumber/formatter/duration.rb +10 -0
  160. data/lib/cucumber/formatter/html.rb +76 -16
  161. data/lib/cucumber/formatter/junit.rb +79 -0
  162. data/lib/cucumber/formatter/pretty.rb +19 -14
  163. data/lib/cucumber/formatter/profile.rb +1 -1
  164. data/lib/cucumber/formatter/progress.rb +12 -12
  165. data/lib/cucumber/formatter/rerun.rb +1 -0
  166. data/lib/cucumber/formatter/tag_cloud.rb +28 -0
  167. data/lib/cucumber/formatter/usage.rb +5 -5
  168. data/lib/cucumber/formatters/unicode.rb +5 -0
  169. data/lib/cucumber/languages.yml +111 -34
  170. data/lib/cucumber/parser/feature.rb +237 -36
  171. data/lib/cucumber/parser/feature.tt +68 -30
  172. data/lib/cucumber/parser/treetop_ext.rb +12 -3
  173. data/lib/cucumber/rails/rspec.rb +5 -3
  174. data/lib/cucumber/rails/world.rb +29 -4
  175. data/lib/cucumber/rake/task.rb +125 -37
  176. data/lib/cucumber/rspec_neuter.rb +23 -0
  177. data/lib/cucumber/step_definition.rb +5 -2
  178. data/lib/cucumber/step_match.rb +10 -6
  179. data/lib/cucumber/step_mother.rb +98 -26
  180. data/lib/cucumber/version.rb +3 -3
  181. data/lib/cucumber/world.rb +2 -2
  182. data/lib/cucumber.rb +7 -2
  183. data/rails_generators/cucumber/USAGE +0 -3
  184. data/rails_generators/cucumber/cucumber_generator.rb +51 -44
  185. data/rails_generators/cucumber/templates/cucumber.rake +5 -5
  186. data/rails_generators/cucumber/templates/cucumber_environment.rb +23 -0
  187. data/rails_generators/cucumber/templates/de/paths.rb +27 -0
  188. data/rails_generators/cucumber/templates/de/webrat_steps.rb +139 -0
  189. data/rails_generators/cucumber/templates/en/paths.rb +27 -0
  190. data/rails_generators/cucumber/templates/{webrat_steps.rb → en/webrat_steps.rb} +26 -2
  191. data/rails_generators/cucumber/templates/env.rb +1 -1
  192. data/rails_generators/feature/USAGE +0 -3
  193. data/rails_generators/feature/feature_generator.rb +6 -30
  194. data/spec/cucumber/ast/feature_element_spec.rb +40 -0
  195. data/spec/cucumber/ast/py_string_spec.rb +4 -0
  196. data/spec/cucumber/ast/table_spec.rb +21 -5
  197. data/spec/cucumber/ast/visitor_spec.rb +27 -0
  198. data/spec/cucumber/cli/configuration_spec.rb +75 -54
  199. data/spec/cucumber/cli/main_spec.rb +60 -154
  200. data/spec/cucumber/formatter/color_io_spec.rb +1 -0
  201. data/spec/cucumber/formatter/duration_spec.rb +22 -0
  202. data/spec/cucumber/formatter/progress_spec.rb +36 -0
  203. data/spec/cucumber/parser/feature_parser_spec.rb +102 -1
  204. data/spec/cucumber/step_mother_spec.rb +23 -5
  205. metadata +79 -22
  206. data/examples/java/Rakefile +0 -12
  207. data/examples/self_test/features/support/tag_count_formatter.rb +0 -25
  208. data/lib/cucumber/formatter.rb +0 -1
  209. data/rails_generators/cucumber/templates/paths.rb +0 -29
  210. data/spec/cucumber/formatters/profile_formatter_spec.rb +0 -198
@@ -7,7 +7,14 @@ else
7
7
  require 'action_controller/test_process'
8
8
  require 'action_controller/integration'
9
9
  end
10
- require 'test/unit/testresult'
10
+
11
+ begin
12
+ require 'test/unit/testresult'
13
+ rescue LoadError => e
14
+ e.message << "\nYou must gem install test-unit. For more info see https://rspec.lighthouseapp.com/projects/16211/tickets/292"
15
+ e.message << "\nAlso make sure you have rack 1.0.0 or higher."
16
+ raise e
17
+ end
11
18
 
12
19
  # So that Test::Unit doesn't launch at the end - makes it think it has already been run.
13
20
  Test::Unit.run = true if Test::Unit.respond_to?(:run=)
@@ -30,6 +37,11 @@ module Cucumber #:nodoc:
30
37
  end
31
38
 
32
39
  def self.use_transactional_fixtures
40
+
41
+ unless ::Rails.configuration.cache_classes
42
+ warn "WARNING: You have set Rails' config.cache_classes to false (most likely in config/environments/test.rb). This setting is known to break Cucumber's use_transactional_fixtures method. Set config.cache_classes to true if you want to use transactional fixtures. For more information see https://rspec.lighthouseapp.com/projects/16211/tickets/165."
43
+ end
44
+
33
45
  World.use_transactional_fixtures = true
34
46
  if defined?(ActiveRecord::Base)
35
47
  $__cucumber_toplevel.Before do
@@ -56,13 +68,26 @@ module Cucumber #:nodoc:
56
68
 
57
69
  def self.bypass_rescue
58
70
  ActionController::Base.class_eval do
71
+ alias_method :rescue_action_without_bypass, :rescue_action
72
+
59
73
  def rescue_action(exception)
60
74
  raise exception
61
75
  end
62
76
  end
63
- ActionController::Dispatcher.class_eval do
64
- def self.failsafe_response(output, status, exception = nil)
65
- raise exception
77
+
78
+ begin
79
+ ActionController::Failsafe.class_eval do
80
+ alias_method :failsafe_response_without_bypass, :failsafe_response
81
+
82
+ def failsafe_response(exception)
83
+ raise exception
84
+ end
85
+ end
86
+ rescue NameError # Failsafe was introduced in Rails 2.3.2
87
+ ActionController::Dispatcher.class_eval do
88
+ def self.failsafe_response(output, status, exception = nil)
89
+ raise exception
90
+ end
66
91
  end
67
92
  end
68
93
  end
@@ -14,7 +14,7 @@ module Cucumber
14
14
  # To further configure the task, you can pass a block:
15
15
  #
16
16
  # Cucumber::Rake::Task.new do |t|
17
- # t.cucumber_opts = "--format progress"
17
+ # t.cucumber_opts = %w{--format progress}
18
18
  # end
19
19
  #
20
20
  # This task can also be configured to be run with RCov:
@@ -25,46 +25,139 @@ module Cucumber
25
25
  #
26
26
  # See the attributes for additional configuration possibilities.
27
27
  class Task
28
- LIB = File.expand_path(File.dirname(__FILE__) + '/../..') # :nodoc:
28
+ class InProcessCucumberRunner #:nodoc:
29
+ attr_reader :args
30
+
31
+ def initialize(libs, cucumber_opts, feature_files)
32
+ raise "libs must be an Array when running in-process" unless Array === libs
33
+ libs.reverse.each{|lib| $LOAD_PATH.unshift(lib)}
34
+ @args = (
35
+ cucumber_opts +
36
+ feature_files
37
+ ).flatten.compact
38
+ end
39
+
40
+ def run
41
+ require 'cucumber/cli/main'
42
+ failure = Cucumber::Cli::Main.execute(args)
43
+ raise "Cucumber failed" if failure
44
+ end
45
+ end
46
+
47
+ class ForkedCucumberRunner #:nodoc:
48
+ attr_reader :args
49
+
50
+ def initialize(libs, cucumber_bin, cucumber_opts, feature_files)
51
+ @args = (
52
+ ['-I'] + load_path(libs) +
53
+ quoted_binary(cucumber_bin) +
54
+ cucumber_opts +
55
+ feature_files
56
+ ).flatten
57
+ end
58
+
59
+ def load_path(libs)
60
+ ['"%s"' % libs.join(File::PATH_SEPARATOR)]
61
+ end
62
+
63
+ def quoted_binary(cucumber_bin)
64
+ ['"%s"' % cucumber_bin]
65
+ end
66
+
67
+ def run
68
+ ruby(args.join(" ")) # ruby(*args) is broken on Windows
69
+ end
70
+ end
71
+
72
+ class RCovCucumberRunner < ForkedCucumberRunner #:nodoc:
73
+ def initialize(libs, cucumber_bin, cucumber_opts, feature_files, rcov_opts)
74
+ @args = (
75
+ ['-I'] + load_path(libs) +
76
+ ['-S', 'rcov'] + rcov_opts +
77
+ quoted_binary(cucumber_bin) +
78
+ ['--'] +
79
+ cucumber_opts +
80
+ feature_files
81
+ ).flatten
82
+ end
83
+ end
84
+
85
+ LIB = File.expand_path(File.dirname(__FILE__) + '/../..') # :nodoc:
86
+
87
+ # TODO: remove depreated accessors for 0.4.0
88
+ def self.deprecate_accessor(attribute) # :nodoc:
89
+ attr_reader attribute
90
+ class_eval <<-EOF, __FILE__, __LINE__ + 1
91
+ def #{attribute}=(value)
92
+ @#{attribute} = value
93
+ 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")
94
+ end
95
+ EOF
96
+ end
29
97
 
30
98
  # Directories to add to the Ruby $LOAD_PATH
31
99
  attr_accessor :libs
100
+
32
101
  # Name of the cucumber binary to use for running features. Defaults to Cucumber::BINARY
33
102
  attr_accessor :binary
103
+
34
104
  # Array of paths to specific step definition files to use
35
- attr_accessor :step_list
105
+ deprecate_accessor :step_list
106
+
36
107
  # File pattern for finding step definitions. Defaults to
37
108
  # 'features/**/*.rb'.
38
- attr_accessor :step_pattern
109
+ deprecate_accessor :step_pattern
110
+
39
111
  # Array of paths to specific features to run.
40
- attr_accessor :feature_list
112
+ deprecate_accessor :feature_list
113
+
41
114
  # 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
115
+ # 'features/**/*.feature'. Can be overridden by the FEATURE environment variable.
116
+ deprecate_accessor :feature_pattern
117
+
44
118
  # Extra options to pass to the cucumber binary. Can be overridden by the CUCUMBER_OPTS environment variable.
119
+ # It's recommended to pass an Array, but if it's a String it will be #split by ' '.
45
120
  attr_accessor :cucumber_opts
46
- # Run cucumber with RCov?
121
+ def cucumber_opts=(opts) #:nodoc:
122
+ @cucumber_opts = String === opts ? opts.split(' ') : opts
123
+ end
124
+
125
+ # Run cucumber with RCov? Defaults to false. If you set this to
126
+ # true, +fork+ is implicit.
47
127
  attr_accessor :rcov
48
- # Extra options to pass to rcov
128
+
129
+ # Extra options to pass to rcov.
130
+ # It's recommended to pass an Array, but if it's a String it will be #split by ' '.
49
131
  attr_accessor :rcov_opts
50
- # Extra options for multi language support
51
- attr_accessor :language
132
+ def rcov_opts=(opts) #:nodoc:
133
+ @rcov_opts = String === opts ? opts.split(' ') : opts
134
+ end
52
135
 
53
- # Define a Rake
136
+ # Whether or not to fork a new ruby interpreter. Defaults to true.
137
+ attr_accessor :fork
138
+
139
+ # 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.
140
+ attr_accessor :profile
141
+ def profile=(profile) #:nodoc:
142
+ @profile = profile
143
+ unless feature_list
144
+ # TODO: remove once we completely remove these from the rake task.
145
+ @step_list = []
146
+ @feature_list = [] # Don't use accessor to avoid deprecation warning.
147
+ end
148
+ end
149
+
150
+ # Define Cucumber Rake task
54
151
  def initialize(task_name = "features", desc = "Run Features with Cucumber")
55
152
  @task_name, @desc = task_name, desc
153
+ @fork = true
56
154
  @libs = ['lib']
57
155
  @rcov_opts = %w{--rails --exclude osx\/objc,gems\/}
58
156
 
59
157
  yield self if block_given?
60
158
 
61
- if language
62
- @feature_pattern = "features/#{language}/*.feature"
63
- @step_pattern = "features/#{language}/step_definitions/*.rb"
64
- else
65
- @feature_pattern = "features/**/*.feature" if feature_pattern.nil? && feature_list.nil?
66
- @step_pattern = "features/**/*.rb" if step_pattern.nil? && step_list.nil?
67
- end
159
+ @feature_pattern = "features/**/*.feature" if feature_pattern.nil? && feature_list.nil?
160
+ @step_pattern = "features/**/*.rb" if step_pattern.nil? && step_list.nil?
68
161
 
69
162
  @binary = binary.nil? ? Cucumber::BINARY : File.expand_path(binary)
70
163
  @libs.insert(0, LIB) if binary == Cucumber::BINARY
@@ -75,28 +168,23 @@ module Cucumber
75
168
  def define_task # :nodoc:
76
169
  desc @desc
77
170
  task @task_name do
78
- ruby(arguments_for_ruby_execution.join(" ")) # ruby(*args) is broken on Windows
171
+ runner.run
79
172
  end
80
173
  end
81
174
 
82
- def arguments_for_ruby_execution(task_args = nil) # :nodoc:
83
- lib_args = ['"%s"' % libs.join(File::PATH_SEPARATOR)]
84
- cucumber_bin = ['"%s"' % binary]
85
- cuc_opts = [(ENV['CUCUMBER_OPTS'] || cucumber_opts)]
86
-
87
- step_files(task_args).each do |step_file|
88
- cuc_opts << '--require'
89
- cuc_opts << step_file
90
- end
91
-
92
- if rcov
93
- args = (['-I'] + lib_args + ['-S', 'rcov'] + rcov_opts +
94
- cucumber_bin + ['--'] + cuc_opts + feature_files(task_args)).flatten
175
+ def runner(task_args = nil) # :nodoc:
176
+ cucumber_opts = [(ENV['CUCUMBER_OPTS'] ? ENV['CUCUMBER_OPTS'].split(/\s+/) : nil) || cucumber_opts_with_profile]
177
+ if(@rcov)
178
+ RCovCucumberRunner.new(libs, binary, cucumber_opts, feature_files(task_args), rcov_opts)
179
+ elsif(@fork)
180
+ ForkedCucumberRunner.new(libs, binary, cucumber_opts, feature_files(task_args))
95
181
  else
96
- args = (['-I'] + lib_args + cucumber_bin + cuc_opts + feature_files(task_args)).flatten
182
+ InProcessCucumberRunner.new(libs, cucumber_opts, feature_files(task_args))
97
183
  end
184
+ end
98
185
 
99
- args
186
+ def cucumber_opts_with_profile # :nodoc:
187
+ @profile ? [cucumber_opts, '--profile', @profile] : cucumber_opts
100
188
  end
101
189
 
102
190
  def feature_files(task_args = nil) # :nodoc:
@@ -131,7 +219,7 @@ module Cucumber
131
219
  def define_task # :nodoc:
132
220
  desc @desc
133
221
  task @task_name, :feature_name do |t, args|
134
- ruby(arguments_for_ruby_execution(args).join(" ")) # ruby(*args) is broken on Windows
222
+ runner(args).run
135
223
  end
136
224
  end
137
225
 
@@ -142,4 +230,4 @@ module Cucumber
142
230
  end
143
231
 
144
232
  end
145
- end
233
+ end
@@ -0,0 +1,23 @@
1
+ require 'optparse'
2
+
3
+ module Spec
4
+ module Runner
5
+ # Neuters RSpec's option parser.
6
+ # (RSpec's option parser tries to parse ARGV, which
7
+ # will fail when running cucumber)
8
+ class OptionParser < ::OptionParser
9
+ NEUTERED_RSPEC = Object.new
10
+ def NEUTERED_RSPEC.method_missing(m, *args); self; end
11
+
12
+ def self.method_added(m)
13
+ unless @__neutering_rspec
14
+ @__neutering_rspec = true
15
+ define_method(m) do |*a|
16
+ NEUTERED_RSPEC
17
+ end
18
+ @__neutering_rspec = false
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -70,9 +70,12 @@ module Cucumber
70
70
  end
71
71
  block_args << multiline_arg_class.default_arg_name unless multiline_arg_class.nil?
72
72
  block_arg_string = block_args.empty? ? "" : " |#{block_args.join(", ")}|"
73
- multiline_class_string = multiline_arg_class ? "# #{multiline_arg_class.default_arg_name} is a #{multiline_arg_class.to_s}\n " : ""
73
+ multiline_class_comment = ""
74
+ if(multiline_arg_class == Ast::Table)
75
+ multiline_class_comment = "# #{multiline_arg_class.default_arg_name} is a #{multiline_arg_class.to_s}\n "
76
+ end
74
77
 
75
- "#{step_keyword} /^#{escaped}$/ do#{block_arg_string}\n #{multiline_class_string}pending\nend"
78
+ "#{step_keyword} /^#{escaped}$/ do#{block_arg_string}\n #{multiline_class_comment}pending\nend"
76
79
  end
77
80
 
78
81
  class MissingProc < StandardError
@@ -1,12 +1,15 @@
1
1
  module Cucumber
2
2
  class StepMatch
3
- attr_reader :step_definition
4
- attr_reader :args
5
-
3
+ attr_reader :step_definition, :args
4
+
6
5
  def initialize(step_definition, step_name, formatted_step_name, args)
7
6
  @step_definition, @step_name, @formatted_step_name, @args = step_definition, step_name, formatted_step_name, args
8
7
  end
9
-
8
+
9
+ def name
10
+ @formatted_step_name
11
+ end
12
+
10
13
  def invoke(world, multiline_arg)
11
14
  all_args = @args.dup
12
15
  all_args << multiline_arg if multiline_arg
@@ -33,12 +36,13 @@ module Cucumber
33
36
  class NoStepMatch
34
37
  attr_reader :step_definition
35
38
 
36
- def initialize(step)
39
+ def initialize(step, name)
37
40
  @step = step
41
+ @name = name
38
42
  end
39
43
 
40
44
  def format_args(format)
41
- @step.name
45
+ @name
42
46
  end
43
47
 
44
48
  def file_colon_line
@@ -57,7 +57,8 @@ module Cucumber
57
57
  message << "in 2 places:\n\n"
58
58
  message << first_proc.backtrace_line('World') << "\n"
59
59
  message << second_proc.backtrace_line('World') << "\n\n"
60
- message << "Use Ruby modules instead to extend your worlds. See the #World RDoc.\n\n"
60
+ message << "Use Ruby modules instead to extend your worlds. See the Cucumber::StepMother#World RDoc\n"
61
+ message << "or http://wiki.github.com/aslakhellesoy/cucumber/a-whole-new-world.\n\n"
61
62
  super(message)
62
63
  end
63
64
  end
@@ -67,6 +68,29 @@ module Cucumber
67
68
  # so #register_step_definition (and more interestingly - its aliases) are
68
69
  # available from the top-level.
69
70
  module StepMother
71
+ class Hook
72
+ def initialize(tag_names, proc)
73
+ @tag_names = tag_names.map{|tag| Ast::Tags.strip_prefix(tag)}
74
+ @proc = proc
75
+ end
76
+
77
+ def matches_tag_names?(tag_names)
78
+ @tag_names.empty? || (@tag_names & tag_names).any?
79
+ end
80
+
81
+ def execute_in(world, scenario, location, exception_fails_scenario = true)
82
+ begin
83
+ world.cucumber_instance_exec(false, location, scenario, &@proc)
84
+ rescue Exception => exception
85
+ if exception_fails_scenario
86
+ scenario.fail!(exception)
87
+ else
88
+ raise
89
+ end
90
+ end
91
+ end
92
+ end
93
+
70
94
  class << self
71
95
  def alias_adverb(adverb)
72
96
  adverb = adverb.gsub(/\s/, '')
@@ -76,6 +100,10 @@ module Cucumber
76
100
 
77
101
  attr_writer :snippet_generator, :options, :visitor
78
102
 
103
+ def options
104
+ @options ||= {}
105
+ end
106
+
79
107
  def step_visited(step)
80
108
  steps << step unless steps.index(step)
81
109
  end
@@ -89,8 +117,13 @@ module Cucumber
89
117
  end
90
118
  end
91
119
 
92
- def scenarios
120
+ def scenarios(status = nil)
93
121
  @scenarios ||= []
122
+ if(status)
123
+ @scenarios.select{|scenario| scenario.status == status}
124
+ else
125
+ @scenarios
126
+ end
94
127
  end
95
128
 
96
129
  # Registers a new StepDefinition. This method is aliased
@@ -114,12 +147,30 @@ module Cucumber
114
147
 
115
148
  # Registers a Before proc. You can call this method as many times as you
116
149
  # want (typically from ruby scripts under <tt>support</tt>).
117
- def Before(&proc)
118
- (@before_procs ||= []) << proc
150
+ def Before(*tag_names, &proc)
151
+ register_hook(:before, tag_names, proc)
152
+ end
153
+
154
+ def After(*tag_names, &proc)
155
+ register_hook(:after, tag_names, proc)
119
156
  end
120
157
 
121
- def After(&proc)
122
- (@after_procs ||= []).unshift(proc)
158
+ def AfterStep(*tag_names, &proc)
159
+ register_hook(:after_step, tag_names, proc)
160
+ end
161
+
162
+ def register_hook(phase, tags, proc)
163
+ hook = Hook.new(tags, proc)
164
+ hooks[phase] << hook
165
+ hook
166
+ end
167
+
168
+ def hooks
169
+ @hooks ||= Hash.new {|hash, phase| hash[phase] = []}
170
+ end
171
+
172
+ def hooks_for(phase, scenario)
173
+ hooks[phase].select{|hook| scenario.accept_hook?(hook)}
123
174
  end
124
175
 
125
176
  # Registers any number of +world_modules+ (Ruby Modules) and/or a Proc.
@@ -188,6 +239,13 @@ module Cucumber
188
239
  end
189
240
  end
190
241
 
242
+ def clear!
243
+ step_definitions.clear
244
+ hooks.clear
245
+ steps.clear
246
+ scenarios.clear
247
+ end
248
+
191
249
  def step_definitions
192
250
  @step_definitions ||= []
193
251
  end
@@ -197,30 +255,39 @@ module Cucumber
197
255
  end
198
256
 
199
257
  def before_and_after(scenario, skip=false)
200
- unless current_world || skip
258
+ before(scenario) unless skip
259
+ @current_scenario = scenario
260
+ yield scenario
261
+ @current_scenario = nil
262
+ after(scenario) unless skip
263
+ scenario_visited(scenario)
264
+ end
265
+
266
+ def before(scenario)
267
+ unless current_world
201
268
  new_world!
202
269
  execute_before(scenario)
203
270
  end
204
- if block_given?
205
- yield
206
- execute_after(scenario) unless skip
207
- nil_world!
208
- scenario_visited(scenario)
209
- end
210
271
  end
211
-
272
+
273
+ def after(scenario)
274
+ execute_after(scenario)
275
+ nil_world!
276
+ end
277
+
278
+ def after_step
279
+ execute_after_step(@current_scenario)
280
+ end
281
+
212
282
  private
213
283
 
214
284
  def max_step_definition_length
215
285
  @max_step_definition_length ||= step_definitions.map{|step_definition| step_definition.text_length}.max
216
286
  end
217
287
 
218
- def options
219
- @options || {}
220
- end
221
-
222
288
  # Creates a new world instance
223
289
  def new_world!
290
+ return if options[:dry_run]
224
291
  create_world!
225
292
  extend_world
226
293
  connect_world
@@ -268,23 +335,28 @@ module Cucumber
268
335
  end
269
336
 
270
337
  def execute_before(scenario)
271
- (@before_procs ||= []).each do |proc|
272
- @current_world.cucumber_instance_exec(false, 'Before', scenario, &proc)
338
+ return if options[:dry_run]
339
+ hooks_for(:before, scenario).each do |hook|
340
+ hook.execute_in(@current_world, scenario, 'Before')
273
341
  end
274
342
  end
275
343
 
276
344
  def execute_after(scenario)
277
- (@after_procs ||= []).each do |proc|
278
- @current_world.cucumber_instance_exec(false, 'After', scenario, &proc)
345
+ return if options[:dry_run]
346
+ hooks_for(:after, scenario).each do |hook|
347
+ hook.execute_in(@current_world, scenario, 'After')
279
348
  end
280
349
  end
281
350
 
282
- def scenario_visited(scenario)
283
- scenarios << scenario unless scenarios.index(scenario)
351
+ def execute_after_step(scenario)
352
+ return if options[:dry_run]
353
+ hooks_for(:after_step, scenario).each do |hook|
354
+ hook.execute_in(@current_world, scenario, 'AfterStep', false)
355
+ end
284
356
  end
285
357
 
286
- def options
287
- @options || {}
358
+ def scenario_visited(scenario)
359
+ scenarios << scenario unless scenarios.index(scenario)
288
360
  end
289
361
  end
290
362
  end
@@ -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 = 3 # Set to nil for official release
4
+ MINOR = 3
5
+ TINY = 9
6
+ PATCH = 4 # Set to nil for official release
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY, PATCH].compact.join('.')
9
9
  end
@@ -16,7 +16,7 @@ module Cucumber
16
16
  step_match.invoke(self, multiline_argument)
17
17
  rescue Exception => e
18
18
  e.nested! if Undefined === e
19
- @__cucumber_current_step.exception = e
19
+ @__cucumber_current_step.exception = e if @__cucumber_current_step
20
20
  raise e
21
21
  end
22
22
  end
@@ -50,4 +50,4 @@ module Cucumber
50
50
  end
51
51
  end
52
52
  end
53
- end
53
+ end
data/lib/cucumber.rb CHANGED
@@ -14,6 +14,7 @@ module Cucumber
14
14
  KEYWORD_KEYS = %w{name native encoding feature background scenario scenario_outline examples given when then but}
15
15
 
16
16
  class << self
17
+ # The currently active language
17
18
  attr_reader :lang
18
19
 
19
20
  def load_language(lang) #:nodoc:
@@ -38,10 +39,14 @@ module Cucumber
38
39
  def keyword_hash(lang=@lang)
39
40
  LANGUAGES[lang]
40
41
  end
42
+
43
+ def scenario_keyword
44
+ keyword_hash['scenario'].split('|')[0] + ':'
45
+ end
41
46
 
42
47
  def alias_step_definitions(lang) #:nodoc:
43
- keywords = %w{given when then and but}.map{|keyword| keyword_hash(lang)[keyword]}
44
- alias_steps(keywords)
48
+ keywords = %w{given when then and but}.map{|keyword| keyword_hash(lang)[keyword].split('|')}
49
+ alias_steps(keywords.flatten)
45
50
  end
46
51
 
47
52
  # Sets up additional method aliases for Given, When and Then.
@@ -7,8 +7,5 @@ Description:
7
7
  Also see the feature generator, which you can use to generate skeletons
8
8
  for new features.
9
9
 
10
- If you set the language option, then a subdirectory features/[language] will be generated instead.
11
- Now your are able to use features in different languages.
12
-
13
10
  Examples:
14
11
  `./script/generate cucumber`