cucumber 0.3.7 → 0.3.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -79,13 +79,21 @@ Then /^"(.*)" should contain XML$/ do |file, xml|
79
79
  end
80
80
 
81
81
  Then /^"(.*)" should contain$/ do |file, text|
82
- IO.read(file).should == text
82
+ strip_duration(IO.read(file)).should == text
83
83
  end
84
84
 
85
85
  Then /^"(.*)" should match$/ do |file, text|
86
86
  IO.read(file).should =~ Regexp.new(text)
87
87
  end
88
88
 
89
+ Then /^"([^\"]*)" should have the same contents as "([^\"]*)"$/ do |actual_file, expected_file|
90
+ actual = IO.read(actual_file)
91
+ # Comment out to replace expected file. Use with care! Remember to update duration afterwards.
92
+ # File.open(expected_file, "w"){|io| io.write(actual)}
93
+ actual = replace_duration(actual, '0m30.005s')
94
+ actual.should == IO.read(expected_file)
95
+ end
96
+
89
97
  Then /^STDERR should match$/ do |text|
90
98
  last_stderr.should =~ /#{text}/
91
99
  end
@@ -30,7 +30,20 @@ class CucumberWorld
30
30
  end
31
31
 
32
32
  private
33
- attr_reader :last_exit_status, :last_stdout, :last_stderr
33
+ attr_reader :last_exit_status, :last_stderr
34
+
35
+ # The last standard out, with the duration line taken out (unpredictable)
36
+ def last_stdout
37
+ strip_duration(@last_stdout)
38
+ end
39
+
40
+ def strip_duration(s)
41
+ s.gsub(/^\d+m\d+\.\d+s\n/m, "")
42
+ end
43
+
44
+ def replace_duration(s, replacement)
45
+ s.gsub(/\d+m\d+\.\d+s/m, replacement)
46
+ end
34
47
 
35
48
  def create_file(file_name, file_content)
36
49
  file_content.gsub!("CUCUMBER_LIB", "'#{cucumber_lib_dir}'") # Some files, such as Rakefiles need to use the lib dir
@@ -3,6 +3,8 @@ module Cucumber
3
3
  class Features
4
4
  include Enumerable
5
5
 
6
+ attr_reader :duration
7
+
6
8
  def initialize
7
9
  @features = []
8
10
  end
@@ -17,9 +19,11 @@ module Cucumber
17
19
  end
18
20
 
19
21
  def accept(visitor)
22
+ start = Time.now
20
23
  @features.each do |feature|
21
24
  visitor.visit_feature(feature)
22
25
  end
26
+ @duration = Time.now - start
23
27
  end
24
28
  end
25
29
  end
@@ -4,7 +4,7 @@ module Cucumber
4
4
  def initialize(raw, scenario_outline)
5
5
  super(raw)
6
6
  @scenario_outline = scenario_outline
7
- @cells_class = ExampleCells
7
+ @cells_class = ExampleRow
8
8
  create_step_invocations_for_example_rows!(scenario_outline)
9
9
  end
10
10
 
@@ -43,7 +43,7 @@ module Cucumber
43
43
  @scenario_outline.visit_scenario_name(visitor, row)
44
44
  end
45
45
 
46
- class ExampleCells < Cells
46
+ class ExampleRow < Cells
47
47
 
48
48
  def create_step_invocations!(scenario_outline)
49
49
  @scenario_outline = scenario_outline
@@ -5,6 +5,8 @@ module Cucumber
5
5
  class Scenario
6
6
  include FeatureElement
7
7
 
8
+ attr_reader :name, :line
9
+
8
10
  def initialize(background, comment, tags, line, keyword, name, steps)
9
11
  @background, @comment, @tags, @line, @keyword, @name = background, comment, tags, line, keyword, name
10
12
  attach_steps(steps)
@@ -257,6 +257,7 @@ module Cucumber
257
257
  requires = @options[:require] || feature_dirs
258
258
  files = requires.map do |path|
259
259
  path = path.gsub(/\\/, '/') # In case we're on windows. Globs don't work with backslashes.
260
+ path = path.gsub(/\/$/, '') # Strip trailing slash.
260
261
  File.directory?(path) ? Dir["#{path}/**/*.rb"] : path
