square-cucumber 0.3.12.2 → 0.3.93.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +117 -4
- data/Manifest.txt +11 -0
- data/Rakefile +1 -1
- data/config/hoe.rb +3 -2
- data/cucumber.yml +2 -2
- data/examples/i18n/ko/features/addition.feature +5 -5
- data/examples/i18n/ko/features/step_definitons/calculator_steps.rb +1 -1
- data/examples/i18n/no/features/step_definitons/kalkulator_steps.rb +1 -1
- data/examples/i18n/pt/features/adicao.feature +4 -4
- data/examples/self_test/features/support/env.rb +2 -1
- data/examples/sinatra/features/support/env.rb +7 -1
- data/examples/steps_library/features/step_definitions/steps_lib1.rb +8 -0
- data/examples/steps_library/features/step_definitions/steps_lib2.rb +8 -0
- data/examples/tickets/features/step_definitons/tickets_steps.rb +15 -0
- data/examples/tickets/features/table_diffing.feature +13 -0
- data/examples/watir/features/step_definitons/search_steps.rb +5 -1
- data/features/cucumber_cli_diff_disabled.feature +2 -1
- data/features/html_formatter/a.html +5 -7
- data/features/junit_formatter.feature +21 -14
- data/features/profiles.feature +99 -0
- data/features/rake_task.feature +28 -0
- data/features/step_definitions/cucumber_steps.rb +28 -15
- data/features/steps_formatter.feature +25 -0
- data/features/support/env.rb +9 -5
- data/features/table_diffing.feature +45 -0
- data/features/unicode_table.feature +35 -0
- data/features/work_in_progress.feature +1 -0
- data/gem_tasks/contributors.rake +4 -0
- data/lib/cucumber/ast/background.rb +1 -0
- data/lib/cucumber/ast/comment.rb +1 -0
- data/lib/cucumber/ast/examples.rb +1 -0
- data/lib/cucumber/ast/feature.rb +10 -0
- data/lib/cucumber/ast/features.rb +6 -1
- data/lib/cucumber/ast/outline_table.rb +4 -1
- data/lib/cucumber/ast/py_string.rb +1 -1
- data/lib/cucumber/ast/scenario.rb +1 -0
- data/lib/cucumber/ast/scenario_outline.rb +2 -0
- data/lib/cucumber/ast/step.rb +5 -1
- data/lib/cucumber/ast/step_collection.rb +1 -0
- data/lib/cucumber/ast/step_invocation.rb +1 -0
- data/lib/cucumber/ast/table.rb +306 -52
- data/lib/cucumber/ast/tags.rb +1 -0
- data/lib/cucumber/ast/visitor.rb +2 -1
- data/lib/cucumber/cli/configuration.rb +28 -278
- data/lib/cucumber/cli/drb_client.rb +3 -1
- data/lib/cucumber/cli/language_help_formatter.rb +9 -7
- data/lib/cucumber/cli/main.rb +16 -2
- data/lib/cucumber/cli/options.rb +370 -0
- data/lib/cucumber/cli/profile_loader.rb +65 -0
- data/lib/cucumber/core_ext/instance_exec.rb +8 -5
- data/lib/cucumber/feature_file.rb +7 -1
- data/lib/cucumber/filter.rb +2 -2
- data/lib/cucumber/formatter/ansicolor.rb +42 -9
- data/lib/cucumber/formatter/console.rb +1 -1
- data/lib/cucumber/formatter/html.rb +12 -10
- data/lib/cucumber/formatter/junit.rb +63 -26
- data/lib/cucumber/formatter/pretty.rb +20 -5
- data/lib/cucumber/formatter/progress.rb +1 -1
- data/lib/cucumber/formatter/steps.rb +49 -0
- data/lib/cucumber/languages.yml +6 -6
- data/lib/cucumber/parser/feature.rb +90 -63
- data/lib/cucumber/parser/feature.tt +28 -1
- data/lib/cucumber/parser/i18n/language.rb +12 -5
- data/lib/cucumber/parser/table.rb +25 -25
- data/lib/cucumber/rake/task.rb +9 -3
- data/lib/cucumber/step_definition.rb +1 -1
- data/lib/cucumber/step_match.rb +1 -1
- data/lib/cucumber/step_mother.rb +3 -1
- data/lib/cucumber/version.rb +2 -2
- data/lib/cucumber/webrat/table_locator.rb +66 -0
- data/rails_generators/cucumber/cucumber_generator.rb +5 -1
- data/rails_generators/cucumber/templates/cucumber +3 -2
- data/rails_generators/cucumber/templates/cucumber.rake +18 -6
- data/rails_generators/cucumber/templates/cucumber_environment.rb +7 -4
- data/rails_generators/cucumber/templates/env.rb +1 -0
- data/rails_generators/cucumber/templates/spork_env.rb +1 -0
- data/rails_generators/cucumber/templates/webrat_steps.rb +22 -0
- data/rails_generators/feature/templates/feature.erb +1 -1
- data/rails_generators/feature/templates/steps.erb +2 -8
- data/spec/cucumber/ast/table_spec.rb +169 -0
- data/spec/cucumber/cli/configuration_spec.rb +144 -101
- data/spec/cucumber/cli/main_spec.rb +14 -5
- data/spec/cucumber/cli/options_spec.rb +311 -0
- data/spec/cucumber/cli/profile_loader_spec.rb +10 -0
- data/spec/cucumber/core_ext/proc_spec.rb +16 -2
- data/spec/cucumber/formatter/html_spec.rb +18 -0
- data/spec/cucumber/formatter/progress_spec.rb +2 -2
- data/spec/cucumber/parser/table_parser_spec.rb +1 -1
- data/spec/spec.opts +3 -1
- metadata +18 -4
- data/lib/cucumber/webrat/mechanize_world.rb +0 -82
@@ -10,10 +10,12 @@ class Object
|
|
10
10
|
cucumber_run_with_backtrace_filtering(pseudo_method) do
|
11
11
|
if check_arity && !cucumber_compatible_arity?(args, block)
|
12
12
|
instance_exec do
|
13
|
-
|
13
|
+
ari = cucumber_arity(block)
|
14
|
+
ari = ari < 0 ? (ari.abs-1).to_s+"+" : ari
|
15
|
+
s1 = ari == 1 ? "" : "s"
|
14
16
|
s2 = args.length == 1 ? "" : "s"
|
15
17
|
raise Cucumber::ArityMismatchError.new(
|
16
|
-
"Your block takes #{
|
18
|
+
"Your block takes #{ari} argument#{s1}, but the Regexp matched #{args.length} argument#{s2}."
|
17
19
|
)
|
18
20
|
end
|
19
21
|
else
|
@@ -28,9 +30,10 @@ class Object
|
|
28
30
|
end
|
29
31
|
|
30
32
|
def cucumber_compatible_arity?(args, block)
|
31
|
-
|
32
|
-
|
33
|
-
|
33
|
+
ari = cucumber_arity(block)
|
34
|
+
len = args.length
|
35
|
+
return true if ari == len or ari < 0 && len >= ari.abs-1
|
36
|
+
false
|
34
37
|
end
|
35
38
|
|
36
39
|
def cucumber_run_with_backtrace_filtering(pseudo_method)
|
@@ -31,7 +31,13 @@ module Cucumber
|
|
31
31
|
require 'open-uri'
|
32
32
|
open(@path).read
|
33
33
|
else
|
34
|
-
|
34
|
+
begin
|
35
|
+
File.open(@path, Cucumber.file_mode('r')).read
|
36
|
+
rescue Errno::EACCES => e
|
37
|
+
p = File.expand_path(@path)
|
38
|
+
e.message << "\nCouldn't open #{p}"
|
39
|
+
raise e
|
40
|
+
end
|
35
41
|
end
|
36
42
|
end
|
37
43
|
|
data/lib/cucumber/filter.rb
CHANGED
@@ -32,7 +32,7 @@ module Cucumber
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def included_by_tags?(syntax_node)
|
35
|
-
@include_tags.empty? || syntax_node.
|
35
|
+
@include_tags.empty? || syntax_node.has_all_tags?(@include_tags)
|
36
36
|
end
|
37
37
|
|
38
38
|
def excluded_by_tags?(syntax_node)
|
@@ -47,4 +47,4 @@ module Cucumber
|
|
47
47
|
@name_regexps.nil? || @name_regexps.empty? || @name_regexps.detect{|name_regexp| syntax_node.matches_name?(name_regexp)}
|
48
48
|
end
|
49
49
|
end
|
50
|
-
end
|
50
|
+
end
|
@@ -60,15 +60,6 @@ module Cucumber
|
|
60
60
|
module ANSIColor
|
61
61
|
include Term::ANSIColor
|
62
62
|
|
63
|
-
# Not supported in Term::ANSIColor
|
64
|
-
def grey(m)
|
65
|
-
if ::Term::ANSIColor.coloring?
|
66
|
-
"\e[90m#{m}\e[0m"
|
67
|
-
else
|
68
|
-
m
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
63
|
ALIASES = Hash.new do |h,k|
|
73
64
|
if k.to_s =~ /(.*)_param/
|
74
65
|
h[$1] + ',bold'
|
@@ -105,6 +96,48 @@ module Cucumber
|
|
105
96
|
eval(code)
|
106
97
|
end
|
107
98
|
end
|
99
|
+
|
100
|
+
def self.define_grey
|
101
|
+
begin
|
102
|
+
gem 'genki-ruby-terminfo'
|
103
|
+
require 'terminfo'
|
104
|
+
puts TermInfo.default_object.tigetnum("colors")
|
105
|
+
case TermInfo.default_object.tigetnum("colors")
|
106
|
+
when 0
|
107
|
+
raise "Your terminal doesn't support colours"
|
108
|
+
when 1
|
109
|
+
::Term::ANSIColor.coloring = false
|
110
|
+
alias grey white
|
111
|
+
when 2..8
|
112
|
+
alias grey white
|
113
|
+
else
|
114
|
+
define_real_grey
|
115
|
+
end
|
116
|
+
rescue Exception => e
|
117
|
+
if e.class.name == 'TermInfo::TermInfoError'
|
118
|
+
STDERR.puts "*** WARNING ***"
|
119
|
+
STDERR.puts "You have the genki-ruby-terminfo gem installed, but you haven't set your TERM variable."
|
120
|
+
STDERR.puts "Try setting it to TERM=xterm-256color to get grey colour in output"
|
121
|
+
STDERR.puts "\n"
|
122
|
+
alias grey white
|
123
|
+
else
|
124
|
+
define_real_grey
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def self.define_real_grey
|
130
|
+
def grey(m)
|
131
|
+
if ::Term::ANSIColor.coloring?
|
132
|
+
"\e[90m#{m}\e[0m"
|
133
|
+
else
|
134
|
+
m
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
define_grey
|
140
|
+
|
108
141
|
end
|
109
142
|
end
|
110
143
|
end
|
@@ -77,7 +77,7 @@ module Cucumber
|
|
77
77
|
@io.print dump_count(step_mother.steps.length, "step")
|
78
78
|
print_status_counts{|status| step_mother.steps(status)}
|
79
79
|
|
80
|
-
@io.puts(format_duration(features.duration)) if features
|
80
|
+
@io.puts(format_duration(features.duration)) if features && features.duration
|
81
81
|
|
82
82
|
@io.flush
|
83
83
|
end
|
@@ -1,10 +1,4 @@
|
|
1
|
-
require '
|
2
|
-
begin
|
3
|
-
require 'builder'
|
4
|
-
rescue LoadError
|
5
|
-
gem 'builder'
|
6
|
-
require 'builder'
|
7
|
-
end
|
1
|
+
require 'cucumber/formatter/ordered_xml_markup'
|
8
2
|
require 'cucumber/formatter/duration'
|
9
3
|
|
10
4
|
module Cucumber
|
@@ -20,7 +14,7 @@ module Cucumber
|
|
20
14
|
end
|
21
15
|
|
22
16
|
def create_builder(io)
|
23
|
-
|
17
|
+
OrderedXmlMarkup.new(:target => io, :indent => 0)
|
24
18
|
end
|
25
19
|
|
26
20
|
def visit_features(features)
|
@@ -65,12 +59,20 @@ module Cucumber
|
|
65
59
|
end
|
66
60
|
end
|
67
61
|
|
62
|
+
def visit_tags(tags)
|
63
|
+
super
|
64
|
+
@tag_spacer = nil
|
65
|
+
end
|
66
|
+
|
68
67
|
def visit_tag_name(tag_name)
|
68
|
+
@builder.text!(@tag_spacer) if @tag_spacer
|
69
|
+
@tag_spacer = ' '
|
69
70
|
@builder.span("@#{tag_name}", :class => 'tag')
|
70
71
|
end
|
71
72
|
|
72
73
|
def visit_feature_name(name)
|
73
74
|
lines = name.split(/\r?\n/)
|
75
|
+
return if lines.empty?
|
74
76
|
@builder.h2 do |h2|
|
75
77
|
@builder.span(lines[0], :class => 'val')
|
76
78
|
end
|
@@ -192,7 +194,7 @@ module Cucumber
|
|
192
194
|
|
193
195
|
def visit_py_string(string)
|
194
196
|
@builder.pre(:class => 'val') do |pre|
|
195
|
-
@builder.
|
197
|
+
@builder << string.gsub("\n", '
')
|
196
198
|
end
|
197
199
|
end
|
198
200
|
|
@@ -214,7 +216,7 @@ module Cucumber
|
|
214
216
|
@outline_row += 1 if @outline_row
|
215
217
|
end
|
216
218
|
|
217
|
-
def visit_table_cell_value(value,
|
219
|
+
def visit_table_cell_value(value, status)
|
218
220
|
cell_type = @outline_row == 0 ? :th : :td
|
219
221
|
attributes = {:id => "#{@row_id}_#{@col_index}", :class => 'val'}
|
220
222
|
attributes[:class] += " #{status}" if status
|
@@ -1,9 +1,4 @@
|
|
1
|
-
|
2
|
-
require 'builder'
|
3
|
-
rescue LoadError
|
4
|
-
gem 'builder'
|
5
|
-
require 'builder'
|
6
|
-
end
|
1
|
+
require 'cucumber/formatter/ordered_xml_markup'
|
7
2
|
|
8
3
|
module Cucumber
|
9
4
|
module Formatter
|
@@ -18,16 +13,18 @@ module Cucumber
|
|
18
13
|
|
19
14
|
def visit_feature(feature)
|
20
15
|
@failures = @errors = @tests = 0
|
21
|
-
@builder =
|
16
|
+
@builder = OrderedXmlMarkup.new( :indent => 2 )
|
17
|
+
@time = 0
|
22
18
|
super
|
23
19
|
|
24
|
-
@testsuite =
|
20
|
+
@testsuite = OrderedXmlMarkup.new( :indent => 2 )
|
25
21
|
@testsuite.instruct!
|
26
22
|
@testsuite.testsuite(
|
27
23
|
:failures => @failures,
|
28
24
|
:errors => @errors,
|
29
25
|
:tests => @tests,
|
30
|
-
:
|
26
|
+
:time => @time,
|
27
|
+
:name => @feature_name ) do
|
31
28
|
@testsuite << @builder.target!
|
32
29
|
end
|
33
30
|
|
@@ -36,40 +33,80 @@ module Cucumber
|
|
36
33
|
File.open(feature_filename, 'w') { |file| file.write(@testsuite.target!) }
|
37
34
|
end
|
38
35
|
|
36
|
+
def visit_background(name)
|
37
|
+
@in_background = true
|
38
|
+
super
|
39
|
+
@in_background = false
|
40
|
+
end
|
41
|
+
|
39
42
|
def visit_feature_name(name)
|
40
43
|
lines = name.split(/\r?\n/)
|
41
44
|
@feature_name = lines[0].sub(/Feature\:/, '').strip
|
42
45
|
end
|
43
46
|
|
44
|
-
def visit_scenario_name(keyword, name, file_colon_line, source_indent)
|
45
|
-
|
47
|
+
def visit_scenario_name(keyword, name, file_colon_line, source_indent)
|
48
|
+
scenario_name = name.strip
|
49
|
+
scenario_name = "Unnamed scenario" if name == ""
|
50
|
+
@scenario = scenario_name
|
51
|
+
@outline = keyword.include?('Scenario Outline')
|
52
|
+
@output = "Scenario#{ " outline" if @outline}: #{@scenario}\n\n"
|
46
53
|
end
|
47
54
|
|
48
55
|
def visit_steps(steps)
|
49
|
-
|
56
|
+
return if @in_background
|
57
|
+
start = Time.now
|
50
58
|
super
|
51
|
-
|
52
|
-
@
|
59
|
+
duration = Time.now - start
|
60
|
+
unless @outline
|
61
|
+
if steps.failed?
|
62
|
+
steps.each { |step| @output += "#{step.keyword} #{step.name}\n" }
|
63
|
+
@output += "\nMessage:\n"
|
64
|
+
end
|
65
|
+
build_testcase(duration, steps.status, steps.exception)
|
66
|
+
end
|
53
67
|
end
|
54
68
|
|
55
|
-
def
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
69
|
+
def visit_outline_table(outline_table)
|
70
|
+
@header_row = true
|
71
|
+
super(outline_table)
|
72
|
+
end
|
73
|
+
|
74
|
+
def visit_table_row(table_row)
|
75
|
+
start = Time.now
|
76
|
+
super(table_row)
|
77
|
+
duration = Time.now - start
|
78
|
+
unless @header_row
|
79
|
+
name_suffix = " (outline example : #{table_row.name})"
|
80
|
+
if table_row.failed?
|
81
|
+
@output += "Example row: #{table_row.name}\n"
|
82
|
+
@output += "\nMessage:\n"
|
63
83
|
end
|
84
|
+
build_testcase(duration, table_row.status, table_row.exception, name_suffix)
|
64
85
|
end
|
86
|
+
@header_row = false
|
65
87
|
end
|
66
88
|
|
67
89
|
private
|
68
90
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
91
|
+
def build_testcase(duration, status, exception = nil, suffix = "")
|
92
|
+
@time += duration
|
93
|
+
classname = "#{@feature_name}.#{@scenario}"
|
94
|
+
name = "#{@scenario}#{suffix}"
|
95
|
+
@builder.testcase(:classname => classname, :name => name, :time => duration) do
|
96
|
+
if status != :passed
|
97
|
+
@builder.failure(:message => "#{status.to_s} #{name}", :type => status.to_s) do
|
98
|
+
@builder.text! @output
|
99
|
+
@builder.text!(format_exception(exception)) if exception
|
100
|
+
end
|
101
|
+
@failures += 1
|
102
|
+
end
|
103
|
+
end
|
104
|
+
@tests += 1
|
105
|
+
end
|
73
106
|
|
107
|
+
def format_exception(exception)
|
108
|
+
(["#{exception.message} (#{exception.class})"] + exception.backtrace).join("\n")
|
109
|
+
end
|
110
|
+
end
|
74
111
|
end
|
75
112
|
end
|
@@ -13,13 +13,13 @@ module Cucumber
|
|
13
13
|
include Console
|
14
14
|
attr_writer :indent
|
15
15
|
|
16
|
-
def initialize(step_mother, io, options
|
16
|
+
def initialize(step_mother, io, options)
|
17
17
|
super(step_mother)
|
18
18
|
@io = io
|
19
19
|
@options = options
|
20
|
-
@delim = delim
|
21
20
|
@exceptions = []
|
22
21
|
@indent = 0
|
22
|
+
@prefixes = options[:prefixes] || {}
|
23
23
|
end
|
24
24
|
|
25
25
|
def visit_features(features)
|
@@ -145,6 +145,7 @@ module Cucumber
|
|
145
145
|
|
146
146
|
def visit_multiline_arg(multiline_arg)
|
147
147
|
return if @options[:no_multiline]
|
148
|
+
@table = multiline_arg
|
148
149
|
super
|
149
150
|
end
|
150
151
|
|
@@ -154,7 +155,8 @@ module Cucumber
|
|
154
155
|
end
|
155
156
|
|
156
157
|
def visit_table_row(table_row)
|
157
|
-
@
|
158
|
+
@col_index = 0
|
159
|
+
@io.print ' |'.indent(@indent-2)
|
158
160
|
super
|
159
161
|
@io.puts
|
160
162
|
if table_row.exception && !@exceptions.index(table_row.exception)
|
@@ -169,13 +171,26 @@ module Cucumber
|
|
169
171
|
@io.flush
|
170
172
|
end
|
171
173
|
|
172
|
-
def
|
174
|
+
def visit_table_cell(cell)
|
175
|
+
super
|
176
|
+
@col_index += 1
|
177
|
+
end
|
178
|
+
|
179
|
+
def visit_table_cell_value(value, status)
|
173
180
|
status ||= @status || :passed
|
174
|
-
|
181
|
+
width = @table.col_width(@col_index)
|
182
|
+
cell_text = value.to_s || ''
|
183
|
+
padded = cell_text + (' ' * (width - cell_text.jlength))
|
184
|
+
prefix = cell_prefix(status)
|
185
|
+
@io.print(' ' + format_string("#{prefix}#{padded}", status) + ::Term::ANSIColor.reset(" |"))
|
175
186
|
@io.flush
|
176
187
|
end
|
177
188
|
|
178
189
|
private
|
190
|
+
|
191
|
+
def cell_prefix(status)
|
192
|
+
@prefixes[status]
|
193
|
+
end
|
179
194
|
|
180
195
|
def print_summary(features)
|
181
196
|
print_stats(features)
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Cucumber
|
2
|
+
module Formatter
|
3
|
+
class Steps < Ast::Visitor
|
4
|
+
|
5
|
+
def initialize(step_mother, io, options)
|
6
|
+
super(step_mother)
|
7
|
+
@io = io
|
8
|
+
@options = options
|
9
|
+
@step_definition_files = collect_steps(step_mother)
|
10
|
+
end
|
11
|
+
|
12
|
+
def visit_features(features)
|
13
|
+
print_summary
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def print_summary
|
19
|
+
count = 0
|
20
|
+
@step_definition_files.keys.sort.each do |step_definition_file|
|
21
|
+
@io.puts step_definition_file
|
22
|
+
|
23
|
+
sources = @step_definition_files[step_definition_file]
|
24
|
+
source_indent = source_indent(sources)
|
25
|
+
sources.sort.each do |file_colon_line, regexp|
|
26
|
+
@io.print "#{regexp}".indent(2)
|
27
|
+
@io.print " # #{file_colon_line}".indent(source_indent - regexp.size)
|
28
|
+
@io.puts
|
29
|
+
end
|
30
|
+
@io.puts
|
31
|
+
count += sources.size
|
32
|
+
end
|
33
|
+
@io.puts "#{count} step definition(s) in #{@step_definition_files.size} source file(s)."
|
34
|
+
end
|
35
|
+
|
36
|
+
def collect_steps(step_mother)
|
37
|
+
step_mother.step_definitions.inject({}) do |step_definitions, step_definition|
|
38
|
+
step_definitions[step_definition.file] ||= []
|
39
|
+
step_definitions[step_definition.file] << [ step_definition.file_colon_line, step_definition.regexp.inspect ]
|
40
|
+
step_definitions
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def source_indent(sources)
|
45
|
+
sources.map { |file_colon_line, regexp| regexp.size }.max + 1
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|