cucumber 7.1.0 → 8.0.0.rc.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +79 -1
- data/CONTRIBUTING.md +2 -6
- data/README.md +4 -7
- data/lib/autotest/cucumber_mixin.rb +5 -2
- data/lib/autotest/discover.rb +3 -2
- data/lib/cucumber/cli/configuration.rb +4 -1
- data/lib/cucumber/cli/main.rb +4 -3
- data/lib/cucumber/cli/options.rb +8 -2
- data/lib/cucumber/cli/profile_loader.rb +1 -5
- data/lib/cucumber/cli/rerun_file.rb +1 -1
- data/lib/cucumber/configuration.rb +5 -4
- data/lib/cucumber/constantize.rb +1 -1
- data/lib/cucumber/deprecate.rb +2 -1
- data/lib/cucumber/errors.rb +1 -1
- data/lib/cucumber/events/hook_test_step_created.rb +1 -2
- data/lib/cucumber/events/step_activated.rb +0 -6
- data/lib/cucumber/events/step_definition_registered.rb +0 -5
- data/lib/cucumber/events/test_case_created.rb +1 -2
- data/lib/cucumber/events/test_run_finished.rb +2 -1
- data/lib/cucumber/events/test_step_created.rb +1 -2
- data/lib/cucumber/events/undefined_parameter_type.rb +1 -2
- data/lib/cucumber/events.rb +1 -1
- data/lib/cucumber/file_specs.rb +2 -1
- data/lib/cucumber/filters/activate_steps.rb +1 -0
- data/lib/cucumber/filters/tag_limits/verifier.rb +1 -3
- data/lib/cucumber/filters/tag_limits.rb +1 -3
- data/lib/cucumber/formatter/ansicolor.rb +63 -63
- data/lib/cucumber/formatter/ast_lookup.rb +2 -2
- data/lib/cucumber/formatter/backtrace_filter.rb +1 -1
- data/lib/cucumber/formatter/console.rb +10 -2
- data/lib/cucumber/formatter/console_issues.rb +6 -1
- data/lib/cucumber/formatter/duration_extractor.rb +1 -0
- data/lib/cucumber/formatter/errors.rb +1 -0
- data/lib/cucumber/formatter/fanout.rb +1 -1
- data/lib/cucumber/formatter/http_io.rb +6 -1
- data/lib/cucumber/formatter/ignore_missing_messages.rb +1 -1
- data/lib/cucumber/formatter/io.rb +3 -1
- data/lib/cucumber/formatter/json.rb +8 -6
- data/lib/cucumber/formatter/junit.rb +6 -3
- data/lib/cucumber/formatter/message_builder.rb +3 -2
- data/lib/cucumber/formatter/pretty.rb +15 -5
- data/lib/cucumber/formatter/progress.rb +1 -0
- data/lib/cucumber/formatter/query/hook_by_test_step.rb +1 -0
- data/lib/cucumber/formatter/query/test_case_started_by_test_case.rb +2 -0
- data/lib/cucumber/formatter/rerun.rb +2 -0
- data/lib/cucumber/formatter/summary.rb +1 -0
- data/lib/cucumber/formatter/unicode.rb +4 -4
- data/lib/cucumber/formatter/usage.rb +3 -3
- data/lib/cucumber/gherkin/data_table_parser.rb +1 -0
- data/lib/cucumber/gherkin/formatter/ansi_escapes.rb +2 -2
- data/lib/cucumber/glue/dsl.rb +4 -9
- data/lib/cucumber/glue/hook.rb +2 -1
- data/lib/cucumber/glue/invoke_in_world.rb +4 -4
- data/lib/cucumber/glue/proto_world.rb +10 -9
- data/lib/cucumber/glue/registry_and_more.rb +4 -18
- data/lib/cucumber/glue/step_definition.rb +6 -3
- data/lib/cucumber/hooks.rb +1 -0
- data/lib/cucumber/multiline_argument/data_table/diff_matrices.rb +2 -1
- data/lib/cucumber/multiline_argument/data_table.rb +58 -71
- data/lib/cucumber/platform.rb +2 -2
- data/lib/cucumber/rake/task.rb +10 -7
- data/lib/cucumber/rspec/disable_option_parser.rb +6 -3
- data/lib/cucumber/running_test_case.rb +1 -0
- data/lib/cucumber/runtime/meta_message_builder.rb +106 -0
- data/lib/cucumber/runtime/support_code.rb +3 -0
- data/lib/cucumber/runtime/user_interface.rb +5 -4
- data/lib/cucumber/runtime.rb +21 -37
- data/lib/cucumber/step_match.rb +5 -3
- data/lib/cucumber/step_match_search.rb +3 -2
- data/lib/cucumber/term/ansicolor.rb +74 -50
- data/lib/cucumber/term/banner.rb +1 -0
- data/lib/cucumber/version +1 -1
- data/lib/cucumber.rb +2 -1
- data/lib/simplecov_setup.rb +1 -1
- metadata +74 -73
@@ -3,21 +3,48 @@
|
|
3
3
|
require 'cucumber/platform'
|
4
4
|
require 'cucumber/term/ansicolor'
|
5
5
|
|
6
|
-
Cucumber::Term::ANSIColor.coloring = false if
|
6
|
+
Cucumber::Term::ANSIColor.coloring = false if !$stdout.tty? && !ENV.key?('AUTOTEST')
|
7
7
|
|
8
8
|
module Cucumber
|
9
9
|
module Formatter
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
10
|
+
# This module allows to format cucumber related outputs using ANSI escape sequences.
|
11
|
+
#
|
12
|
+
# For example, it provides a `passed` method which returns the string with
|
13
|
+
# the ANSI escape sequence to format it green per default.
|
14
|
+
#
|
15
|
+
# To use this, include or extend it in your class.
|
16
|
+
#
|
17
|
+
# Example:
|
18
|
+
#
|
19
|
+
# require 'cucumber/formatter/ansicolor'
|
20
|
+
#
|
21
|
+
# class MyFormatter
|
22
|
+
# extend Cucumber::Term::ANSIColor
|
23
|
+
#
|
24
|
+
# def on_test_step_finished(event)
|
25
|
+
# $stdout.puts undefined(event.test_step) if event.result.undefined?
|
26
|
+
# $stdout.puts passed(event.test_step) if event.result.passed?
|
27
|
+
# end
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# This module also allows the user to customize the format of cucumber outputs
|
31
|
+
# using environment variables.
|
32
|
+
#
|
33
|
+
# For instance, if your shell has a black background and a green font (like the
|
34
|
+
# "Homebrew" settings for OS X' Terminal.app), you may want to override passed
|
35
|
+
# steps to be white instead of green.
|
36
|
+
#
|
37
|
+
# Example:
|
38
|
+
#
|
39
|
+
# export CUCUMBER_COLORS="passed=white,bold:passed_param=white,bold,underline"
|
15
40
|
#
|
16
41
|
# The colours that you can change are:
|
17
42
|
#
|
18
43
|
# * <tt>undefined</tt> - defaults to <tt>yellow</tt>
|
19
44
|
# * <tt>pending</tt> - defaults to <tt>yellow</tt>
|
20
45
|
# * <tt>pending_param</tt> - defaults to <tt>yellow,bold</tt>
|
46
|
+
# * <tt>flaky</tt> - defaults to <tt>yellow</tt>
|
47
|
+
# * <tt>flaky_param</tt> - defaults to <tt>yellow,bold</tt>
|
21
48
|
# * <tt>failed</tt> - defaults to <tt>red</tt>
|
22
49
|
# * <tt>failed_param</tt> - defaults to <tt>red,bold</tt>
|
23
50
|
# * <tt>passed</tt> - defaults to <tt>green</tt>
|
@@ -29,26 +56,18 @@ module Cucumber
|
|
29
56
|
# * <tt>comment</tt> - defaults to <tt>grey</tt>
|
30
57
|
# * <tt>tag</tt> - defaults to <tt>cyan</tt>
|
31
58
|
#
|
32
|
-
# For instance, if your shell has a black background and a green font (like the
|
33
|
-
# "Homebrew" settings for OS X' Terminal.app), you may want to override passed
|
34
|
-
# steps to be white instead of green.
|
35
|
-
#
|
36
|
-
# Although not listed, you can also use <tt>grey</tt>.
|
37
|
-
#
|
38
|
-
# Examples: (On Windows, use SET instead of export.)
|
39
|
-
#
|
40
|
-
# export CUCUMBER_COLORS="passed=white"
|
41
|
-
# export CUCUMBER_COLORS="passed=white,bold:passed_param=white,bold,underline"
|
42
|
-
#
|
43
59
|
# To see what colours and effects are available, just run this in your shell:
|
44
60
|
#
|
45
|
-
# ruby -e "require 'rubygems'; require 'term/ansicolor'; puts Cucumber::Term::ANSIColor.attributes"
|
61
|
+
# ruby -e "require 'rubygems'; require 'cucumber/term/ansicolor'; puts Cucumber::Term::ANSIColor.attributes"
|
46
62
|
#
|
47
63
|
module ANSIColor
|
48
64
|
include Cucumber::Term::ANSIColor
|
49
65
|
|
66
|
+
# :stopdoc:
|
50
67
|
ALIASES = Hash.new do |h, k|
|
51
|
-
|
68
|
+
next unless k.to_s =~ /(.*)_param/
|
69
|
+
|
70
|
+
"#{h[Regexp.last_match(1)]},bold"
|
52
71
|
end.merge(
|
53
72
|
'undefined' => 'yellow',
|
54
73
|
'pending' => 'yellow',
|
@@ -60,15 +79,22 @@ module Cucumber
|
|
60
79
|
'comment' => 'grey',
|
61
80
|
'tag' => 'cyan'
|
62
81
|
)
|
82
|
+
# :startdoc:
|
63
83
|
|
64
|
-
|
65
|
-
|
84
|
+
# Apply the custom color scheme
|
85
|
+
#
|
86
|
+
# example:
|
87
|
+
#
|
88
|
+
# apply_custom_colors('passed=white')
|
89
|
+
def apply_custom_colors(colors)
|
90
|
+
colors.split(':').each do |pair|
|
66
91
|
a = pair.split('=')
|
67
92
|
ALIASES[a[0]] = a[1]
|
68
93
|
end
|
69
94
|
end
|
95
|
+
apply_custom_colors(ENV['CUCUMBER_COLORS']) if ENV['CUCUMBER_COLORS']
|
70
96
|
|
71
|
-
#
|
97
|
+
# Define the color-named methods required by Term::ANSIColor.
|
72
98
|
#
|
73
99
|
# Examples:
|
74
100
|
#
|
@@ -80,53 +106,18 @@ module Cucumber
|
|
80
106
|
# red(bold(string, &proc)) + red
|
81
107
|
# end
|
82
108
|
ALIASES.each_key do |method_name|
|
83
|
-
next if method_name
|
84
|
-
code = <<-COLOR
|
85
|
-
def #{method_name}(string=nil, &proc)
|
86
|
-
#{ALIASES[method_name].split(',').join('(') + '(string, &proc' + ')' * ALIASES[method_name].split(',').length}
|
87
|
-
end
|
88
|
-
# This resets the colour to the non-param colour
|
89
|
-
def #{method_name}_param(string=nil, &proc)
|
90
|
-
#{ALIASES[method_name + '_param'].split(',').join('(') + '(string, &proc' + ')' * ALIASES[method_name + '_param'].split(',').length} + #{ALIASES[method_name].split(',').join(' + ')}
|
91
|
-
end
|
92
|
-
COLOR
|
93
|
-
eval(code) # rubocop:disable Security/Eval
|
94
|
-
end
|
109
|
+
next if method_name.end_with?('_param')
|
95
110
|
|
96
|
-
|
97
|
-
|
98
|
-
require 'terminfo'
|
99
|
-
case TermInfo.default_object.tigetnum('colors')
|
100
|
-
when 0
|
101
|
-
raise "Your terminal doesn't support colours."
|
102
|
-
when 1
|
103
|
-
::Cucumber::Term::ANSIColor.coloring = false
|
104
|
-
alias_method :grey, :white
|
105
|
-
when 2..8
|
106
|
-
alias_method :grey, :white # rubocop:disable Lint/DuplicateMethods
|
107
|
-
else
|
108
|
-
define_real_grey
|
109
|
-
end
|
110
|
-
rescue Exception => e # rubocop:disable Lint/RescueException
|
111
|
-
if e.class.name == 'TermInfo::TermInfoError'
|
112
|
-
STDERR.puts '*** WARNING ***'
|
113
|
-
STDERR.puts "You have the genki-ruby-terminfo gem installed, but you haven't set your TERM variable."
|
114
|
-
STDERR.puts 'Try setting it to TERM=xterm-256color to get grey colour in output.'
|
115
|
-
STDERR.puts "\n"
|
116
|
-
alias_method :grey, :white
|
117
|
-
else
|
118
|
-
define_real_grey
|
111
|
+
define_method(method_name) do |text = nil, &proc|
|
112
|
+
apply_styles(ALIASES[method_name], text, &proc)
|
119
113
|
end
|
120
|
-
end
|
121
114
|
|
122
|
-
|
123
|
-
|
124
|
-
::Cucumber::Term::ANSIColor.coloring? ? "\e[90m#{string}\e[0m" : string
|
115
|
+
define_method("#{method_name}_param") do |text = nil, &proc|
|
116
|
+
apply_styles(ALIASES["#{method_name}_param"], text, &proc) + apply_styles(ALIASES[method_name])
|
125
117
|
end
|
126
118
|
end
|
127
119
|
|
128
|
-
|
129
|
-
|
120
|
+
# :stopdoc:
|
130
121
|
def cukes(n)
|
131
122
|
('(::) ' * n).strip
|
132
123
|
end
|
@@ -142,6 +133,15 @@ module Cucumber
|
|
142
133
|
def yellow_cukes(n)
|
143
134
|
blink(yellow(cukes(n)))
|
144
135
|
end
|
136
|
+
# :startdoc:
|
137
|
+
|
138
|
+
private
|
139
|
+
|
140
|
+
def apply_styles(styles, text = nil, &proc)
|
141
|
+
styles.split(',').reverse.reduce(text) do |result, method_name|
|
142
|
+
send(method_name, result, &proc)
|
143
|
+
end
|
144
|
+
end
|
145
145
|
end
|
146
146
|
end
|
147
147
|
end
|
@@ -45,11 +45,11 @@ module Cucumber
|
|
45
45
|
break
|
46
46
|
end
|
47
47
|
break if node.previous_node.nil?
|
48
|
+
|
48
49
|
node = node.previous_node
|
49
50
|
end
|
50
51
|
keyword = dialect.given_keywords.reject { |kw| kw == '* ' }[0] if keyword.nil?
|
51
|
-
|
52
|
-
keyword
|
52
|
+
Cucumber::Gherkin::I18n.code_keyword_for(keyword)
|
53
53
|
end
|
54
54
|
|
55
55
|
ScenarioSource = Struct.new(:type, :scenario)
|
@@ -33,7 +33,7 @@ module Cucumber
|
|
33
33
|
def exception
|
34
34
|
return @exception if ::Cucumber.use_full_backtrace
|
35
35
|
|
36
|
-
pwd_pattern = /#{::Regexp.escape(::Dir.pwd)}\//m
|
36
|
+
pwd_pattern = /#{::Regexp.escape(::Dir.pwd)}\//m
|
37
37
|
backtrace = @exception.backtrace.map { |line| line.gsub(pwd_pattern, './') }
|
38
38
|
|
39
39
|
filtered = (backtrace || []).reject do |line|
|
@@ -34,7 +34,7 @@ module Cucumber
|
|
34
34
|
|
35
35
|
def format_step(keyword, step_match, status, source_indent)
|
36
36
|
comment = if source_indent
|
37
|
-
c = indent(
|
37
|
+
c = indent("# #{step_match.location}", source_indent)
|
38
38
|
format_string(c, :comment)
|
39
39
|
else
|
40
40
|
''
|
@@ -109,7 +109,10 @@ module Cucumber
|
|
109
109
|
# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/10655
|
110
110
|
def linebreaks(msg, max)
|
111
111
|
return msg unless max && max > 0
|
112
|
-
|
112
|
+
|
113
|
+
msg.gsub(/.{1,#{max}}(?:\s|\Z)/) do
|
114
|
+
(Regexp.last_match(0) + 5.chr).gsub(/\n\005/, "\n").gsub(/\005/, "\n")
|
115
|
+
end.rstrip
|
113
116
|
end
|
114
117
|
|
115
118
|
def collect_snippet_data(test_step, ast_lookup)
|
@@ -150,6 +153,7 @@ module Cucumber
|
|
150
153
|
|
151
154
|
def print_passing_wip(config, passed_test_cases, ast_lookup)
|
152
155
|
return unless config.wip?
|
156
|
+
|
153
157
|
messages = passed_test_cases.map do |test_case|
|
154
158
|
scenario_source = ast_lookup.scenario_source(test_case)
|
155
159
|
keyword = scenario_source.type == :Scenario ? scenario_source.scenario.keyword : scenario_source.scenario_outline.keyword
|
@@ -170,6 +174,7 @@ module Cucumber
|
|
170
174
|
def attach(src, media_type)
|
171
175
|
return unless media_type == 'text/x.cucumber.log+plain'
|
172
176
|
return unless @io
|
177
|
+
|
173
178
|
@io.puts
|
174
179
|
@io.puts(format_string(src, :tag))
|
175
180
|
@io.flush
|
@@ -177,6 +182,7 @@ module Cucumber
|
|
177
182
|
|
178
183
|
def print_profile_information
|
179
184
|
return if @options[:skip_profile_information] || @options[:profiles].nil? || @options[:profiles].empty?
|
185
|
+
|
180
186
|
do_print_profile_information(@options[:profiles])
|
181
187
|
end
|
182
188
|
|
@@ -224,6 +230,7 @@ module Cucumber
|
|
224
230
|
key = keys.join('_').to_sym
|
225
231
|
fmt = FORMATS[key]
|
226
232
|
raise "No format for #{key.inspect}: #{FORMATS.inspect}" if fmt.nil?
|
233
|
+
|
227
234
|
fmt
|
228
235
|
end
|
229
236
|
|
@@ -246,6 +253,7 @@ module Cucumber
|
|
246
253
|
|
247
254
|
class SnippetData
|
248
255
|
attr_reader :actual_keyword, :step
|
256
|
+
|
249
257
|
def initialize(actual_keyword, step)
|
250
258
|
@actual_keyword = actual_keyword
|
251
259
|
@step = step
|
@@ -23,6 +23,7 @@ module Cucumber
|
|
23
23
|
|
24
24
|
def to_s
|
25
25
|
return if @issues.empty?
|
26
|
+
|
26
27
|
result = Core::Test::Result::TYPES.map { |type| scenario_listing(type, @issues[type]) }
|
27
28
|
result.flatten.join("\n")
|
28
29
|
end
|
@@ -35,6 +36,7 @@ module Cucumber
|
|
35
36
|
|
36
37
|
def scenario_listing(type, test_cases)
|
37
38
|
return [] if test_cases.empty?
|
39
|
+
|
38
40
|
[format_string("#{type_heading(type)} Scenarios:", type)] + test_cases.map do |test_case|
|
39
41
|
scenario_source = @ast_lookup.scenario_source(test_case)
|
40
42
|
keyword = scenario_source.type == :Scenario ? scenario_source.scenario.keyword : scenario_source.scenario_outline.keyword
|
@@ -54,7 +56,10 @@ module Cucumber
|
|
54
56
|
|
55
57
|
def profiles_string
|
56
58
|
return if @config.custom_profiles.empty?
|
57
|
-
|
59
|
+
|
60
|
+
profiles = @config.custom_profiles.map { |profile| "-p #{profile}" }.join(' ')
|
61
|
+
|
62
|
+
"#{profiles} "
|
58
63
|
end
|
59
64
|
end
|
60
65
|
end
|
@@ -21,7 +21,7 @@ module Cucumber
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def respond_to_missing?(name, include_private = false)
|
24
|
-
recipients.any? { |recipient| recipient.respond_to?(name, include_private) }
|
24
|
+
recipients.any? { |recipient| recipient.respond_to?(name, include_private) } || super(name, include_private)
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
@@ -35,6 +35,7 @@ module Cucumber
|
|
35
35
|
headers = headers.merge(parse_header(header_arg))
|
36
36
|
else
|
37
37
|
raise StandardError, "#{options} was not a valid curl command. Can't set url to #{arg} it is already set to #{url}" if url
|
38
|
+
|
38
39
|
url = arg
|
39
40
|
end
|
40
41
|
end
|
@@ -49,12 +50,14 @@ module Cucumber
|
|
49
50
|
|
50
51
|
def self.remove_arg_for(args, arg)
|
51
52
|
return args.shift unless args.empty?
|
53
|
+
|
52
54
|
raise StandardError, "Missing argument for #{arg}"
|
53
55
|
end
|
54
56
|
|
55
57
|
def self.parse_header(header_arg)
|
56
58
|
parts = header_arg.split(':', 2)
|
57
59
|
raise StandardError, "#{header_arg} was not a valid header" unless parts.length == 2
|
60
|
+
|
58
61
|
{ parts[0].strip => parts[1].strip }
|
59
62
|
end
|
60
63
|
end
|
@@ -76,6 +79,7 @@ module Cucumber
|
|
76
79
|
@reporter.report(response.body)
|
77
80
|
@write_io.close
|
78
81
|
return if response.is_a?(Net::HTTPSuccess) || response.is_a?(Net::HTTPRedirection)
|
82
|
+
|
79
83
|
raise StandardError, "request to #{uri} failed with status #{response.code}"
|
80
84
|
end
|
81
85
|
|
@@ -98,6 +102,7 @@ module Cucumber
|
|
98
102
|
http = build_client(uri, @https_verify_mode)
|
99
103
|
|
100
104
|
raise StandardError, "request to #{uri} failed (too many redirections)" if attempt <= 0
|
105
|
+
|
101
106
|
req = build_request(
|
102
107
|
uri,
|
103
108
|
method,
|
@@ -126,7 +131,7 @@ module Cucumber
|
|
126
131
|
end
|
127
132
|
|
128
133
|
def build_request(uri, method, headers)
|
129
|
-
method_class_name = "#{method[0].upcase}#{method[1
|
134
|
+
method_class_name = "#{method[0].upcase}#{method[1..].downcase}"
|
130
135
|
req = Net::HTTP.const_get(method_class_name).new(uri)
|
131
136
|
headers.each do |header, value|
|
132
137
|
req[header] = value
|
@@ -57,19 +57,21 @@ module Cucumber
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def url?(path_or_url_or_io)
|
60
|
-
path_or_url_or_io.match(
|
60
|
+
path_or_url_or_io.match(/^https?:\/\//)
|
61
61
|
end
|
62
62
|
|
63
63
|
def ensure_file(path, name)
|
64
64
|
raise "You *must* specify --out FILE for the #{name} formatter" unless String == path.class
|
65
65
|
raise "I can't write #{name} to a directory - it has to be a file" if File.directory?(path)
|
66
66
|
raise "I can't write #{name} to a file in the non-existing directory #{File.dirname(path)}" unless File.directory?(File.dirname(path))
|
67
|
+
|
67
68
|
ensure_io(path, nil)
|
68
69
|
end
|
69
70
|
|
70
71
|
def ensure_dir(path, name)
|
71
72
|
raise "You *must* specify --out DIR for the #{name} formatter" unless String == path.class
|
72
73
|
raise "I can't write #{name} reports to a file - it has to be a directory" if File.file?(path)
|
74
|
+
|
73
75
|
FileUtils.mkdir_p(path) unless File.directory?(path)
|
74
76
|
File.absolute_path path
|
75
77
|
end
|
@@ -68,6 +68,7 @@ module Cucumber
|
|
68
68
|
test_step, result = *event.attributes
|
69
69
|
result = result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter)
|
70
70
|
return if internal_hook?(test_step)
|
71
|
+
|
71
72
|
add_match_and_result(test_step, result)
|
72
73
|
@any_step_failed = true if result.failed?
|
73
74
|
end
|
@@ -81,7 +82,7 @@ module Cucumber
|
|
81
82
|
end
|
82
83
|
|
83
84
|
def on_test_run_finished(_event)
|
84
|
-
@io.write(JSON.
|
85
|
+
@io.write(JSON.pretty_generate(@feature_hashes))
|
85
86
|
end
|
86
87
|
|
87
88
|
def attach(src, mime_type)
|
@@ -105,7 +106,7 @@ module Cucumber
|
|
105
106
|
end
|
106
107
|
|
107
108
|
def first_step_after_background?(test_step)
|
108
|
-
@in_background && test_step.location.lines.max >= @test_case_hash[:line]
|
109
|
+
@in_background && test_step.location.file == @feature_hash[:uri] && test_step.location.lines.max >= @test_case_hash[:line]
|
109
110
|
end
|
110
111
|
|
111
112
|
def internal_hook?(test_step)
|
@@ -133,7 +134,7 @@ module Cucumber
|
|
133
134
|
when 'AfterStep hook'
|
134
135
|
after_step_hooks
|
135
136
|
else
|
136
|
-
raise
|
137
|
+
raise "Unknown hook type #{hook_step}"
|
137
138
|
end
|
138
139
|
end
|
139
140
|
|
@@ -175,15 +176,15 @@ module Cucumber
|
|
175
176
|
name: test_step.text,
|
176
177
|
line: test_step.location.lines.min
|
177
178
|
}
|
178
|
-
step_hash[:doc_string] = create_doc_string_hash(step_source.doc_string) unless step_source.doc_string.nil?
|
179
|
+
step_hash[:doc_string] = create_doc_string_hash(step_source.doc_string, test_step.multiline_arg.content) unless step_source.doc_string.nil?
|
179
180
|
step_hash[:rows] = create_data_table_value(step_source.data_table) unless step_source.data_table.nil?
|
180
181
|
step_hash
|
181
182
|
end
|
182
183
|
|
183
|
-
def create_doc_string_hash(doc_string)
|
184
|
+
def create_doc_string_hash(doc_string, doc_string_content)
|
184
185
|
content_type = doc_string.media_type || ''
|
185
186
|
{
|
186
|
-
value:
|
187
|
+
value: doc_string_content,
|
187
188
|
content_type: content_type,
|
188
189
|
line: doc_string.location.line
|
189
190
|
}
|
@@ -259,6 +260,7 @@ module Cucumber
|
|
259
260
|
line: feature.location.line
|
260
261
|
}
|
261
262
|
return if feature.tags.empty?
|
263
|
+
|
262
264
|
@feature_hash[:tags] = create_tags_array_from_hash_array(feature.tags)
|
263
265
|
end
|
264
266
|
|
@@ -84,6 +84,7 @@ module Cucumber
|
|
84
84
|
uri = test_case.location.file
|
85
85
|
feature = @ast_lookup.gherkin_document(uri).feature
|
86
86
|
raise UnNamedFeatureError, uri if feature.name.empty?
|
87
|
+
|
87
88
|
@current_feature_data = @features_data[uri]
|
88
89
|
@current_feature_data[:uri] = uri unless @current_feature_data[:uri]
|
89
90
|
@current_feature_data[:feature] = feature unless @current_feature_data[:feature]
|
@@ -111,6 +112,7 @@ module Cucumber
|
|
111
112
|
keyword = scenario_source.type == :Scenario ? scenario_source.scenario.keyword : scenario_source.scenario_outline.keyword
|
112
113
|
output = "#{keyword}: #{scenario}\n\n"
|
113
114
|
return output if result.ok?(@config.strict)
|
115
|
+
|
114
116
|
if scenario_source.type == :Scenario
|
115
117
|
if @failing_test_step
|
116
118
|
if @failing_test_step.hook?
|
@@ -125,7 +127,7 @@ module Cucumber
|
|
125
127
|
else
|
126
128
|
output += "Example row: #{row_name}\n"
|
127
129
|
end
|
128
|
-
output
|
130
|
+
"#{output}\nMessage:\n"
|
129
131
|
end
|
130
132
|
|
131
133
|
def build_testcase(result, scenario_designation, output)
|
@@ -191,7 +193,7 @@ module Cucumber
|
|
191
193
|
end
|
192
194
|
|
193
195
|
def basename(feature_file)
|
194
|
-
File.basename(feature_file.gsub(/[\\\/]/, '-'), '.feature')
|
196
|
+
File.basename(feature_file.gsub(/[\\\/]/, '-'), '.feature')
|
195
197
|
end
|
196
198
|
|
197
199
|
def write_file(feature_filename, data)
|
@@ -228,13 +230,14 @@ module Cucumber
|
|
228
230
|
end
|
229
231
|
|
230
232
|
def examples_table_row(row)
|
231
|
-
@row_name =
|
233
|
+
@row_name = "| #{row.cells.map(&:value).join(' | ')} |"
|
232
234
|
@name_suffix = " (outline example : #{@row_name})"
|
233
235
|
end
|
234
236
|
end
|
235
237
|
|
236
238
|
class ResultBuilder
|
237
239
|
attr_reader :test_case_duration
|
240
|
+
|
238
241
|
def initialize(result)
|
239
242
|
@test_case_duration = 0
|
240
243
|
result.describe_to(self)
|
@@ -226,10 +226,11 @@ module Cucumber
|
|
226
226
|
output_envelope(message)
|
227
227
|
end
|
228
228
|
|
229
|
-
def on_test_run_finished(
|
229
|
+
def on_test_run_finished(event)
|
230
230
|
message = Cucumber::Messages::Envelope.new(
|
231
231
|
test_run_finished: Cucumber::Messages::TestRunFinished.new(
|
232
|
-
timestamp: time_to_timestamp(Time.now)
|
232
|
+
timestamp: time_to_timestamp(Time.now),
|
233
|
+
success: event.success
|
233
234
|
)
|
234
235
|
)
|
235
236
|
|
@@ -24,11 +24,9 @@ module Cucumber
|
|
24
24
|
include Console
|
25
25
|
include Io
|
26
26
|
include Cucumber::Gherkin::Formatter::Escaping
|
27
|
-
attr_reader :config, :options
|
27
|
+
attr_reader :config, :options, :current_feature_uri, :current_scenario_outline, :current_examples, :current_test_case, :in_scenario_outline, :print_background_steps
|
28
28
|
private :config, :options
|
29
|
-
attr_reader :current_feature_uri, :current_scenario_outline, :current_examples, :current_test_case
|
30
29
|
private :current_feature_uri, :current_scenario_outline, :current_examples, :current_test_case
|
31
|
-
attr_reader :in_scenario_outline, :print_background_steps
|
32
30
|
private :in_scenario_outline, :print_background_steps
|
33
31
|
|
34
32
|
def initialize(config)
|
@@ -105,16 +103,19 @@ module Cucumber
|
|
105
103
|
|
106
104
|
def on_test_step_started(event)
|
107
105
|
return if event.test_step.hook?
|
106
|
+
|
108
107
|
print_step_header(current_test_case) if first_step_after_printing_background_steps?(event.test_step)
|
109
108
|
end
|
110
109
|
|
111
110
|
def on_test_step_finished(event)
|
112
111
|
collect_snippet_data(event.test_step, @ast_lookup) if event.result.undefined?
|
113
112
|
return if in_scenario_outline && !options[:expand]
|
113
|
+
|
114
114
|
exception_to_be_printed = find_exception_to_be_printed(event.result)
|
115
115
|
print_step_data(event.test_step, event.result) if print_step_data?(event, exception_to_be_printed)
|
116
116
|
print_step_output
|
117
117
|
return unless exception_to_be_printed
|
118
|
+
|
118
119
|
print_exception(exception_to_be_printed, event.result.to_sym, 6)
|
119
120
|
@exceptions << exception_to_be_printed
|
120
121
|
end
|
@@ -127,6 +128,7 @@ module Cucumber
|
|
127
128
|
else
|
128
129
|
exception_to_be_printed = find_exception_to_be_printed(event.result)
|
129
130
|
return unless exception_to_be_printed
|
131
|
+
|
130
132
|
print_exception(exception_to_be_printed, event.result.to_sym, 6)
|
131
133
|
@exceptions << exception_to_be_printed
|
132
134
|
end
|
@@ -140,6 +142,7 @@ module Cucumber
|
|
140
142
|
|
141
143
|
def attach(src, media_type)
|
142
144
|
return unless media_type == 'text/x.cucumber.log+plain'
|
145
|
+
|
143
146
|
@test_step_output.push src
|
144
147
|
end
|
145
148
|
|
@@ -147,9 +150,11 @@ module Cucumber
|
|
147
150
|
|
148
151
|
def find_exception_to_be_printed(result)
|
149
152
|
return nil if result.ok?(options[:strict])
|
153
|
+
|
150
154
|
result = result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter)
|
151
155
|
exception = result.failed? ? result.exception : result
|
152
156
|
return nil if @exceptions.include?(exception)
|
157
|
+
|
153
158
|
exception
|
154
159
|
end
|
155
160
|
|
@@ -196,6 +201,7 @@ module Cucumber
|
|
196
201
|
def feature_has_background?
|
197
202
|
feature_children = gherkin_document.feature.children
|
198
203
|
return false if feature_children.empty?
|
204
|
+
|
199
205
|
!feature_children.first.background.nil?
|
200
206
|
end
|
201
207
|
|
@@ -239,6 +245,7 @@ module Cucumber
|
|
239
245
|
def first_step_after_printing_background_steps?(test_step)
|
240
246
|
return false unless print_background_steps
|
241
247
|
return false unless test_step.location.lines.max >= current_test_case.location.lines.max
|
248
|
+
|
242
249
|
@print_background_steps = false
|
243
250
|
true
|
244
251
|
end
|
@@ -262,7 +269,8 @@ module Cucumber
|
|
262
269
|
def print_comments(up_to_line, indent_amount)
|
263
270
|
comments = gherkin_document.comments
|
264
271
|
return if comments.empty? || comments.length <= @next_comment_to_be_printed
|
265
|
-
|
272
|
+
|
273
|
+
comments[@next_comment_to_be_printed..].each do |comment|
|
266
274
|
if comment.location.line <= up_to_line
|
267
275
|
@io.puts(indent(format_string(comment.text.strip, :comment), indent_amount))
|
268
276
|
@next_comment_to_be_printed += 1
|
@@ -294,6 +302,7 @@ module Cucumber
|
|
294
302
|
|
295
303
|
def print_description(description)
|
296
304
|
return unless description
|
305
|
+
|
297
306
|
description.split("\n").each do |line|
|
298
307
|
@io.puts(line)
|
299
308
|
end
|
@@ -398,6 +407,7 @@ module Cucumber
|
|
398
407
|
end
|
399
408
|
@io.puts
|
400
409
|
next if options[:no_multiline]
|
410
|
+
|
401
411
|
print_doc_string(step.doc_string.content, :skipped, 6) unless step.doc_string.nil?
|
402
412
|
print_data_table(step.data_table, :skipped, 6) unless step.data_table.nil?
|
403
413
|
end
|
@@ -445,7 +455,7 @@ module Cucumber
|
|
445
455
|
language = ::Gherkin::Dialect.for(language_code)
|
446
456
|
scenario_keyword = language.scenario_keywords[0]
|
447
457
|
row = scenario_source(test_case).row
|
448
|
-
expanded_name =
|
458
|
+
expanded_name = "| #{row.cells.map(&:value).join(' | ')} |"
|
449
459
|
@source_indent = calculate_source_indent_for_expanded_test_case(test_case, scenario_keyword, expanded_name)
|
450
460
|
@io.puts
|
451
461
|
print_keyword_name(scenario_keyword, expanded_name, 6, test_case.location)
|
@@ -58,6 +58,7 @@ module Cucumber
|
|
58
58
|
progress(result.to_sym) if !test_step.hook? || result.failed?
|
59
59
|
|
60
60
|
return if test_step.hook?
|
61
|
+
|
61
62
|
collect_snippet_data(test_step, @ast_lookup) if result.undefined?
|
62
63
|
@pending_step_matches << @matches[test_step.to_s] if result.pending?
|
63
64
|
@failed_results << result if result.failed?
|
@@ -13,6 +13,7 @@ module Cucumber
|
|
13
13
|
|
14
14
|
def hook_id(test_step)
|
15
15
|
return @hook_id_by_test_step_id[test_step.id] if @hook_id_by_test_step_id.key?(test_step.id)
|
16
|
+
|
16
17
|
raise TestStepUnknownError, "No hook found for #{test_step.id} }. Known: #{@hook_id_by_test_step_id.keys}"
|
17
18
|
end
|
18
19
|
|