cucumber 0.9.2 → 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
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