cucumber 1.1.9 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/.travis.yml +9 -0
  2. data/History.md +20 -3
  3. data/README.md +1 -2
  4. data/cucumber.gemspec +10 -13
  5. data/cucumber.yml +2 -2
  6. data/features/.cucumber/stepdefs.json +13 -391
  7. data/features/backtraces.feature +36 -0
  8. data/features/{issue_117.feature → drb_server_integration.feature} +3 -3
  9. data/features/formatter_step_file_colon_line.feature +46 -0
  10. data/features/{issue_57.feature → rerun_formatter.feature} +2 -2
  11. data/features/run_specific_scenarios.feature +47 -0
  12. data/gem_tasks/cucumber.rake +15 -8
  13. data/legacy_features/cucumber_cli.feature +0 -7
  14. data/legacy_features/junit_formatter.feature +60 -10
  15. data/legacy_features/language_help.feature +1 -0
  16. data/lib/cucumber.rb +2 -1
  17. data/lib/cucumber/ast/step.rb +1 -1
  18. data/lib/cucumber/ast/step_invocation.rb +2 -15
  19. data/lib/cucumber/ast/table.rb +16 -6
  20. data/lib/cucumber/ast/tree_walker.rb +5 -5
  21. data/lib/cucumber/cli/options.rb +5 -8
  22. data/lib/cucumber/formatter/ansicolor.rb +7 -12
  23. data/lib/cucumber/formatter/cucumber.css +7 -1
  24. data/lib/cucumber/formatter/gherkin_formatter_adapter.rb +1 -1
  25. data/lib/cucumber/formatter/html.rb +5 -5
  26. data/lib/cucumber/formatter/interceptor.rb +62 -0
  27. data/lib/cucumber/formatter/junit.rb +30 -14
  28. data/lib/cucumber/formatter/pretty.rb +3 -3
  29. data/lib/cucumber/formatter/progress.rb +1 -1
  30. data/lib/cucumber/formatter/rerun.rb +1 -1
  31. data/lib/cucumber/formatter/usage.rb +1 -1
  32. data/lib/cucumber/js_support/js_snippets.rb +1 -1
  33. data/lib/cucumber/platform.rb +1 -1
  34. data/lib/cucumber/rb_support/rb_dsl.rb +15 -8
  35. data/lib/cucumber/rb_support/rb_language.rb +3 -3
  36. data/lib/cucumber/rb_support/rb_step_definition.rb +17 -5
  37. data/lib/cucumber/term/ansicolor.rb +118 -0
  38. data/spec/cucumber/ast/table_spec.rb +9 -0
  39. data/spec/cucumber/cli/configuration_spec.rb +12 -6
  40. data/spec/cucumber/cli/options_spec.rb +9 -3
  41. data/spec/cucumber/constantize_spec.rb +5 -1
  42. data/spec/cucumber/formatter/ansicolor_spec.rb +1 -1
  43. data/spec/cucumber/formatter/interceptor_spec.rb +111 -0
  44. data/spec/cucumber/formatter/junit_spec.rb +36 -20
  45. data/spec/cucumber/formatter/progress_spec.rb +2 -2
  46. data/spec/cucumber/rb_support/rb_language_spec.rb +5 -5
  47. data/spec/cucumber/rb_support/rb_step_definition_spec.rb +17 -1
  48. data/spec/cucumber/rb_support/regexp_argument_matcher_spec.rb +6 -2
  49. data/spec/cucumber/step_match_spec.rb +8 -4
  50. data/spec/spec_helper.rb +15 -1
  51. metadata +215 -82
  52. data/.gitmodules +0 -3
  53. data/lib/cucumber/formatter/pdf.rb +0 -244
@@ -100,16 +100,16 @@ module Cucumber
100
100
  end
101
101
  end
102
102
 
103
- def visit_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background)
104
- broadcast(keyword, step_match, multiline_arg, status, exception, source_indent, background) do
105
- visit_step_name(keyword, step_match, status, source_indent, background)
103
+ def visit_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background, file_colon_line)
104
+ broadcast(keyword, step_match, multiline_arg, status, exception, source_indent, background, file_colon_line) do
105
+ visit_step_name(keyword, step_match, status, source_indent, background, file_colon_line)
106
106
  visit_multiline_arg(multiline_arg) if multiline_arg
107
107
  visit_exception(exception, status) if exception
108
108
  end
109
109
  end
110
110
 
111
- def visit_step_name(keyword, step_match, status, source_indent, background) #:nodoc:
112
- broadcast(keyword, step_match, status, source_indent, background)
111
+ def visit_step_name(keyword, step_match, status, source_indent, background, file_colon_line) #:nodoc:
112
+ broadcast(keyword, step_match, status, source_indent, background, file_colon_line)
113
113
  end