261
262
  end.flatten.uniq
262
263
  sorted_files = files.sort { |a,b| (b =~ %r{/support/} || -1) <=> (a =~ %r{/support/} || -1) }.reject{|f| f =~ /^http/}
@@ -75,11 +75,12 @@ module Cucumber
75
75
  private
76
76
 
77
77
  def require_files
78
+ requires = configuration.files_to_require
78
79
  verbose_log("Ruby files required:")
79
- configuration.files_to_require.each do |lib|
80
+ verbose_log(requires.map{|lib| " * #{lib}"}.join("\n"))
81
+ requires.each do |lib|
80
82
  begin
81
83
  require lib
82
- verbose_log(" * #{lib}")
83
84
  rescue LoadError => e
84
85
  e.message << "\nFailed to load #{lib}"
85
86
  raise e
@@ -93,14 +94,18 @@ module Cucumber
93
94
  end
94
95
 
95
96
  def enable_diffing
96
- if configuration.diff_enabled? && defined?(::Spec)
97
+ if configuration.diff_enabled?
97
98
  begin
98
- require 'spec/runner/differs/default' # RSpec >=1.2.4
99
- rescue ::LoadError
100
- require 'spec/expectations/differs/default' # RSpec <=1.2.3
99
+ require 'spec/expectations'
100
+ begin
101
+ require 'spec/runner/differs/default' # RSpec >=1.2.4
102
+ rescue ::LoadError
103
+ require 'spec/expectations/differs/default' # RSpec <=1.2.3
104
+ end
105
+ options = OpenStruct.new(:diff_format => :unified, :context_lines => 3)
106
+ ::Spec::Expectations.differ = ::Spec::Expectations::Differs::Default.new(options)
107
+ rescue ::LoadError => ignore
101
108
  end
102
- options = OpenStruct.new(:diff_format => :unified, :context_lines => 3)
103
- ::Spec::Expectations.differ = ::Spec::Expectations::Differs::Default.new(options)
104
109
  end
105
110
  end
106
111
 
@@ -1,9 +1,12 @@
1
1
  require 'cucumber/formatter/ansicolor'
2
+ require 'cucumber/formatter/duration'
2
3
 
3
4
  module Cucumber
4
5
  module Formatter
5
6
  module Console
6
7
  extend ANSIColor
8
+ include Duration
9
+
7
10
  FORMATS = Hash.new{|hash, format| hash[format] = method(format).to_proc}
8
11
 
9
12
  def format_step(keyword, step_match, status, source_indent)
@@ -50,13 +53,15 @@ module Cucumber
50
53
  end
51
54
  end
52
55
 
53
- def print_counts
56
+ def print_stats(features)
54
57
  @io.print dump_count(step_mother.scenarios.length, "scenario")
55
58
  print_status_counts{|status| step_mother.scenarios(status)}
56
59
 
57
60
  @io.print dump_count(step_mother.steps.length, "step")
58
61
  print_status_counts{|status| step_mother.steps(status)}
59
62
 
63
+ @io.puts(format_duration(features.duration))
64
+
60
65
  @io.flush
61
66
  end
62
67
 
@@ -1,34 +1,53 @@
1
-
2
-
3
-
4
-
5
-
6
1
  .cucumber {
7
2
  background: black;
8
3
  color: white;
9
4
  padding: 1em;
10
5
  }
11
6
  .cucumber .passed {
12
- color: green;
7
+ color: #008800;
13
8
  }
14
9
  .cucumber .undefined {
15
- color: yellow;
10
+ color: #888800;
16
11
  }
17
12
  .cucumber .pending {
18
- color: yellow;
13
+ color: #888800;
19
14
  }
20
15
  .cucumber .failed {
21
- color: red;
16
+ color: #880000;
22
17
  }
23
18
  .cucumber .skipped {
24
- color: cyan;
19
+ color: #008888;
25
20
  }
26
21
  .cucumber .outline {
27
- color: cyan;
22
+ color: #008888;
23
+ }
24
+
25
+ .cucumber .passed_param {
26
+ font-weight: bold;
27
+ color: #00ff00;
28
+ }
29
+ .cucumber .undefined_param {
30
+ font-weight: bold;
31
+ color: #ffff00;
28
32
  }
