cucumber 8.0.0 → 9.2.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.
- checksums.yaml +4 -4
- data/README.md +14 -23
- data/VERSION +1 -0
- data/lib/cucumber/cli/main.rb +1 -1
- data/lib/cucumber/cli/options.rb +66 -66
- data/lib/cucumber/cli/profile_loader.rb +5 -5
- data/lib/cucumber/configuration.rb +7 -2
- data/lib/cucumber/deprecate.rb +6 -47
- data/lib/cucumber/errors.rb +2 -1
- data/lib/cucumber/events/envelope.rb +2 -0
- data/lib/cucumber/events/gherkin_source_parsed.rb +2 -0
- data/lib/cucumber/events/gherkin_source_read.rb +2 -0
- data/lib/cucumber/events/test_case_finished.rb +2 -0
- data/lib/cucumber/events/test_case_started.rb +2 -0
- data/lib/cucumber/events/test_step_finished.rb +2 -0
- data/lib/cucumber/events/test_step_started.rb +2 -0
- data/lib/cucumber/events/undefined_parameter_type.rb +2 -0
- data/lib/cucumber/file_specs.rb +1 -1
- data/lib/cucumber/filters/retry.rb +20 -1
- data/lib/cucumber/formatter/ansicolor.rb +19 -27
- data/lib/cucumber/formatter/ast_lookup.rb +14 -6
- data/lib/cucumber/formatter/console.rb +16 -14
- data/lib/cucumber/formatter/console_counts.rb +3 -1
- data/lib/cucumber/formatter/console_issues.rb +4 -2
- data/lib/cucumber/formatter/curl_option_parser.rb +49 -0
- data/lib/cucumber/formatter/errors.rb +2 -0
- data/lib/cucumber/formatter/fail_fast.rb +1 -1
- data/lib/cucumber/formatter/html.rb +2 -0
- data/lib/cucumber/formatter/http_io.rb +10 -142
- data/lib/cucumber/formatter/io_http_buffer.rb +88 -0
- data/lib/cucumber/formatter/json.rb +2 -6
- data/lib/cucumber/formatter/junit.rb +4 -4
- data/lib/cucumber/formatter/message_builder.rb +21 -6
- data/lib/cucumber/formatter/pretty.rb +9 -5
- data/lib/cucumber/formatter/publish_banner_printer.rb +0 -2
- data/lib/cucumber/formatter/query/hook_by_test_step.rb +2 -0
- data/lib/cucumber/formatter/query/pickle_by_test.rb +2 -0
- data/lib/cucumber/formatter/query/pickle_step_by_test_step.rb +2 -0
- data/lib/cucumber/formatter/query/step_definitions_by_test_step.rb +2 -0
- data/lib/cucumber/formatter/query/test_case_started_by_test_case.rb +2 -0
- data/lib/cucumber/formatter/rerun.rb +3 -3
- data/lib/cucumber/formatter/unicode.rb +3 -3
- data/lib/cucumber/formatter/url_reporter.rb +3 -1
- data/lib/cucumber/gherkin/formatter/ansi_escapes.rb +23 -25
- data/lib/cucumber/glue/invoke_in_world.rb +2 -2
- data/lib/cucumber/glue/proto_world.rb +20 -25
- data/lib/cucumber/glue/registry_and_more.rb +9 -5
- data/lib/cucumber/glue/snippet.rb +4 -2
- data/lib/cucumber/glue/world_factory.rb +2 -0
- data/lib/cucumber/multiline_argument/data_table/diff_matrices.rb +2 -0
- data/lib/cucumber/multiline_argument/data_table.rb +37 -36
- data/lib/cucumber/platform.rb +11 -16
- data/lib/cucumber/rake/task.rb +2 -6
- data/lib/cucumber/running_test_case.rb +1 -1
- data/lib/cucumber/runtime/for_programming_languages.rb +1 -2
- data/lib/cucumber/runtime/meta_message_builder.rb +4 -2
- data/lib/cucumber/runtime/user_interface.rb +2 -2
- data/lib/cucumber/runtime.rb +5 -5
- data/lib/cucumber/step_match.rb +1 -1
- data/lib/cucumber/term/ansicolor.rb +1 -1
- data/lib/cucumber/term/banner.rb +2 -0
- metadata +86 -242
- data/CHANGELOG.md +0 -3231
- data/CONTRIBUTING.md +0 -246
- data/lib/autotest/cucumber.rb +0 -8
- data/lib/autotest/cucumber_mixin.rb +0 -133
- data/lib/autotest/cucumber_rails.rb +0 -8
- data/lib/autotest/cucumber_rails_rspec.rb +0 -8
- data/lib/autotest/cucumber_rails_rspec2.rb +0 -8
- data/lib/autotest/cucumber_rspec.rb +0 -8
- data/lib/autotest/cucumber_rspec2.rb +0 -8
- data/lib/autotest/discover.rb +0 -14
- data/lib/cucumber/version +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f6b3938bfcfa22aba558e5ea44825ed2ee19e9c7d26c0a5613f7998095d5c287
|
4
|
+
data.tar.gz: edc19d118e96175085722756b873b48c2ec319663edeedd81de027a48ac7d66c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f1338b46610ebd6fff711400c0160294f451e3c98558ca155712d07040a06f9a55fcb99c6e9cd00e5df248a415928b2a7c70da76a7badcc461b832ec464b66a8
|
7
|
+
data.tar.gz: b1c00b91c1055daf161482ba19b4cfa60089140af3212f9a1d71ef9a692d4dabd43fdb5fa3fa0bfcbcce018053f0ebc5460f1449bfaa32fa6afb0f532156c9d1
|
data/README.md
CHANGED
@@ -1,15 +1,11 @@
|
|
1
|
-
<
|
2
|
-
<img src="./.github/img/cucumber-open-logo.png" alt="Cucumber Open - Supported by Smartbear" width="428" />
|
3
|
-
</p>
|
1
|
+
<img src="docs/img/cucumber-open-logo.png" alt="Cucumber Open - Supported by Smartbear" width="428" />
|
4
2
|
|
5
3
|
# Cucumber
|
6
4
|
|
7
5
|
[](https://vshymanskyy.github.io/StandWithUkraine)
|
8
6
|
[](https://opencollective.com/cucumber)
|
9
7
|
[](https://opencollective.com/cucumber)
|
10
|
-
[](https://oselvar.com/github/cucumber/oselvar-github-metrics/main/cucumber/cucumber-ruby)
|
12
|
-
[](https://github.com/cucumber/cucumber-ruby/actions/workflows/cucumber-ruby.yml)
|
8
|
+
[](https://github.com/cucumber/cucumber-ruby/actions/workflows/test.yaml)
|
13
9
|
[](https://codeclimate.com/github/cucumber/cucumber-ruby)
|
14
10
|
[](https://coveralls.io/r/cucumber/cucumber-ruby?branch=main)
|
15
11
|
|
@@ -18,9 +14,7 @@ written in plain language, they can be read by anyone on your team. Because they
|
|
18
14
|
read by anyone, you can use them to help improve communication, collaboration and trust on
|
19
15
|
your team.
|
20
16
|
|
21
|
-
<
|
22
|
-
<img src="./.github/img/gherkin-example.png" alt="Cucumber Gherkin Example" width="728" />
|
23
|
-
</p>
|
17
|
+
<img src="docs/img/gherkin-example.png" alt="Cucumber Gherkin Example" width="728" />
|
24
18
|
|
25
19
|
This is the Ruby implementation of Cucumber. Cucumber is also available for [JavaScript](https://github.com/cucumber/cucumber-js),
|
26
20
|
[Java](https://github.com/cucumber/cucumber-jvm), and a lot of other languages. You can find a list of implementations here: https://cucumber.io/docs/installation/.
|
@@ -51,19 +45,16 @@ Later in this document, bundler is considered being used so all commands are usi
|
|
51
45
|
|
52
46
|
### Supported platforms
|
53
47
|
|
48
|
+
- Ruby 3.2
|
54
49
|
- Ruby 3.1
|
55
50
|
- Ruby 3.0
|
56
51
|
- Ruby 2.7
|
57
|
-
- Ruby 2.6
|
58
52
|
- TruffleRuby 22.0.0+
|
59
|
-
- JRuby (with [some limitations](https://github.com/cucumber/cucumber-ruby/blob/main/docs/jruby-limitations.md))
|
60
|
-
- 9.3 >= 9.3.1 (there is a known issue with JRuby 9.3.0. More info can
|
61
|
-
be found in the [PR#1571](https://github.com/cucumber/cucumber-ruby/pull/1571).)
|
53
|
+
- JRuby 9.4+ (with [some limitations](https://github.com/cucumber/cucumber-ruby/blob/main/docs/jruby-limitations.md))
|
62
54
|
|
63
55
|
### Ruby on Rails
|
64
56
|
|
65
|
-
Using Ruby on Rails? You can use [cucumber-rails](https://github.com/cucumber/cucumber-rails)
|
66
|
-
to bring Cucumber into your Rails project.
|
57
|
+
Using Ruby on Rails? You can use [cucumber-rails](https://github.com/cucumber/cucumber-rails) to bring Cucumber into your Rails project.
|
67
58
|
|
68
59
|
## Usage
|
69
60
|
|
@@ -110,19 +101,20 @@ And a file named `steps.rb` in `features/step_definitions` with:
|
|
110
101
|
```ruby
|
111
102
|
# features/step_definitions/steps.rb
|
112
103
|
|
113
|
-
Given(
|
104
|
+
Given('this will pass') do
|
114
105
|
@this_will_pass = true
|
115
106
|
end
|
116
107
|
|
117
|
-
Given(
|
108
|
+
Given('this will fail') do
|
118
109
|
@this_will_pass = false
|
119
110
|
end
|
120
111
|
|
121
|
-
When(
|
112
|
+
When('I do an action') do
|
113
|
+
:no_op
|
122
114
|
end
|
123
115
|
|
124
116
|
Then("some results should be there") do
|
125
|
-
expect(@this_will_pass)
|
117
|
+
expect(@this_will_pass).to be true
|
126
118
|
end
|
127
119
|
```
|
128
120
|
|
@@ -136,9 +128,9 @@ To execute a single feature file:
|
|
136
128
|
|
137
129
|
To execute a single example, indicates the line of the name of the example:
|
138
130
|
|
139
|
-
$ bundle exec cucumber features/rule.feature:
|
131
|
+
$ bundle exec cucumber features/rule.feature:5
|
140
132
|
|
141
|
-
To summarize the results on the standard output, and
|
133
|
+
To summarize the results on the standard output, and generate a HTML report on disk:
|
142
134
|
|
143
135
|
$ bundle exec cucumber --format summary --format html --out report.html
|
144
136
|
|
@@ -146,8 +138,7 @@ For more command line options
|
|
146
138
|
|
147
139
|
$ bundle exec cucumber --help
|
148
140
|
|
149
|
-
You can also find documentation on the command line possibilities in
|
150
|
-
[features/docs/cli](features/docs/cli).
|
141
|
+
You can also find documentation on the command line possibilities in [features/docs/cli](features/docs/cli).
|
151
142
|
|
152
143
|
## Documentation and support
|
153
144
|
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
9.2.1
|
data/lib/cucumber/cli/main.rb
CHANGED
@@ -49,7 +49,7 @@ module Cucumber
|
|
49
49
|
rescue Errno::EACCES, Errno::ENOENT => e
|
50
50
|
@err.puts("#{e.message} (#{e.class})")
|
51
51
|
exit_unable_to_finish
|
52
|
-
rescue Exception => e
|
52
|
+
rescue Exception => e
|
53
53
|
@err.puts("#{e.message} (#{e.class})")
|
54
54
|
@err.puts(e.backtrace.join("\n"))
|
55
55
|
exit_unable_to_finish
|
data/lib/cucumber/cli/options.rb
CHANGED
@@ -12,26 +12,26 @@ module Cucumber
|
|
12
12
|
CUCUMBER_PUBLISH_URL = ENV['CUCUMBER_PUBLISH_URL'] || 'https://messages.cucumber.io/api/reports -X GET'
|
13
13
|
INDENT = ' ' * 53
|
14
14
|
BUILTIN_FORMATS = {
|
15
|
-
'pretty'
|
16
|
-
'progress'
|
17
|
-
'rerun'
|
18
|
-
'usage'
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
'stepdefs'
|
24
|
-
|
25
|
-
'junit'
|
26
|
-
|
27
|
-
'json'
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
'message'
|
33
|
-
'html'
|
34
|
-
'summary'
|
15
|
+
'pretty' => ['Cucumber::Formatter::Pretty', 'Prints the feature as is - in colours.'],
|
16
|
+
'progress' => ['Cucumber::Formatter::Progress', 'Prints one character per scenario.'],
|
17
|
+
'rerun' => ['Cucumber::Formatter::Rerun', 'Prints failing files with line numbers.'],
|
18
|
+
'usage' => ['Cucumber::Formatter::Usage', "Prints where step definitions are used.\n" \
|
19
|
+
"#{INDENT}The slowest step definitions (with duration) are\n" \
|
20
|
+
"#{INDENT}listed first. If --dry-run is used the duration\n" \
|
21
|
+
"#{INDENT}is not shown, and step definitions are sorted by\n" \
|
22
|
+
"#{INDENT}filename instead."],
|
23
|
+
'stepdefs' => ['Cucumber::Formatter::Stepdefs', "Prints All step definitions with their locations. Same as\n" \
|
24
|
+
"#{INDENT}the usage formatter, except that steps are not printed."],
|
25
|
+
'junit' => ['Cucumber::Formatter::Junit', "Generates a report similar to Ant+JUnit. Use\n" \
|
26
|
+
"#{INDENT}junit,fileattribute=true to include a file attribute."],
|
27
|
+
'json' => ['Cucumber::Formatter::Json', "Prints the feature as JSON.\n" \
|
28
|
+
"#{INDENT}The JSON format is in maintenance mode.\n" \
|
29
|
+
"#{INDENT}Please consider using the message formatter\n"\
|
30
|
+
"#{INDENT}with the standalone json-formatter\n" \
|
31
|
+
"#{INDENT}(https://github.com/cucumber/cucumber/tree/master/json-formatter)."],
|
32
|
+
'message' => ['Cucumber::Formatter::Message', 'Prints each message in NDJSON form, which can then be consumed by other tools.'],
|
33
|
+
'html' => ['Cucumber::Formatter::HTML', 'Outputs HTML report'],
|
34
|
+
'summary' => ['Cucumber::Formatter::Summary', 'Summary output of feature and scenarios']
|
35
35
|
}.freeze
|
36
36
|
max = BUILTIN_FORMATS.keys.map(&:length).max
|
37
37
|
FORMAT_HELP_MSG = [
|
@@ -50,20 +50,21 @@ module Cucumber
|
|
50
50
|
FORMAT_HELP = (BUILTIN_FORMATS.keys.sort.map do |key|
|
51
51
|
" #{key}#{' ' * (max - key.length)} : #{BUILTIN_FORMATS[key][1]}"
|
52
52
|
end) + FORMAT_HELP_MSG
|
53
|
-
PROFILE_SHORT_FLAG = '-p'
|
54
|
-
NO_PROFILE_SHORT_FLAG = '-P'
|
55
|
-
PROFILE_LONG_FLAG = '--profile'
|
56
|
-
NO_PROFILE_LONG_FLAG = '--no-profile'
|
57
|
-
FAIL_FAST_FLAG = '--fail-fast'
|
58
|
-
RETRY_FLAG = '--retry'
|
53
|
+
PROFILE_SHORT_FLAG = '-p'
|
54
|
+
NO_PROFILE_SHORT_FLAG = '-P'
|
55
|
+
PROFILE_LONG_FLAG = '--profile'
|
56
|
+
NO_PROFILE_LONG_FLAG = '--no-profile'
|
57
|
+
FAIL_FAST_FLAG = '--fail-fast'
|
58
|
+
RETRY_FLAG = '--retry'
|
59
|
+
RETRY_TOTAL_FLAG = '--retry-total'
|
59
60
|
OPTIONS_WITH_ARGS = [
|
60
61
|
'-r', '--require', '--i18n-keywords', '-f', '--format', '-o',
|
61
62
|
'--out', '-t', '--tags', '-n', '--name', '-e', '--exclude',
|
62
|
-
PROFILE_SHORT_FLAG, PROFILE_LONG_FLAG, RETRY_FLAG,
|
63
|
-
'--lines', '--port', '-I', '--snippet-type'
|
63
|
+
PROFILE_SHORT_FLAG, PROFILE_LONG_FLAG, RETRY_FLAG, RETRY_TOTAL_FLAG,
|
64
|
+
'-l', '--lines', '--port', '-I', '--snippet-type'
|
64
65
|
].freeze
|
65
66
|
ORDER_TYPES = %w[defined random].freeze
|
66
|
-
TAG_LIMIT_MATCHER = /(?<tag_name>@\w+):(?<limit>\d+)/x
|
67
|
+
TAG_LIMIT_MATCHER = /(?<tag_name>@\w+):(?<limit>\d+)/x.freeze
|
67
68
|
|
68
69
|
def self.parse(args, out_stream, error_stream, options = {})
|
69
70
|
new(out_stream, error_stream, options).parse!(args)
|
@@ -91,13 +92,13 @@ module Cucumber
|
|
91
92
|
@options[key] = value
|
92
93
|
end
|
93
94
|
|
94
|
-
def parse!(args)
|
95
|
+
def parse!(args)
|
95
96
|
@args = args
|
96
97
|
@expanded_args = @args.dup
|
97
98
|
|
98
99
|
@args.extend(::OptionParser::Arguable)
|
99
100
|
|
100
|
-
@args.options do |opts|
|
101
|
+
@args.options do |opts|
|
101
102
|
opts.banner = banner
|
102
103
|
opts.on('--publish', 'Publish a report to https://reports.cucumber.io') do
|
103
104
|
set_option :publish_enabled, true
|
@@ -108,16 +109,17 @@ module Cucumber
|
|
108
109
|
opts.on('-j DIR', '--jars DIR', 'Load all the jars under DIR') { |jars| load_jars(jars) } if Cucumber::JRUBY
|
109
110
|
|
110
111
|
opts.on("#{RETRY_FLAG} ATTEMPTS", *retry_msg) { |v| set_option :retry, v.to_i }
|
112
|
+
opts.on("#{RETRY_TOTAL_FLAG} TESTS", *retry_total_msg) { |v| set_option :retry_total, v.to_i }
|
111
113
|
opts.on('--i18n-languages', *i18n_languages_msg) { list_languages_and_exit }
|
112
114
|
opts.on('--i18n-keywords LANG', *i18n_keywords_msg) { |lang| language lang }
|
113
115
|
opts.on(FAIL_FAST_FLAG, 'Exit immediately following the first failing scenario') { set_option :fail_fast }
|
114
116
|
opts.on('-f FORMAT', '--format FORMAT', *format_msg, *FORMAT_HELP) do |v|
|
115
117
|
add_option :formats, [*parse_formats(v), @out_stream]
|
116
118
|
end
|
117
|
-
opts.on('--init', *init_msg) {
|
119
|
+
opts.on('--init', *init_msg) { initialize_project }
|
118
120
|
opts.on('-o', '--out [FILE|DIR|URL]', *out_msg) { |v| out_stream v }
|
119
|
-
opts.on('-t TAG_EXPRESSION', '--tags TAG_EXPRESSION', *tags_msg) { |v| add_tag
|
120
|
-
opts.on('-n NAME', '--name NAME', *name_msg) { |v| add_option
|
121
|
+
opts.on('-t TAG_EXPRESSION', '--tags TAG_EXPRESSION', *tags_msg) { |v| add_tag(v) }
|
122
|
+
opts.on('-n NAME', '--name NAME', *name_msg) { |v| add_option(:name_regexps, /#{v}/) }
|
121
123
|
opts.on('-e', '--exclude PATTERN', *exclude_msg) { |v| add_option :excludes, Regexp.new(v) }
|
122
124
|
opts.on(PROFILE_SHORT_FLAG, "#{PROFILE_LONG_FLAG} PROFILE", *profile_short_flag_msg) { |v| add_profile v }
|
123
125
|
opts.on(NO_PROFILE_SHORT_FLAG, NO_PROFILE_LONG_FLAG, *no_profile_short_flag_msg) { |_v| disable_profile_loading }
|
@@ -141,11 +143,11 @@ module Cucumber
|
|
141
143
|
opts.on('-x', '--expand', 'Expand Scenario Outline Tables in output.') { set_option :expand }
|
142
144
|
|
143
145
|
opts.on('--order TYPE[:SEED]', 'Run examples in the specified order. Available types:',
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
Specify SEED to reproduce the shuffling from a previous run.
|
148
|
-
|
146
|
+
*<<~TEXT.split("\n")) do |order|
|
147
|
+
[defined] Run scenarios in the order they were defined (default).
|
148
|
+
[random] Shuffle scenarios before running.
|
149
|
+
Specify SEED to reproduce the shuffling from a previous run.
|
150
|
+
e.g. --order random:5738
|
149
151
|
TEXT
|
150
152
|
@options[:order], @options[:seed] = *order.split(':')
|
151
153
|
raise "'#{@options[:order]}' is not a recognised order type. Please use one of #{ORDER_TYPES.join(', ')}." unless ORDER_TYPES.include?(@options[:order])
|
@@ -271,6 +273,13 @@ Specify SEED to reproduce the shuffling from a previous run.
|
|
271
273
|
['Specify the number of times to retry failing tests (default: 0)']
|
272
274
|
end
|
273
275
|
|
276
|
+
def retry_total_msg
|
277
|
+
[
|
278
|
+
'The total number of failing test after which retrying of tests is suspended.',
|
279
|
+
'Example: --retry-total 10 -> Will stop retrying tests after 10 failing tests.'
|
280
|
+
]
|
281
|
+
end
|
282
|
+
|
274
283
|
def name_msg
|
275
284
|
[
|
276
285
|
'Only execute the feature elements which match part of the given name.',
|
@@ -286,15 +295,15 @@ Specify SEED to reproduce the shuffling from a previous run.
|
|
286
295
|
]
|
287
296
|
end
|
288
297
|
|
289
|
-
def parse_formats(
|
290
|
-
formatter, *formatter_options =
|
291
|
-
options_hash = Hash[formatter_options.map { |
|
298
|
+
def parse_formats(value)
|
299
|
+
formatter, *formatter_options = value.split(',')
|
300
|
+
options_hash = Hash[formatter_options.map { |string| string.split('=') }]
|
292
301
|
[formatter, options_hash]
|
293
302
|
end
|
294
303
|
|
295
|
-
def out_stream(
|
304
|
+
def out_stream(value)
|
296
305
|
@options[:formats] << ['pretty', {}, nil] if @options[:formats].empty?
|
297
|
-
@options[:formats][-1][2] =
|
306
|
+
@options[:formats][-1][2] = value
|
298
307
|
end
|
299
308
|
|
300
309
|
def tags_msg
|
@@ -366,12 +375,12 @@ Specify SEED to reproduce the shuffling from a previous run.
|
|
366
375
|
].join("\n")
|
367
376
|
end
|
368
377
|
|
369
|
-
def require_files(
|
370
|
-
@options[:require] <<
|
371
|
-
return unless Cucumber::JRUBY && File.directory?(
|
378
|
+
def require_files(filenames)
|
379
|
+
@options[:require] << filenames
|
380
|
+
return unless Cucumber::JRUBY && File.directory?(filenames)
|
372
381
|
|
373
382
|
require 'java'
|
374
|
-
$CLASSPATH <<
|
383
|
+
$CLASSPATH << filenames
|
375
384
|
end
|
376
385
|
|
377
386
|
def require_jars(jars)
|
@@ -432,8 +441,8 @@ Specify SEED to reproduce the shuffling from a previous run.
|
|
432
441
|
ProjectInitializer.new.run && Kernel.exit(0)
|
433
442
|
end
|
434
443
|
|
435
|
-
def add_profile(
|
436
|
-
@profiles <<
|
444
|
+
def add_profile(profile)
|
445
|
+
@profiles << profile
|
437
446
|
end
|
438
447
|
|
439
448
|
def set_option(option, value = nil)
|
@@ -446,7 +455,7 @@ Specify SEED to reproduce the shuffling from a previous run.
|
|
446
455
|
end
|
447
456
|
|
448
457
|
def exit_ok(text)
|
449
|
-
@out_stream.puts
|
458
|
+
@out_stream.puts(text)
|
450
459
|
Kernel.exit(0)
|
451
460
|
end
|
452
461
|
|
@@ -474,22 +483,11 @@ Specify SEED to reproduce the shuffling from a previous run.
|
|
474
483
|
end
|
475
484
|
end
|
476
485
|
|
477
|
-
def disable_profile_loading?
|
478
|
-
@disable_profile_loading
|
479
|
-
end
|
480
|
-
|
481
486
|
def merge_profiles
|
482
|
-
if @disable_profile_loading
|
483
|
-
@out_stream.puts 'Disabling profiles...'
|
484
|
-
return
|
485
|
-
end
|
487
|
+
return @out_stream.puts 'Disabling profiles...' if @disable_profile_loading
|
486
488
|
|
487
489
|
@profiles << @default_profile if default_profile_should_be_used?
|
488
|
-
|
489
|
-
@profiles.each do |profile|
|
490
|
-
merge_with_profile(profile)
|
491
|
-
end
|
492
|
-
|
490
|
+
@profiles.each { |profile| merge_with_profile(profile) }
|
493
491
|
@options[:profiles] = @profiles
|
494
492
|
end
|
495
493
|
|
@@ -513,7 +511,7 @@ Specify SEED to reproduce the shuffling from a previous run.
|
|
513
511
|
@profile_loader ||= ProfileLoader.new
|
514
512
|
end
|
515
513
|
|
516
|
-
def reverse_merge(other_options)
|
514
|
+
def reverse_merge(other_options)
|
517
515
|
@options = other_options.options.merge(@options)
|
518
516
|
@options[:require] += other_options[:require]
|
519
517
|
@options[:excludes] += other_options[:excludes]
|
@@ -543,6 +541,7 @@ Specify SEED to reproduce the shuffling from a previous run.
|
|
543
541
|
end
|
544
542
|
|
545
543
|
@options[:retry] = other_options[:retry] if @options[:retry].zero?
|
544
|
+
@options[:retry_total] = other_options[:retry_total] if @options[:retry_total].infinite?
|
546
545
|
|
547
546
|
self
|
548
547
|
end
|
@@ -616,7 +615,8 @@ Specify SEED to reproduce the shuffling from a previous run.
|
|
616
615
|
snippets: true,
|
617
616
|
source: true,
|
618
617
|
duration: true,
|
619
|
-
retry: 0
|
618
|
+
retry: 0,
|
619
|
+
retry_total: Float::INFINITY
|
620
620
|
}
|
621
621
|
end
|
622
622
|
end
|
@@ -11,11 +11,11 @@ module Cucumber
|
|
11
11
|
|
12
12
|
def args_from(profile)
|
13
13
|
unless cucumber_yml.key?(profile)
|
14
|
-
raise(ProfileNotFound,
|
15
|
-
Could not find profile: '#{profile}'
|
14
|
+
raise(ProfileNotFound, <<~END_OF_ERROR)
|
15
|
+
Could not find profile: '#{profile}'
|
16
16
|
|
17
|
-
Defined profiles in cucumber.yml:
|
18
|
-
|
17
|
+
Defined profiles in cucumber.yml:
|
18
|
+
* #{cucumber_yml.keys.sort.join("\n * ")}
|
19
19
|
END_OF_ERROR
|
20
20
|
end
|
21
21
|
|
@@ -84,7 +84,7 @@ Defined profiles in cucumber.yml:
|
|
84
84
|
def load_configuration
|
85
85
|
require 'yaml'
|
86
86
|
begin
|
87
|
-
@cucumber_yml = YAML.load(@cucumber_erb)
|
87
|
+
@cucumber_yml = YAML.load(@cucumber_erb)
|
88
88
|
rescue StandardError
|
89
89
|
raise(YmlLoadError, "cucumber.yml was found, but could not be parsed. Please refer to cucumber's documentation on correct profile usage.\n")
|
90
90
|
end
|
@@ -78,6 +78,10 @@ module Cucumber
|
|
78
78
|
@options[:retry]
|
79
79
|
end
|
80
80
|
|
81
|
+
def retry_total_tests
|
82
|
+
@options[:retry_total]
|
83
|
+
end
|
84
|
+
|
81
85
|
def guess?
|
82
86
|
@options[:guess]
|
83
87
|
end
|
@@ -209,7 +213,7 @@ module Cucumber
|
|
209
213
|
yield factory,
|
210
214
|
formatter_options,
|
211
215
|
path_or_io
|
212
|
-
rescue Exception => e
|
216
|
+
rescue Exception => e
|
213
217
|
raise e, "#{e.message}\nError creating formatter: #{format}", e.backtrace
|
214
218
|
end
|
215
219
|
end
|
@@ -273,7 +277,8 @@ module Cucumber
|
|
273
277
|
snippets: true,
|
274
278
|
source: true,
|
275
279
|
duration: true,
|
276
|
-
event_bus: Cucumber::Events.make_event_bus
|
280
|
+
event_bus: Cucumber::Events.make_event_bus,
|
281
|
+
retry_total: Float::INFINITY
|
277
282
|
}
|
278
283
|
end
|
279
284
|
|
data/lib/cucumber/deprecate.rb
CHANGED
@@ -4,52 +4,11 @@ require 'cucumber/platform'
|
|
4
4
|
require 'cucumber/gherkin/formatter/ansi_escapes'
|
5
5
|
|
6
6
|
module Cucumber
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
end
|
14
|
-
|
15
|
-
def failure_message(message)
|
16
|
-
failed + message + reset
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
class CliOption
|
21
|
-
def self.deprecate(stream, option, message, remove_after_version)
|
22
|
-
return if stream.nil?
|
23
|
-
|
24
|
-
stream.puts(
|
25
|
-
AnsiString.failure_message(
|
26
|
-
"\nWARNING: #{option} is deprecated" \
|
27
|
-
" and will be removed after version #{remove_after_version}.\n#{message}.\n"
|
28
|
-
)
|
29
|
-
)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
module ForUsers
|
34
|
-
def self.call(message, method, remove_after_version)
|
35
|
-
$stderr.puts AnsiString.failure_message(
|
36
|
-
"\nWARNING: ##{method} is deprecated" \
|
37
|
-
" and will be removed after version #{remove_after_version}. #{message}.\n" \
|
38
|
-
"(Called from #{caller(3..3).first})"
|
39
|
-
)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
module ForDevelopers
|
44
|
-
def self.call(_message, _method, remove_after_version)
|
45
|
-
raise "This method is due for removal after version #{remove_after_version}" if Cucumber::VERSION >= remove_after_version
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
STRATEGY = $PROGRAM_NAME =~ /rspec$/ ? ForDevelopers : ForUsers
|
50
|
-
end
|
51
|
-
|
52
|
-
def self.deprecate(*args)
|
53
|
-
Deprecate::STRATEGY.call(*args)
|
7
|
+
def self.deprecate(message, method, remove_after_version)
|
8
|
+
$stderr.puts(
|
9
|
+
"\nWARNING: ##{method} is deprecated" \
|
10
|
+
" and will be removed after version #{remove_after_version}. #{message}.\n" \
|
11
|
+
"(Called from #{caller(3..3).first})"
|
12
|
+
)
|
54
13
|
end
|
55
14
|
end
|
data/lib/cucumber/errors.rb
CHANGED
@@ -35,7 +35,8 @@ module Cucumber
|
|
35
35
|
# Raised when a step matches 2 or more StepDefinitions
|
36
36
|
class Ambiguous < StandardError
|
37
37
|
def initialize(step_name, step_definitions, used_guess)
|
38
|
-
|
38
|
+
# TODO: [LH] - Just use a heredoc here to fix this up
|
39
|
+
message = String.new
|
39
40
|
message << "Ambiguous match of \"#{step_name}\":\n\n"
|
40
41
|
message << step_definitions.map(&:backtrace_line).join("\n")
|
41
42
|
message << "\n\n"
|
data/lib/cucumber/file_specs.rb
CHANGED
@@ -5,7 +5,7 @@ require 'cucumber/core/test/location'
|
|
5
5
|
|
6
6
|
module Cucumber
|
7
7
|
class FileSpecs
|
8
|
-
FILE_COLON_LINE_PATTERN = /^([\w\W]*?)(?::([\d:]+))
|
8
|
+
FILE_COLON_LINE_PATTERN = /^([\w\W]*?)(?::([\d:]+))?$/.freeze # :nodoc:
|
9
9
|
|
10
10
|
def initialize(file_specs)
|
11
11
|
Cucumber.logger.debug("Features:\n")
|
@@ -7,6 +7,11 @@ require 'cucumber/events'
|
|
7
7
|
module Cucumber
|
8
8
|
module Filters
|
9
9
|
class Retry < Core::Filter.new(:configuration)
|
10
|
+
def initialize(*_args)
|
11
|
+
super
|
12
|
+
@total_permanently_failed = 0
|
13
|
+
end
|
14
|
+
|
10
15
|
def test_case(test_case)
|
11
16
|
configuration.on_event(:test_case_finished) do |event|
|
12
17
|
next unless retry_required?(test_case, event)
|
@@ -21,7 +26,21 @@ module Cucumber
|
|
21
26
|
private
|
22
27
|
|
23
28
|
def retry_required?(test_case, event)
|
24
|
-
|
29
|
+
return false unless event.test_case == test_case
|
30
|
+
|
31
|
+
return false unless event.result.failed?
|
32
|
+
|
33
|
+
return false if @total_permanently_failed >= configuration.retry_total_tests
|
34
|
+
|
35
|
+
retry_required = test_case_counts[test_case] < configuration.retry_attempts
|
36
|
+
if retry_required
|
37
|
+
# retry test
|
38
|
+
true
|
39
|
+
else
|
40
|
+
# test failed after max. attempts
|
41
|
+
@total_permanently_failed += 1
|
42
|
+
false
|
43
|
+
end
|
25
44
|
end
|
26
45
|
|
27
46
|
def test_case_counts
|