114
114
 
115
115
  def visit_multiline_arg(multiline_arg) #:nodoc:
@@ -9,10 +9,6 @@ module Cucumber
9
9
  BUILTIN_FORMATS = {
10
10
  'html' => ['Cucumber::Formatter::Html', 'Generates a nice looking HTML report.'],
11
11
  'pretty' => ['Cucumber::Formatter::Pretty', 'Prints the feature as is - in colours.'],
12
- 'pdf' => ['Cucumber::Formatter::Pdf', "Generates a PDF report. You need to have the\n" +
13
- "#{INDENT}prawn gem installed. Will pick up logo from\n" +
14
- "#{INDENT}features/support/logo.png or\n" +
15
- "#{INDENT}features/support/logo.jpg if present."],
16
12
  'progress' => ['Cucumber::Formatter::Progress', 'Prints one character per scenario.'],
17
13
  'rerun' => ['Cucumber::Formatter::Rerun', 'Prints failing files with line numbers.'],
18
14
  'usage' => ['Cucumber::Formatter::Usage', "Prints where step definitions are used.\n" +
@@ -42,6 +38,7 @@ module Cucumber
42
38
  "on Ruby's LOAD_PATH, for example in a Ruby gem."
43
39
  ]
44
40
  DRB_FLAG = '--drb'
41
+ DRB_OPTIONAL_FLAG = '--[no-]drb'
45
42
  PROFILE_SHORT_FLAG = '-p'
46
43
  NO_PROFILE_SHORT_FLAG = '-P'
47
44
  PROFILE_LONG_FLAG = '--profile'
@@ -214,7 +211,7 @@ module Cucumber
214
211
  opts.on("-c", "--[no-]color",
215
212
  "Whether or not to use ANSI color in the output. Cucumber decides",
216
213
  "based on your platform and the output destination if not specified.") do |v|
217
- Term::ANSIColor.coloring = v
214
+ Cucumber::Term::ANSIColor.coloring = v
218
215
  end
219
216
  opts.on("-d", "--dry-run", "Invokes formatters without executing the steps.",
220
217
  "This also omits the loading of your support/env.rb file if it exists.") do
@@ -225,7 +222,7 @@ module Cucumber
225
222
  "Be careful if you choose to overwrite the originals.",
226
223
  "Implies --dry-run --format pretty.") do |directory|
227
224
  @options[:autoformat] = directory
228
- Term::ANSIColor.coloring = false
225
+ Cucumber::Term::ANSIColor.coloring = false
229
226
  @options[:dry_run] = true
230
227
  @quiet = true
231
228
  end
@@ -265,8 +262,8 @@ module Cucumber
265
262
  opts.on("-x", "--expand", "Expand Scenario Outline Tables in output.") do
266
263
  @options[:expand] = true
267
264
  end
268
- opts.on(DRB_FLAG, "Run features against a DRb server. (i.e. with the spork gem)") do
269
- @options[:drb] = true
265
+ opts.on(DRB_OPTIONAL_FLAG, "Run features against a DRb server. (i.e. with the spork gem)") do |drb|
266
+ @options[:drb] = drb
270
267
  end
271
268
  opts.on("--port PORT", "Specify DRb port. Ignored without --drb") do |port|
272
269
  @options[:drb_port] = port
@@ -1,10 +1,5 @@
1
- begin
2
- require 'term/ansicolor'
3
- rescue LoadError
4
- require 'rubygems'
5
- require 'term/ansicolor'
6
- end
7
1
  require 'cucumber/platform'
2
+ require 'cucumber/term/ansicolor'
8
3
 
9
4
  if Cucumber::IRONRUBY
10
5
  begin
@@ -17,11 +12,11 @@ end
17
12
  if Cucumber::WINDOWS_MRI
18
13
  unless ENV['ANSICON']
