cucumber 0.9.2 → 0.9.3

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/Gemfile CHANGED
@@ -1,10 +1,2 @@
1
1
  source "http://rubygems.org"
2
2
  gemspec
3
-
4
- # Use source from sibling folders (if available) instead of gems
5
- %w[gherkin].each do |g|
6
- if File.directory?(File.dirname(__FILE__) + "/../#{g}")
7
- @dependencies.reject!{|dep| dep.name == g}
8
- gem g, :path => "../#{g}"
9
- end
10
- end
@@ -1,3 +1,11 @@
1
+ == 0.9.3 (2010-10-24)
2
+
3
+ === Bugfixes
4
+ * Better JSON representation of Regexps (Aslak Hellesøy)
5
+ * Update to work with latest spork (Matt Wynne)
6
+ * Prevent MiniTest::Unit#autorun from running in at_exit hook. (Aslak Hellesøy)
7
+ * Fixed incorect --help for --strict. It fails on both pending and undefined. (Aslak Hellesøy)
8
+
1
9
  == 0.9.2 (2010-10-04)
2
10
 
3
11
  === Bugfixes
@@ -24,7 +24,7 @@ for important information about this release. Happy cuking!
24
24
 
25
25
  }
26
26
 
27
- s.add_dependency 'gherkin', '~> 2.2.5'
27
+ s.add_dependency 'gherkin', '~> 2.2.9'
28
28
  s.add_dependency 'term-ansicolor', '~> 1.0.5'
29
29
  s.add_dependency 'builder', '~> 2.1.2'
30
30
  s.add_dependency 'diff-lcs', '~> 1.1.2'
@@ -9,8 +9,8 @@ Feature: List step defs as json
9
9
  Scenario: Two Ruby step definitions, in the same file
10
10
  Given a file named "features/step_definitions/foo_steps.rb" with:
11
11
  """
12
- Given(/foo/) {}
13
- Given(/b.r/) {}
12
+ Given(/foo/i) {}
13
+ Given(/b.r/xm) {}
14
14
  """
15
15
  When I run the following Ruby code:
16
16
  """
@@ -21,15 +21,17 @@ Feature: List step defs as json
21
21
  Then it should pass
22
22
  And the output should contain the following JSON:
23
23
  """
24
- [ "/foo/", "/b.r/" ]
25
-
24
+ [
25
+ {"source": "foo", "flags": "i"},
26
+ {"source": "b.r", "flags": "mx"}
27
+ ]
26
28
  """
27
29
 
28
30
  Scenario: Non-default directory structure
29
31
  Given a file named "my_weird/place/foo_steps.rb" with:
30
32
  """
31
33
  Given(/foo/) {}
32
- Given(/b.r/) {}
34
+ Given(/b.r/x) {}
33
35
  """
34
36
  When I run the following Ruby code:
35
37
  """
@@ -40,6 +42,9 @@ Feature: List step defs as json
40
42
  Then it should pass
41
43
  And the output should contain the following JSON:
42
44
  """
43
- [ "/foo/", "/b.r/" ]
45
+ [
46
+ {"source": "foo", "flags": ""},
47
+ {"source": "b.r", "flags": "x"}
48
+ ]
44
49
 
45
50
  """
