cucumber 0.3.7 → 0.3.8
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/History.txt +21 -0
- data/Manifest.txt +6 -0
- data/bin/cucumber +1 -0
- data/examples/java/build.xml +7 -0
- data/features/html_formatter.feature +7 -0
- data/features/html_formatter/a.html +1182 -0
- data/features/step_definitions/cucumber_steps.rb +9 -1
- data/features/support/env.rb +14 -1
- data/lib/cucumber/ast/features.rb +4 -0
- data/lib/cucumber/ast/outline_table.rb +2 -2
- data/lib/cucumber/ast/scenario.rb +2 -0
- data/lib/cucumber/cli/configuration.rb +1 -0
- data/lib/cucumber/cli/main.rb +13 -8
- data/lib/cucumber/formatter/console.rb +6 -1
- data/lib/cucumber/formatter/cucumber.css +31 -12
- data/lib/cucumber/formatter/duration.rb +10 -0
- data/lib/cucumber/formatter/html.rb +28 -9
- data/lib/cucumber/formatter/pretty.rb +3 -3
- data/lib/cucumber/formatter/profile.rb +1 -1
- data/lib/cucumber/formatter/progress.rb +3 -3
- data/lib/cucumber/formatter/tag_cloud.rb +2 -2
- data/lib/cucumber/formatter/usage.rb +2 -2
- data/lib/cucumber/formatters/unicode.rb +5 -0
- data/lib/cucumber/rake/task.rb +4 -3
- data/lib/cucumber/rspec_neuter.rb +23 -0
- data/lib/cucumber/step_match.rb +2 -3
- data/lib/cucumber/version.rb +2 -1
- data/rails_generators/cucumber/cucumber_generator.rb +3 -0
- data/rails_generators/cucumber/templates/cucumber_environment.rb +21 -0
- data/rails_generators/cucumber/templates/env.rb +1 -1
- data/spec/cucumber/formatter/duration_spec.rb +22 -0
- metadata +8 -2
@@ -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
|
data/features/support/env.rb
CHANGED
@@ -30,7 +30,20 @@ class CucumberWorld
|
|
30
30
|
end
|
31
31
|
|
32
32
|
private
|
33
|
-
attr_reader :last_exit_status, :
|
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 =
|
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
|
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/}
|
data/lib/cucumber/cli/main.rb
CHANGED
@@ -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
|
-
|
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?
|
97
|
+
if configuration.diff_enabled?
|
97
98
|
begin
|
98
|
-
require 'spec/
|
99
|
-
|
100
|
-
|
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
|
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:
|
7
|
+
color: #008800;
|
13
8
|
}
|
14
9
|
.cucumber .undefined {
|
15
|
-
color:
|
10
|
+
color: #888800;
|
16
11
|
}
|
17
12
|
.cucumber .pending {
|
18
|
-
color:
|
13
|
+
color: #888800;
|
19
14
|
}
|
20
15
|
.cucumber .failed {
|
21
|
-
color:
|
16
|
+
color: #880000;
|
22
17
|
}
|
23
18
|
.cucumber .skipped {
|
24
|
-
color:
|
19
|
+
color: #008888;
|
25
20
|
}
|
26
21
|
.cucumber .outline {
|
27
|
-
color:
|
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 .
|
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;
|
@@ -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
|
-
|
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
|
-
|
117
|
-
@builder.div do |div|
|
118
|
-
div << h("#{keyword} #{step_name}").gsub(/<span>/, '<span>').gsub(/<\/span>/, '</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
|
-
|
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
|
-
|
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(/<span class="(.*?)">/, '<span class="\1">').gsub(/<\/span>/, '</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
|
-
|
181
|
+
def print_summary(features)
|
182
|
+
print_stats(features)
|
183
183
|
print_snippets(@options)
|
184
184
|
print_passing_wip(@options)
|
185
185
|
end
|
@@ -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
|
-
|
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|
|