19
14
  STDERR.puts %{*** WARNING: You must use ANSICON 1.31 or higher (http://adoxa.110mb.com/ansicon) to get coloured output on Windows}
20
- Term::ANSIColor.coloring = false
15
+ Cucumber::Term::ANSIColor.coloring = false
21
16
  end
22
17
  end
23
18
 
24
- Term::ANSIColor.coloring = false if !STDOUT.tty? && !ENV.has_key?('AUTOTEST')
19
+ Cucumber::Term::ANSIColor.coloring = false if !STDOUT.tty? && !ENV.has_key?("AUTOTEST")
25
20
 
26
21
  module Cucumber
27
22
  module Formatter
@@ -57,11 +52,11 @@ module Cucumber
57
52
  # (If you're on Windows, use SET instead of export).
58
53
  # To see what colours and effects are available, just run this in your shell:
59
54
  #
60
- # ruby -e "require 'rubygems'; require 'term/ansicolor'; puts Term::ANSIColor.attributes"
55
+ # ruby -e "require 'rubygems'; require 'term/ansicolor'; puts Cucumber::Term::ANSIColor.attributes"
61
56
  #
62
57
  # Although not listed, you can also use <tt>grey</tt>
63
58
  module ANSIColor
64
- include Term::ANSIColor
59
+ include Cucumber::Term::ANSIColor
65
60
 
66
61
  ALIASES = Hash.new do |h,k|
67
62
  if k.to_s =~ /(.*)_param/
@@ -108,7 +103,7 @@ module Cucumber
108
103
  when 0
109
104
  raise "Your terminal doesn't support colours"
110
105
  when 1
111
- ::Term::ANSIColor.coloring = false
106
+ ::Cucumber::Term::ANSIColor.coloring = false
112
107
  alias grey white
113
108
  when 2..8
114
109
  alias grey white
@@ -130,7 +125,7 @@ module Cucumber
130
125
 
131
126
  def self.define_real_grey #:nodoc:
132
127
  def grey(m) #:nodoc:
133
- if ::Term::ANSIColor.coloring?
128
+ if ::Cucumber::Term::ANSIColor.coloring?
134
129
  "\e[90m#{m}\e[0m"
135
130
  else
136
131
  m
@@ -21,7 +21,7 @@ body {
21
21
  float: right;
22
22
  margin: 0 0 0 10px;
23
23
  }
24
- .cucumber .scenario h3, td .scenario h3, th .scenario h3 {
24
+ .cucumber .scenario h3, td .scenario h3, th .scenario h3, .background h3 {
25
25
  font-size: 11px;
26
26
  padding: 3px;
27
27
  margin: 0;
@@ -29,6 +29,12 @@ body {
29
29
  color: white;
30
30
  font-weight: bold;
31
31
  }
32
+
33
+ .background h3 {
34
+ font-size: 1.2em;
35
+ background: #666;
36
+ }
37
+
32
38
  .cucumber h1, td h1, th h1 {
33
39
  margin: 0px 10px 0px 10px;
34
40
  padding: 10px;
@@ -46,7 +46,7 @@ module Cucumber
46
46
  end
47
47
  end
48
48
 
49
- def before_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background)
49
+ def before_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background, file_colon_line)
50
50
  arguments = step_match.step_arguments.map{|a| Gherkin::Formatter::Argument.new(a.offset, a.val)}
51
51
  location = step_match.file_colon_line
52
52
  match = Gherkin::Formatter::Model::Match.new(arguments, location)
@@ -143,7 +143,7 @@ module Cucumber
143
143
 
144
144
  def background_name(keyword, name, file_colon_line, source_indent)
145
145
  @listing_background = true
146
- @builder.h3 do |h3|
146
+ @builder.h3(:id => "background_#{@scenario_number}") do |h3|
147
147
  @builder.span(keyword, :class => 'keyword')
148
148
  @builder.text!(' ')
149
149
  @builder.span(name, :class => 'val')
@@ -221,7 +221,7 @@ module Cucumber
221
221
  move_progress
222
222
  end
223
223
 
224
- def before_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background)
224
+ def before_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background, file_colon_line)
225
225
  @step_match = step_match
226
226
  @hide_this_step = false
227
227
  if exception
@@ -241,7 +241,7 @@ module Cucumber
241
241
  @builder << "<li id='#{@step_id}' class='step #{status}'>"
242
242
  end
243
243
 
244
- def after_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background)
244
+ def after_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background, file_colon_line)
245
245
  return if @hide_this_step
246
246
  # print snippet for undefined steps
247
247
  if status == :undefined
@@ -254,7 +254,7 @@ module Cucumber
254
254
  print_messages
255
255
  end
256
256
 
257
- def step_name(keyword, step_match, status, source_indent, background)
257
+ def step_name(keyword, step_match, status, source_indent, background, file_colon_line)
258
258
  @step_matches ||= []
259
259
  background_in_scenario = background && !@listing_background
260
260
  @skip_step = @step_matches.index(step_match) || background_in_scenario
@@ -513,7 +513,7 @@ module Cucumber
513
513
  def inline_js_content
514
514
  <<-EOF
515
515
 