@@ -0,0 +1,34 @@
1
+ Feature: Run Cli::Main with existing Runtime
2
+
3
+ This is the API that Spork uses. It creates an existing runtime then
4
+ calls load_programming_language('rb') on it to load the RbDsl.
5
+ When the process forks, Spork them passes the runtime to Cli::Main to
6
+ run it.
7
+
8
+ Background:
9
+ Given a standard Cucumber project directory structure
10
+
11
+ Scenario: Run a single feature
12
+ Given a file named "features/step_definitions/success.rb" with:
13
+ """
14
+ Given(/pass/) {}
15
+ """
16
+ Given a file named "features/success.feature" with:
17
+ """
18
+ Feature:
19
+ Scenario:
20
+ Given I pass
21
+ """
22
+ When I run the following Ruby code:
23
+ """
24
+ require 'cucumber'
25
+ runtime = Cucumber::Runtime.new
26
+ runtime.load_programming_language('rb')
27
+ Cucumber::Cli::Main.new([]).execute!(runtime)
28
+
29
+ """
30
+ Then it should pass
31
+ And the output should contain:
32
+ """
33
+ Given I pass
34
+ """
@@ -61,7 +61,6 @@ When /^I run the following Ruby code:$/ do |code|
61
61
  run %{#{Cucumber::RUBY_BINARY} -r rubygems -I #{cucumber_lib_dir} -e "#{code}"}
62
62
  end
63
63
 
64
-
65
64
  Then /^it should (fail|pass)$/ do |success|
66
65
  if success == 'fail'
67
66
  last_exit_status.should_not == 0
@@ -77,7 +76,7 @@ Then /^it should (fail|pass) with$/ do |success, output|
77
76
  Then("it should #{success}")
78
77
  end
79
78
 
80
- Then /^the output should contain$/ do |text|
79
+ Then /^the output should contain:?$/ do |text|
81
80
  last_stdout.should include(text)
82
81
  end
83
82
 
@@ -8,6 +8,7 @@ require 'cucumber/step_mother'
8
8
  require 'cucumber/cli/main'
9
9
  require 'cucumber/broadcaster'
10
10
  require 'cucumber/step_definitions'
11
+ require 'cucumber/core_ext/disable_mini_unit_autorun'
11
12
 
12
13
  module Cucumber
13
14
  class << self
@@ -13,14 +13,6 @@ require 'cucumber/formatter/color_io'
13
13
  require 'cucumber/cli/configuration'
14
14
  require 'cucumber/cli/drb_client'
15
15
 
16
- if defined?(Spork::TestFramework::Cucumber)
17
- class Spork::TestFramework::Cucumber < Spork::TestFramework
18
- def run_tests(argv, stderr, stdout)
19
- ::Cucumber::Cli::Main.new(argv, stdout, stderr).execute!
20
- end
21
- end
22
- end
23
-
24
16
  module Cucumber
25
17
  module Cli
26
18
  class Main
@@ -42,15 +34,17 @@ module Cucumber
42
34
  @configuration = nil
43
35
  end
44
36
 
45
- def execute!(legacy_step_mother = nil)
46
- if legacy_step_mother
47
- warn("Passing a step_mother to #execute! is deprecated, and has been ignored: #{caller[0]}")
48
- end
49
-
37
+ def execute!(existing_runtime = nil)
50
38
  trap_interrupt
51
39
  return @drb_output if run_drb_client
52
40
 
53
- runtime = Runtime.new(configuration)
41
+ runtime = if existing_runtime
42
+ existing_runtime.configure(configuration)
43
+ existing_runtime
44
+ else
45
+ Runtime.new(configuration)
46
+ end
47
+
54
48
  runtime.run!
55
49
  runtime.results.failure?
56
50
  rescue ProfilesNotDefinedError, YmlLoadError, ProfileNotFound => e
@@ -229,7 +229,7 @@ module Cucumber
229
229
  opts.on("-b", "--backtrace", "Show full backtrace for all errors.") do
230
230
  Cucumber.use_full_backtrace = true
231
231
  end
232
- opts.on("-S", "--strict", "Fail if there are any undefined steps.") do
232
+ opts.on("-S", "--strict", "Fail if there are any undefined or pending steps.") do
233
233
  @options[:strict] = true
234
234
  end
235
235
  opts.on("-w", "--wip", "Fail if there are any passing scenarios.") do
@@ -0,0 +1,10 @@
1
+ # Why: http://groups.google.com/group/cukes/browse_thread/thread/5682d41436e235d7
2
+ begin
3
+ require 'minitest/unit'
4
+ class MiniTest::Unit
5
+ class << self
6
+ @@installed_at_exit = true
7
+ end
8
+ end
9
+ rescue LoadError => ignore
10
+ end
@@ -4,7 +4,7 @@ require 'rbconfig'
4
4
 
5
5
  module Cucumber
6
6
  unless defined?(Cucumber::VERSION)
7
- VERSION = '0.9.2'
7
+ VERSION = '0.9.3'
8
8
  BINARY = File.expand_path(File.dirname(__FILE__) + '/../../bin/cucumber')
9
9
  LIBDIR = File.expand_path(File.dirname(__FILE__) + '/../../lib')
10
10
  JRUBY = defined?(JRUBY_VERSION)
@@ -38,6 +38,14 @@ module Cucumber
38
38
  @regexp.inspect
39
39
  end
40
40
 
41
+ def to_hash
42
+ flags = ''
43
+ flags += 'm' if (@regexp.options & Regexp::MULTILINE) != 0
44
+ flags += 'i' if (@regexp.options & Regexp::IGNORECASE) != 0
45
+ flags += 'x' if (@regexp.options & Regexp::EXTENDED) != 0
46
+ {'source' => @regexp.source, 'flags' => flags}
47
+ end
48
+
41
49
  def ==(step_definition)
42
50
  regexp_source == step_definition.regexp_source
43
51
  end
@@ -18,10 +18,21 @@ module Cucumber
18
18
  def initialize(configuration = Configuration.default)
19
19
  @current_scenario = nil
20
20
  @configuration = Configuration.parse(configuration)
21
- @support_code = SupportCode.new(self, @configuration.guess?)
21
+ @support_code = SupportCode.new(self, @configuration)
22
22
  @results = Results.new(@configuration)
23
23
  end
24
24
 
25
+ # Allows you to take an existing runtime and change it's configuration
26
+ def configure(new_configuration)
27
+ @configuration = Configuration.parse(new_configuration)
28
+ @support_code.configure(@configuration)
29
+ @results.configure(@configuration)
30
+ end
31
+
32
+ def load_programming_language(language)
33
+ @support_code.load_programming_language(language)
34
+ end
35
+
25
36
  def run!
26
37
  load_step_definitions
27
38
  fire_after_configuration_hook
@@ -48,67 +59,6 @@ module Cucumber
48
59
  @results.steps(status)
49
60
  end
50
61
 
51
- # Loads and registers programming language implementation.
52
- # Instances are cached, so calling with the same argument
53
- # twice will return the same instance.
54
- #
55
- def load_programming_language(ext)
56
- @support_code.load_programming_language!(ext)
57
- end
58
-
59
- def invoke(step_name, multiline_argument=nil)
60
- # It is very important to leave multiline_argument=nil as a vararg. Cuke4Duke needs it that way.
61
- @support_code.invoke(step_name, multiline_argument)
62
- end
63
-
64
- # Invokes a series of steps +steps_text+. Example:
65
- #
66
- # invoke(%Q{
67
- # Given I have 8 cukes in my belly
68
- # Then I should not be thirsty
69
- # })
70
- def invoke_steps(steps_text, i18n, file_colon_line)
71
- @support_code.invoke_steps(steps_text, i18n, file_colon_line)
72
- end
73
-
74
- # Returns a Cucumber::Ast::Table for +text_or_table+, which can either
75
- # be a String:
76
- #
77
- # table(%{
78
- # | account | description | amount |
79
- # | INT-100 | Taxi | 114 |
80
- # | CUC-101 | Peeler | 22 |
81
- # })
82
- #
83
- # or a 2D Array:
84
- #
85
- # table([
86
- # %w{ account description amount },
87
- # %w{ INT-100 Taxi 114 },
88
- # %w{ CUC-101 Peeler 22 }
89
- # ])
90
- #
91
- def table(text_or_table, file=nil, line_offset=0)
92
- if Array === text_or_table
93
- Ast::Table.new(text_or_table)
94
- else
95
- Ast::Table.parse(text_or_table, file, line_offset)
96
- end
97
- end
98
-
99
- # Returns a regular String for +string_with_triple_quotes+. Example:
100
- #
101
- # """
102
- # hello
103
- # world
104
- # """
105
- #
106
- # Is retured as: " hello\nworld"
107
- #
108
- def py_string(string_with_triple_quotes, file=nil, line_offset=0)
109
- Ast::PyString.parse(string_with_triple_quotes)
110
- end
111
-
112
62
  def step_match(step_name, name_to_report=nil) #:nodoc:
113
63
  @support_code.step_match(step_name, name_to_report)
114
64
  end
@@ -0,0 +1,65 @@
1
+ require 'forwardable'
2
+
3
+ module Cucumber
4
+ class Runtime
5
+ # This is what a programming language will consider to be a runtime.
6
+ #
7
+ # It's a thin class that directs the handul of methods needed by the
8
+ # programming languages to the right place.
9
+ class ForProgrammingLanguages
10
+ extend Forwardable
11
+
12
+ def initialize(support_code, user_interface)
13
+ @support_code, @user_interface = support_code, user_interface
14
+ end
15
+
16
+ def_delegators :@user_interface,
17
+ :embed,
18
+ :ask,
19
+ :announce
20
+
21
+ def_delegators :@support_code,
22
+ :invoke_steps,
23
+ :invoke,
24
+ :load_programming_language
25
+
26
+ # Returns a Cucumber::Ast::Table for +text_or_table+, which can either
27
+ # be a String:
28
+ #
29
+ # table(%{
30
+ # | account | description | amount |
31
+ # | INT-100 | Taxi | 114 |
32
+ # | CUC-101 | Peeler | 22 |
33
+ # })
34
+ #
35
+ # or a 2D Array:
36
+ #
37
+ # table([
38
+ # %w{ account description amount },
39
+ # %w{ INT-100 Taxi 114 },
40
+ # %w{ CUC-101 Peeler 22 }
41
+ # ])
42
+ #
43
+ def table(text_or_table, file=nil, line_offset=0)
44
+ if Array === text_or_table
45
+ Ast::Table.new(text_or_table)
46
+ else
47
+ Ast::Table.parse(text_or_table, file, line_offset)
48
+ end
49
+ end
50
+
51
+ # Returns a regular String for +string_with_triple_quotes+. Example:
52
+ #
53
+ # """
54
+ # hello
55
+ # world
56
+ # """
57
+ #
58
+ # Is retured as: " hello\nworld"
59
+ #
60
+ def py_string(string_with_triple_quotes, file=nil, line_offset=0)
61
+ Ast::PyString.parse(string_with_triple_quotes)
62
+ end
63
+ end
64
+ end
65
+ end
@@ -6,6 +6,10 @@ module Cucumber
6
6
  @configuration = configuration
7
7
  end
8
8
 
9
+ def configure(new_configuration)
10
+ @configuration = Configuration.parse(new_configuration)
11
+ end
12
+
9
13
  def step_visited(step) #:nodoc:
10
14
  steps << step unless steps.index(step)
11
15
  end
@@ -1,9 +1,12 @@
1
1
  require 'cucumber/constantize'
2
+ require 'cucumber/runtime/for_programming_languages'
2
3
 
3
4
  module Cucumber
4
5
  class Runtime
5
6
 
6
7
  class SupportCode
8
+
9
+ require 'forwardable'
7
10
  class StepInvoker
8
11
  include Gherkin::Rubify
9
12
 
@@ -31,25 +34,39 @@ module Cucumber
31
34
  end
32
35
 
33
36
  include Constantize
34
-
35
- def initialize(step_mother, in_guess_mode)
36
- @step_mother = step_mother
37
- @guess_step_matches = in_guess_mode
37
+
38
+ def initialize(user_interface, configuration={})
39
+ @configuration = Configuration.parse(configuration)
40
+ @runtime_facade = Runtime::ForProgrammingLanguages.new(self, user_interface)
38
41
  @unsupported_programming_languages = []
39
42
  @programming_languages = []
40
43
  @language_map = {}
41
44
  end
45
+
46
+ def configure(new_configuration)
47
+ @configuration = Configuration.parse(new_configuration)
48
+ end
42
49
 
50
+ # Invokes a series of steps +steps_text+. Example:
51
+ #
52
+ # invoke(%Q{
53
+ # Given I have 8 cukes in my belly
54
+ # Then I should not be thirsty
55
+ # })
43
56
  def invoke_steps(steps_text, i18n, file_colon_line)
44
57
  file, line = file_colon_line.split(':')
45
58
  parser = Gherkin::Parser::Parser.new(StepInvoker.new(self), true, 'steps')
46
59
  parser.parse(steps_text, file, line.to_i)
47
60
  end
48
-
49
- def load_programming_language!(ext)
61
+
62
+ # Loads and registers programming language implementation.
63
+ # Instances are cached, so calling with the same argument
64
+ # twice will return the same instance.
65
+ #
66
+ def load_programming_language(ext)
50
67
  return @language_map[ext] if @language_map[ext]
51
68
  programming_language_class = constantize("Cucumber::#{ext.capitalize}Support::#{ext.capitalize}Language")
52
- programming_language = programming_language_class.new(@step_mother)
69
+ programming_language = programming_language_class.new(@runtime_facade)
53
70
  @programming_languages << programming_language
54
71
  @language_map[ext] = programming_language
55
72
  programming_language
@@ -75,7 +92,7 @@ module Cucumber
75
92
  end
76
93
 
77
94
  def snippet_text(step_keyword, step_name, multiline_arg_class) #:nodoc:
78
- load_programming_language!('rb') if unknown_programming_language?
95
+ load_programming_language('rb') if unknown_programming_language?
79
96
  @programming_languages.map do |programming_language|
80
97
  programming_language.snippet_text(step_keyword, step_name, multiline_arg_class)
81
98
  end.join("\n")
@@ -116,6 +133,7 @@ module Cucumber
116
133
  end
117
134
 
118
135
  def invoke(step_name, multiline_argument=nil)
136
+ # It is very important to leave multiline_argument=nil as a vararg. Cuke4Duke needs it that way.
119
137
  begin
120
138
  step_match(step_name).invoke(multiline_argument)
121
139
  rescue Exception => e
@@ -127,7 +145,7 @@ module Cucumber
127
145
  private
128
146
 
129
147
  def guess_step_matches?
130
- @guess_step_matches
148
+ @configuration.guess?
131
149
  end
132
150
 
133
151
  def matches(step_name, name_to_report)
@@ -165,11 +183,11 @@ module Cucumber
165
183
  Cucumber.logger
166
184
  end
167
185
 
168
- def programming_language_for(step_def_file) #:nodoc:
186
+ def programming_language_for(step_def_file)
169
187
  if ext = File.extname(step_def_file)[1..-1]
170
188
  return nil if @unsupported_programming_languages.index(ext)
171
189
  begin
172
- load_programming_language!(ext)
190
+ load_programming_language(ext)
173
191
  rescue LoadError => e
174
192
  log.debug("Failed to load '#{ext}' programming language for file #{step_def_file}: #{e.message}\n")
175
193
  @unsupported_programming_languages << ext