29
- .cucumber .param {
33
+ .cucumber .pending_param {
30
34
  font-weight: bold;
35
+ color: #ffff00;
31
36
  }
37
+ .cucumber .failed_param {
38
+ font-weight: bold;
39
+ font-weight: bold;
40
+ color: #ff0000;
41
+ }
42
+ .cucumber .skipped_param {
43
+ font-weight: bold;
44
+ color: #00ffff;
45
+ }
46
+ .cucumber .outline_param {
47
+ font-weight: bold;
48
+ color: #00ffff;
49
+ }
50
+
32
51
  .cucumber a {
33
52
  text-decoration: none;
34
53
  color: inherit;
@@ -0,0 +1,10 @@
1
+ module Cucumber
2
+ module Formatter
3
+ module Duration
4
+ def format_duration(seconds)
5
+ m, s = seconds.divmod(60)
6
+ "#{m}m#{'%.3f' % s}s"
7
+ end
8
+ end
9
+ end
10
+ end
@@ -5,11 +5,13 @@ rescue LoadError
5
5
  gem 'builder'
6
6
  require 'builder'
7
7
  end
8
+ require 'cucumber/formatter/duration'
8
9
 
9
10
  module Cucumber
10
11
  module Formatter
11
12
  class Html < Ast::Visitor
12
13
  include ERB::Util # for the #h method
14
+ include Duration
13
15
 
14
16
  def initialize(step_mother, io, options)
15
17
  super(step_mother)
@@ -34,6 +36,7 @@ module Cucumber
34
36
  @builder.body do
35
37
  @builder.div(:class => 'cucumber') do
36
38
  super
39
+ @builder.div(format_duration(features.duration), :class => 'duration')
37
40
  end
38
41
  end
39
42
  end
@@ -45,6 +48,10 @@ module Cucumber
45
48
  end
46
49
  end
47
50
 
51
+ def visit_tag_name(tag_name)
52
+ @builder.span("@#{tag_name}", :class => 'tag')
53
+ end
54
+
48
55
  def visit_feature_name(name)
49
56
  lines = name.split(/\r?\n/)
50
57
  @builder.h2(lines[0])
@@ -63,6 +70,7 @@ module Cucumber
63
70
  end
64
71
 
65
72
  def visit_background_name(keyword, name, file_colon_line, source_indent)
73
+ @listing_background = true
66
74
  @builder.h3("#{keyword} #{name}")
67
75
  end
68
76
 
@@ -74,6 +82,7 @@ module Cucumber
74
82
  end
75
83
 
76
84
  def visit_scenario_name(keyword, name, file_colon_line, source_indent)
85
+ @listing_background = false
77
86
  @builder.h3("#{keyword} #{name}")
78
87
  end
79
88
 
@@ -102,21 +111,19 @@ module Cucumber
102
111
 
103
112
  def visit_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background)
104
113
  @status = status
105
- @builder.li(:id => @step_id, :class => status) do
114
+ @builder.li(:id => @step_id, :class => "step #{status}") do
106
115
  super(keyword, step_match, multiline_arg, status, exception, source_indent, background)
107
116
  end
108
117
  end
109
118
 
110
119
  def visit_step_name(keyword, step_match, status, source_indent, background)
111
120
  @step_matches ||= []
112
- @skip_step = @step_matches.index(step_match)
121
+ background_in_scenario = background && !@listing_background
122
+ @skip_step = @step_matches.index(step_match) || background_in_scenario
113
123
  @step_matches << step_match
114
124
 
115
125
  unless @skip_step
116
- step_name = step_match.format_args(lambda{|param| "<span>#{param}</span>"})
117
- @builder.div do |div|
118
- div << h("#{keyword} #{step_name}").gsub(/&lt;span&gt;/, '<span>').gsub(/&lt;\/span&gt;/, '</span>')
119
- end
126
+ build_step(keyword, step_match, status)
120
127
  end
121
128
  end
122
129
 
@@ -163,15 +170,26 @@ module Cucumber
163
170
  cell_type = @outline_row == 0 ? :th : :td
164
171
  attributes = {:id => "#{@row_id}_#{@col_index}"}
165
172
  attributes[:class] = status if status
166
- @builder.__send__(cell_type, value, attributes)
173
+ build_cell(cell_type, value, attributes)
167
174
  @col_index += 1
168
175
  end
169
-
176
+
170
177
  def announce(announcement)
171
178
  @builder.pre(announcement, :class => 'announcement')
172
179
  end
173
180
 
174
- private
181
+ protected
182
+
183
+ def build_step(keyword, step_match, status)
184
+ step_name = step_match.format_args(lambda{|param| %{<span class="#{status}_param">#{param}</span>}})
185
+ @builder.div do |div|
186
+ div << h("#{keyword} #{step_name}").gsub(/&lt;span class=&quot;(.*?)&quot;&gt;/, '<span class="\1">').gsub(/&lt;\/span&gt;/, '</span>')
187
+ end
188
+ end
189
+
190
+ def build_cell(cell_type, value, attributes)
191
+ @builder.__send__(cell_type, value, attributes)
192
+ end
175
193
 
176
194
  def inline_css
177
195
  @builder.style(:type => 'text/css') do
@@ -182,6 +200,7 @@ module Cucumber
182
200
  def format_exception(exception)
183
201
  (["#{exception.message} (#{exception.class})"] + exception.backtrace).join("\n")
184
202
  end
203
+
185
204
  end
186
205
  end
187
206
  end
@@ -24,7 +24,7 @@ module Cucumber
24
24
 
25
25
  def visit_features(features)
26
26
  super
27
- print_summary unless @options[:autoformat]
27
+ print_summary(features) unless @options[:autoformat]
28
28
  end
29
29
 
30
30
  def visit_feature(feature)
@@ -178,8 +178,8 @@ module Cucumber
178
178
 
179
179
  private
180
180
 
181
- def print_summary
182
- print_counts
181
+ def print_summary(features)
182
+ print_stats(features)
183
183
  print_snippets(@options)
184
184
  print_passing_wip(@options)
185
185
  end
@@ -27,7 +27,7 @@ module Cucumber
27
27
  end
28
28
  end
29
29
 
30
- def print_summary
30
+ def print_summary(features)
31
31
  super
32
32
  @io.puts "\n\nTop #{NUMBER_OF_STEP_DEFINITONS_TO_SHOW} average slowest steps with #{NUMBER_OF_STEP_INVOCATIONS_TO_SHOW} slowest matches:\n"
33
33
 
@@ -15,7 +15,7 @@ module Cucumber
15
15
  super
16
16
  @io.puts
17
17
  @io.puts
18
- print_summary
18
+ print_summary(features)
19
19
  end
20
20
 
21
21
  def visit_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background)
@@ -30,10 +30,10 @@ module Cucumber
30
30
 
31
31
  private
32
32
 
33
- def print_summary
33
+ def print_summary(features)
34
34
  print_steps(:pending)
35
35
  print_steps(:failed)
36
- print_counts
36
+ print_stats(features)
37
37
  print_snippets(@options)
38
38
  print_passing_wip(@options)
39
39
  end
@@ -10,14 +10,14 @@ module Cucumber
10
10
 
11
11
  def visit_features(features)
12
12
  super
13
- print_summary
13
+ print_summary(features)
14
14
  end
15
15
 
16
16
  def visit_tag_name(tag_name)
17
17
  @counts[tag_name] += 1
18
18
  end
19
19
 
20
- def print_summary
20
+ def print_summary(features)
21
21
  matrix = @counts.to_a.sort{|paira, pairb| paira[0] <=> pairb[0]}.transpose
22
22
  table = Cucumber::Ast::Table.new(matrix)
23
23
  Cucumber::Formatter::Pretty.new(@step_mother, @io, {}).visit_multiline_arg(table)
@@ -16,7 +16,7 @@ module Cucumber
16
16
 
17
17
  def visit_features(features)
18
18
  super
19
- print_summary
19
+ print_summary(features)
20
20
  end
21
21
 
22
22
  def visit_step(step)
@@ -37,7 +37,7 @@ module Cucumber
37
37
  end
38
38
  end
39
39
 
40
- def print_summary
40
+ def print_summary(features)
41
41
  sorted_defs = @step_definitions.keys.sort_by{|step_definition| step_definition.backtrace_line}
42
42
 
43
43
  sorted_defs.each do |step_definition|