516
- SCENARIOS = "h3[id^='scenario_']";
516
+ SCENARIOS = "h3[id^='scenario_'],h3[id^=background_]";
517
517
 
518
518
  $(document).ready(function() {
519
519
  $(SCENARIOS).css('cursor', 'pointer');
@@ -0,0 +1,62 @@
1
+
2
+ module Cucumber
3
+ module Formatter
4
+ module Interceptor
5
+ class Pipe
6
+ attr_reader :pipe, :buffer
7
+ def initialize(pipe)
8
+ @pipe = pipe
9
+ @buffer = []
10
+ @wrapped = true
11
+ end
12
+
13
+ def write(str)
14
+ @buffer << str if @wrapped
15
+ return @pipe.write(str)
16
+ end
17
+
18
+ def unwrap!
19
+ @wrapped = false
20
+ @pipe
21
+ end
22
+
23
+ def method_missing(method, *args, &blk)
24
+ @pipe.send(method, *args, &blk)
25
+ end
26
+
27
+ def self.validate_pipe(pipe)
28
+ unless [:stdout, :stderr].include? pipe
29
+ raise ArgumentError, '#wrap only accepts :stderr or :stdout'
30
+ end
31
+ end
32
+
33
+ def self.unwrap!(pipe)
34
+ validate_pipe pipe
35
+ wrapped = nil
36
+ case pipe
37
+ when :stdout
38
+ wrapped = $stdout
39
+ $stdout = wrapped.unwrap!
40
+ when :stderr
41
+ wrapped = $stderr
42
+ $stderr = wrapped.unwrap!
43
+ end
44
+ wrapped
45
+ end
46
+
47
+ def self.wrap(pipe)
48
+ validate_pipe pipe
49
+
50
+ case pipe
51
+ when :stderr
52
+ $stderr = self.new($stderr)
53
+ return $stderr
54
+ when :stdout
55
+ $stdout = self.new($stdout)
56
+ return $stdout
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -1,5 +1,6 @@
1
1
  require 'cucumber/formatter/ordered_xml_markup'
2
2
  require 'cucumber/formatter/io'
3
+ require 'cucumber/formatter/interceptor'
3
4
  require 'fileutils'
4
5
 
5
6
  module Cucumber
@@ -7,13 +8,13 @@ module Cucumber
7
8
  # The formatter used for <tt>--format junit</tt>
8
9
  class Junit
9
10
  include Io
10
-
11
+
11
12
  class UnNamedFeatureError < StandardError
12
13
  def initialize(feature_file)
13
14
  super("The feature in '#{feature_file}' does not have a name. The JUnit XML format requires a name for the testsuite element.")
14
15
  end
15
16
  end
16
-
17
+
17
18
  def initialize(step_mother, io, options)
18
19
  @reportdir = ensure_dir(io, "junit")
19
20
  @options = options
@@ -24,13 +25,17 @@ module Cucumber
24
25
  @failures = @errors = @tests = @skipped = 0
25
26
  @builder = OrderedXmlMarkup.new( :indent => 2 )
26
27
  @time = 0
28
+ # In order to fill out <system-err/> and <system-out/>, we need to
29
+ # intercept the $stderr and $stdout
30
+ @interceptedout = Interceptor::Pipe.wrap(:stdout)
31
+ @interceptederr = Interceptor::Pipe.wrap(:stderr)
27
32
  end
28
-
33
+
29
34
  def before_feature_element(feature_element)
30
35
  @in_examples = Ast::ScenarioOutline === feature_element
31
36
  @steps_start = Time.now
32
37
  end
33
-
38
+
34
39
  def after_feature(feature)
35
40
  @testsuite = OrderedXmlMarkup.new( :indent => 2 )
36
41
  @testsuite.instruct!
@@ -42,15 +47,24 @@ module Cucumber
42
47
  :time => "%.6f" % @time,
43
48
  :name => @feature_name ) do
44
49
  @testsuite << @builder.target!
50
+ @testsuite.tag!('system-out') do
51
+ @testsuite.cdata! @interceptedout.buffer.join
52
+ end
53
+ @testsuite.tag!('system-err') do
54
+ @testsuite.cdata! @interceptederr.buffer.join
55
+ end
45
56
  end
46
57
 
47
58
  write_file(feature_result_filename(feature.file), @testsuite.target!)
59
+
60
+ Interceptor::Pipe.unwrap! :stdout
61
+ Interceptor::Pipe.unwrap! :stderr
48
62
  end
49
63
 
50
64
  def before_background(*args)
51
65
  @in_background = true
52
66
  end
53
-
67
+
54
68
  def after_background(*args)
55
69
  @in_background = false
56
70
  end
@@ -68,10 +82,10 @@ module Cucumber
68
82
 
69
83
  def before_steps(steps)
70
84
  end
71
-
85
+
72
86
  def after_steps(steps)
73
87
  return if @in_background || @in_examples
74
-
88
+
75
89
  duration = Time.now - @steps_start
76
90
  if steps.failed?
77
91
  steps.each { |step| @output += "#{step.keyword}#{step.name}\n" }
@@ -79,12 +93,12 @@ module Cucumber
79
93
  end
80
94
  build_testcase(duration, steps.status, steps.exception)
81
95
  end
82
-
96
+
83
97
  def before_examples(*args)
84
98
  @header_row = true
85
99
  @in_examples = true
86
100
  end
87
-
101
+
88
102
  def after_examples(*args)
89
103
  @in_examples = false
90
104
  end
@@ -106,7 +120,7 @@ module Cucumber
106
120
  end
107
121
  build_testcase(duration, table_row.status, table_row.exception, name_suffix)
108
122
  end
109
-
123
+
110
124
  @header_row = false if @header_row
111
125
  end
112
126
 
@@ -114,7 +128,7 @@ module Cucumber
114
128
 
115
129
  def build_testcase(duration, status, exception = nil, suffix = "")
116
130
  @time += duration
117
- classname = "#{@feature_name}.#{@scenario}"
131
+ classname = @feature_name
118
132
  name = "#{@scenario}#{suffix}"
119
133
  pending = [:pending, :undefined].include?(status)
120
134
  passed = (status == :passed || (pending && !@options[:strict]))
@@ -131,6 +145,8 @@ module Cucumber
131
145
  @builder.skipped
132
146
  @skipped += 1
133
147
  end
148
+ @builder.tag!('system-out')
149
+ @builder.tag!('system-err')
134
150
  end
135
151
  @tests += 1
136
152
  end
@@ -138,15 +154,15 @@ module Cucumber
138
154
  def format_exception(exception)
139
155
  (["#{exception.message} (#{exception.class})"] + exception.backtrace).join("\n")
140
156
  end
141
-
157
+
142
158
  def feature_result_filename(feature_file)
143
159
  File.join(@reportdir, "TEST-#{basename(feature_file)}.xml")
144
160
  end
145
-
161
+
146
162
  def basename(feature_file)
147
163
  File.basename(feature_file.gsub(/[\\\/]/, '-'), '.feature')
148
164
  end
149
-
165
+
150
166
  def write_file(feature_filename, data)
151
167
  File.open(feature_filename, 'w') { |file| file.write(data) }
152
168
  end
@@ -129,7 +129,7 @@ module Cucumber
129
129
  @indent = 6
130
130
  end
131
131
 
132
- def before_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background)
132
+ def before_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background, file_colon_line)
133
133
  @hide_this_step = false
