square-cucumber 0.3.12.2 → 0.3.93.1
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 +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
|