134
134
  if exception
135
135
  if @exceptions.include?(exception)
@@ -145,7 +145,7 @@ module Cucumber
145
145
  @status = status
146
146
  end
147
147
 
148
- def step_name(keyword, step_match, status, source_indent, background)
148
+ def step_name(keyword, step_match, status, source_indent, background, file_colon_line)
149
149
  return if @hide_this_step
150
150
  source_indent = nil unless @options[:source]
151
151
  name_to_report = format_step(keyword, step_match, status, source_indent)
@@ -203,7 +203,7 @@ module Cucumber
203
203
  cell_text = escape_cell(value.to_s || '')
204
204
  padded = cell_text + (' ' * (width - cell_text.unpack('U*').length))
205
205
  prefix = cell_prefix(status)
206
- @io.print(' ' + format_string("#{prefix}#{padded}", status) + ::Term::ANSIColor.reset(" |"))
206
+ @io.print(' ' + format_string("#{prefix}#{padded}", status) + ::Cucumber::Term::ANSIColor.reset(" |"))
207
207
  @io.flush
208
208
  end
209
209
 
@@ -37,7 +37,7 @@ module Cucumber
37
37
  @exception_raised = false
38
38
  end
39
39
 
40
- def after_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background)
40
+ def after_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background, file_colon_line)
41
41
  progress(status)
42
42
  @status = status
43
43
  end
@@ -76,7 +76,7 @@ module Cucumber
76
76
  return unless @in_examples
77
77
  end
78
78
 
79
- def step_name(keyword, step_match, status, source_indent, background)
79
+ def step_name(keyword, step_match, status, source_indent, background, file_colon_line)
80
80
  @rerun = true if [:failed, :pending, :undefined].index(status)
81
81
  end
82
82