cucumber 10.2.0 → 11.0.0

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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/VERSION +1 -1
  4. data/lib/cucumber/cli/configuration.rb +1 -1
  5. data/lib/cucumber/cli/options.rb +3 -18
  6. data/lib/cucumber/cli/profile_loader.rb +2 -2
  7. data/lib/cucumber/cli/rerun_file.rb +1 -1
  8. data/lib/cucumber/cli.rb +3 -0
  9. data/lib/cucumber/configuration.rb +29 -24
  10. data/lib/cucumber/events/envelope.rb +18 -0
  11. data/lib/cucumber/events/test_run_hook_finished.rb +11 -0
  12. data/lib/cucumber/events/test_run_hook_started.rb +11 -0
  13. data/lib/cucumber/events.rb +2 -0
  14. data/lib/cucumber/filters/randomizer.rb +5 -5
  15. data/lib/cucumber/filters/reverser.rb +41 -0
  16. data/lib/cucumber/filters.rb +1 -12
  17. data/lib/cucumber/formatter/ansicolor.rb +3 -0
  18. data/lib/cucumber/formatter/duration_extractor.rb +2 -0
  19. data/lib/cucumber/formatter/html.rb +1 -3
  20. data/lib/cucumber/formatter/junit.rb +1 -28
  21. data/lib/cucumber/formatter/message.rb +1 -0
  22. data/lib/cucumber/formatter/message_builder.rb +133 -29
  23. data/lib/cucumber/formatter/progress.rb +1 -0
  24. data/lib/cucumber/formatter/query/test_case_started_by_test_case.rb +1 -0
  25. data/lib/cucumber/formatter/rerun.rb +76 -32
  26. data/lib/cucumber/formatter/usage.rb +1 -1
  27. data/lib/cucumber/formatter.rb +3 -0
  28. data/lib/cucumber/glue/registry_and_more.rb +27 -14
  29. data/lib/cucumber/glue.rb +3 -0
  30. data/lib/cucumber/multiline_argument/data_table.rb +0 -11
  31. data/lib/cucumber/platform.rb +2 -2
  32. data/lib/cucumber/query.rb +273 -0
  33. data/lib/cucumber/rake/forked_cucumber_runner.rb +57 -0
  34. data/lib/cucumber/rake/in_process_cucumber_runner.rb +27 -0
  35. data/lib/cucumber/rake/task.rb +36 -106
  36. data/lib/cucumber/rake.rb +3 -0
  37. data/lib/cucumber/repository.rb +136 -0
  38. data/lib/cucumber/rspec/disable_option_parser.rb +3 -3
  39. data/lib/cucumber/runtime.rb +1 -0
  40. data/lib/cucumber/step_match.rb +1 -1
  41. data/lib/cucumber.rb +2 -13
  42. metadata +29 -21
  43. data/lib/cucumber/formatter/query/pickle_step_by_test_step.rb +0 -28
  44. data/lib/cucumber/formatter/query/test_run_started.rb +0 -17
  45. data/lib/cucumber/step_definition_light.rb +0 -29
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bd6eb560b45052579319bf0fdf3052c8ef17e122a51342271e87917ae5ed6c28
4
- data.tar.gz: 81d39f9f1a7c285e206645d1289347875b45bc5a56d4ce9b95137933055b0609
3
+ metadata.gz: c26004e2b3e93b8a26180b4e6395f62dc4dcf8ab9cf410e6a179af00e98687ae
4
+ data.tar.gz: 7cc32417229dd46c4aa4816e6137cfae251ed1d1f2eb107693e3b03442d1c3d6
5
5
  SHA512:
6
- metadata.gz: 99ab364fa46cadbee42cdc23114e17e27030a5d8868e85367884b01eef9a165b3bf27ea786708ea3cbdfe5a1ef132652e703bebfb9e41453a11fc68345a4f94d
7
- data.tar.gz: c7fef1179a2b86ff74daa07b1ffd0336333716ab1469b84a6d909eeab0466812f0a1a37718582ec6bd2633d53e49b9f811fd20ae48d27c3b99b72233e41edce5
6
+ metadata.gz: dfd1379832fc0fb2cede983c7d2fac1491fa83cc394d00e9fd00359632029f6adc44c6ef1140c824f8abb8e03a736075c99b94fcdab40ac457facadc5cc58b44
7
+ data.tar.gz: 3f26435c0610fdaaa7afc111010a3bac1683f7e1235a5c49eafe85e4f64f398d8dd78333cffa9edd1b951f3225fb0b85c08d8cfcf6962891a6bda596ce28d3d8
data/README.md CHANGED
@@ -45,12 +45,12 @@ Later in this document, bundler is considered being used so all commands are usi
45
45
 
46
46
  ### Supported platforms
47
47
 
48
+ - Ruby 4.0
48
49
  - Ruby 3.4
49
50
  - Ruby 3.3
50
51
  - Ruby 3.2
51
- - Ruby 3.1
52
52
  - TruffleRuby 24.0.0+
53
- - JRuby 9.4+ (with [some limitations](https://github.com/cucumber/cucumber-ruby/blob/main/docs/jruby-limitations.md))
53
+ - JRuby 10.0+ (with [some limitations](https://github.com/cucumber/cucumber-ruby/blob/main/docs/jruby-limitations.md))
54
54
 
55
55
  ### Ruby on Rails
56
56
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 10.2.0
1
+ 11.0.0
@@ -15,7 +15,7 @@ module Cucumber
15
15
  class Configuration
16
16
  include Constantize
17
17
 
18
- attr_reader :out_stream
18
+ attr_reader :out_stream, :options
19
19
 
20
20
  def initialize(out_stream = $stdout, error_stream = $stderr)
21
21
  @out_stream = out_stream
@@ -63,7 +63,7 @@ module Cucumber
63
63
  PROFILE_SHORT_FLAG, PROFILE_LONG_FLAG, RETRY_FLAG, RETRY_TOTAL_FLAG,
64
64
  '-l', '--lines', '--port', '-I', '--snippet-type'
65
65
  ].freeze
66
- ORDER_TYPES = %w[defined random].freeze
66
+ ORDER_TYPES = %w[defined random reverse].freeze
67
67
  TAG_LIMIT_MATCHER = /(?<tag_name>@\w+):(?<limit>\d+)/x.freeze
68
68
 
69
69
  def self.parse(args, out_stream, error_stream, options = {})
@@ -146,6 +146,7 @@ module Cucumber
146
146
  *<<~TEXT.split("\n")) do |order|
147
147
  [defined] Run scenarios in the order they were defined (default).
148
148
  [random] Shuffle scenarios before running.
149
+ [reverse] Run scenarios in the opposite order to which they were defined.
149
150
  Specify SEED to reproduce the shuffling from a previous run.
150
151
  e.g. --order random:5738
151
152
  TEXT
@@ -601,23 +602,7 @@ module Cucumber
601
602
  end
602
603
 
603
604
  def default_options
604
- {
605
- strict: Cucumber::Core::Test::Result::StrictConfiguration.new,
606
- require: [],
607
- dry_run: false,
608
- formats: [],
609
- excludes: [],
610
- tag_expressions: [],
611
- tag_limits: {},
612
- name_regexps: [],
613
- env_vars: {},
614
- diff_enabled: true,
615
- snippets: true,
616
- source: true,
617
- duration: true,
618
- retry: 0,
619
- retry_total: Float::INFINITY
620
- }
605
+ Cucumber::Configuration.default_options
621
606
  end
622
607
  end
623
608
  end
@@ -80,9 +80,9 @@ module Cucumber
80
80
  end
81
81
 
82
82
  def process_configuration_file_with_erb
83
- @cucumber_erb = ERB.new(IO.read(cucumber_file), trim_mode: '%').result(binding)
83
+ @cucumber_erb = ERB.new(File.read(cucumber_file), trim_mode: '%').result(binding)
84
84
  rescue StandardError
85
- raise(YmlLoadError, "cucumber.yml was found, but could not be parsed with ERB. Please refer to cucumber's documentation on correct profile usage.\n#{$ERROR_INFO.inspect}")
85
+ raise(YmlLoadError, "cucumber.yml was found, but could not be parsed with ERB. Please refer to cucumber's documentation on correct profile usage.\n#{$ERROR_INFO.inspect}")
86
86
  end
87
87
 
88
88
  def load_configuration
@@ -24,7 +24,7 @@ module Cucumber
24
24
  private
25
25
 
26
26
  def lines
27
- IO.read(@path).split("\n")
27
+ File.read(path).split("\n")
28
28
  end
29
29
  end
30
30
  end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ Dir["#{File.dirname(__FILE__)}/cli/*.rb"].map(&method(:require))
@@ -19,6 +19,30 @@ module Cucumber
19
19
  new
20
20
  end
21
21
 
22
+ def self.default_options
23
+ {
24
+ autoload_code_paths: %w[features/support features/step_definitions],
25
+ filters: [],
26
+ strict: Cucumber::Core::Test::Result::StrictConfiguration.new,
27
+ require: [],
28
+ dry_run: false,
29
+ fail_fast: false,
30
+ formats: [],
31
+ excludes: [],
32
+ tag_expressions: [],
33
+ name_regexps: [],
34
+ env_vars: {},
35
+ diff_enabled: true,
36
+ snippets: true,
37
+ source: true,
38
+ duration: true,
39
+ event_bus: Cucumber::Events.make_event_bus,
40
+ retry_total: Float::INFINITY,
41
+ tag_limits: {},
42
+ retry: 0
43
+ }
44
+ end
45
+
22
46
  # Subscribe to an event.
23
47
  #
24
48
  # See {Cucumber::Events} for the list of possible events.
@@ -35,7 +59,7 @@ module Cucumber
35
59
  end
36
60
 
37
61
  def initialize(user_options = {})
38
- @options = default_options.merge(Hash(user_options))
62
+ @options = self.class.default_options.merge(Hash(user_options))
39
63
  end
40
64
 
41
65
  def with_options(new_options)
@@ -54,6 +78,10 @@ module Cucumber
54
78
  @options[:order] == 'random'
55
79
  end
56
80
 
81
+ def reverse_order?
82
+ @options[:order] == 'reverse'
83
+ end
84
+
57
85
  def seed
58
86
  @options[:seed]
59
87
  end
@@ -259,29 +287,6 @@ module Cucumber
259
287
 
260
288
  private
261
289
 
262
- def default_options
263
- {
264
- autoload_code_paths: ['features/support', 'features/step_definitions'],
265
- filters: [],
266
- strict: Cucumber::Core::Test::Result::StrictConfiguration.new,
267
- require: [],
268
- dry_run: false,
269
- publish_quiet: false,
270
- fail_fast: false,
271
- formats: [],
272
- excludes: [],
273
- tag_expressions: [],
274
- name_regexps: [],
275
- env_vars: {},
276
- diff_enabled: true,
277
- snippets: true,
278
- source: true,
279
- duration: true,
280
- event_bus: Cucumber::Events.make_event_bus,
281
- retry_total: Float::INFINITY
282
- }
283
- end
284
-
285
290
  def default_features_paths
286
291
  ['features']
287
292
  end
@@ -6,6 +6,24 @@ module Cucumber
6
6
  module Events
7
7
  class Envelope < Core::Event.new(:envelope)
8
8
  attr_reader :envelope
9
+
10
+ def inspect
11
+ "Envelope Event -> Message Type: #{type}}"
12
+ end
13
+
14
+ def to_s
15
+ inspect
16
+ end
17
+
18
+ private
19
+
20
+ def type
21
+ envelope.instance_variables.detect { |message| !envelope.send(name_of(message)).nil? }
22
+ end
23
+
24
+ def name_of(message)
25
+ message.to_s.delete('@')
26
+ end
9
27
  end
10
28
  end
11
29
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cucumber/core/events'
4
+
5
+ module Cucumber
6
+ module Events
7
+ class TestRunHookFinished < Core::Event.new(:hook, :test_result)
8
+ attr_reader :hook, :test_result
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cucumber/core/events'
4
+
5
+ module Cucumber
6
+ module Events
7
+ class TestRunHookStarted < Core::Event.new(:hook)
8
+ attr_reader :hook
9
+ end
10
+ end
11
+ end
@@ -34,6 +34,8 @@ module Cucumber
34
34
  TestCaseStarted,
35
35
  TestCaseReady,
36
36
  TestRunFinished,
37
+ TestRunHookFinished,
38
+ TestRunHookStarted,
37
39
  TestRunStarted,
38
40
  TestStepCreated,
39
41
  TestStepFinished,
@@ -6,6 +6,9 @@ module Cucumber
6
6
  module Filters
7
7
  # Batches up all test cases, randomizes them, and then sends them on
8
8
  class Randomizer
9
+ attr_reader :seed
10
+ private :seed
11
+
9
12
  def initialize(seed, receiver = nil)
10
13
  @receiver = receiver
11
14
  @test_cases = []
@@ -26,7 +29,7 @@ module Cucumber
26
29
  end
27
30
 
28
31
  def with_receiver(receiver)
29
- self.class.new(@seed, receiver)
32
+ self.class.new(seed, receiver)
30
33
  end
31
34
 
32
35
  private
@@ -34,12 +37,9 @@ module Cucumber
34
37
  def shuffled_test_cases
35
38
  digester = Digest::SHA2.new(256)
36
39
  @test_cases.map.with_index
37
- .sort_by { |_, index| digester.digest((@seed + index).to_s) }
40
+ .sort_by { |_, index| digester.digest((seed + index).to_s) }
38
41
  .map { |test_case, _| test_case }
39
42
  end
40
-
41
- attr_reader :seed
42
- private :seed
43
43
  end
44
44
  end
45
45
  end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'digest/sha2'
4
+
5
+ module Cucumber
6
+ module Filters
7
+ # Reverses the order of test cases
8
+ class Reverser
9
+ attr_reader :seed
10
+ private :seed
11
+
12
+ def initialize(receiver = nil)
13
+ @receiver = receiver
14
+ @test_cases = []
15
+ end
16
+
17
+ def test_case(test_case)
18
+ @test_cases << test_case
19
+ self
20
+ end
21
+
22
+ def done
23
+ reversed_test_cases.each do |test_case|
24
+ test_case.describe_to(@receiver)
25
+ end
26
+ @receiver.done
27
+ self
28
+ end
29
+
30
+ def with_receiver(receiver)
31
+ self.class.new(receiver)
32
+ end
33
+
34
+ private
35
+
36
+ def reversed_test_cases
37
+ @test_cases.reverse
38
+ end
39
+ end
40
+ end
41
+ end
@@ -1,14 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'cucumber/filters/activate_steps'
4
- require 'cucumber/filters/apply_after_step_hooks'
5
- require 'cucumber/filters/apply_before_hooks'
6
- require 'cucumber/filters/apply_after_hooks'
7
- require 'cucumber/filters/apply_around_hooks'
8
- require 'cucumber/filters/broadcast_test_run_started_event'
9
- require 'cucumber/filters/prepare_world'
10
- require 'cucumber/filters/quit'
11
- require 'cucumber/filters/randomizer'
12
- require 'cucumber/filters/retry'
13
- require 'cucumber/filters/tag_limits'
14
- require 'cucumber/filters/broadcast_test_case_ready_event'
3
+ Dir["#{File.dirname(__FILE__)}/filters/*.rb"].map(&method(:require))
@@ -47,6 +47,8 @@ module Cucumber
47
47
  # * <tt>flaky_param</tt> - defaults to <tt>yellow,bold</tt>
48
48
  # * <tt>failed</tt> - defaults to <tt>red</tt>
49
49
  # * <tt>failed_param</tt> - defaults to <tt>red,bold</tt>
50
+ # * <tt>ambiguous</tt> - defaults to <tt>red</tt>
51
+ # * <tt>abmiguous_param</tt> - defaults to <tt>red,bold</tt>
50
52
  # * <tt>passed</tt> - defaults to <tt>green</tt>
51
53
  # * <tt>passed_param</tt> - defaults to <tt>green,bold</tt>
52
54
  # * <tt>outline</tt> - defaults to <tt>cyan</tt>
@@ -72,6 +74,7 @@ module Cucumber
72
74
  'pending' => 'yellow',
73
75
  'flaky' => 'yellow',
74
76
  'failed' => 'red',
77
+ 'ambiguous' => 'red',
75
78
  'passed' => 'green',
76
79
  'outline' => 'cyan',
77
80
  'skipped' => 'cyan',
@@ -14,6 +14,8 @@ module Cucumber
14
14
 
15
15
  def failed(*) end
16
16
 
17
+ def ambiguous(*) end
18
+
17
19
  def undefined(*) end
18
20
 
19
21
  def skipped(*) end
@@ -7,17 +7,15 @@ require 'cucumber/formatter/message_builder'
7
7
  module Cucumber
8
8
  module Formatter
9
9
  class HTML < MessageBuilder
10
- include Io
11
-
12
10
  def initialize(config)
13
11
  @io = ensure_io(config.out_stream, config.error_stream)
14
12
  @html_formatter = Cucumber::HTMLFormatter::Formatter.new(@io)
15
13
  @html_formatter.write_pre_message
16
-
17
14
  super(config)
18
15
  end
19
16
 
20
17
  def output_envelope(envelope)
18
+ @repository.update(envelope)
21
19
  @html_formatter.write_message(envelope)
22
20
  @html_formatter.write_post_message if envelope.test_run_finished
23
21
  end
@@ -131,7 +131,7 @@ module Cucumber
131
131
  end
132
132
 
133
133
  def build_testcase(result, scenario_designation, output)
134
- duration = ResultBuilder.new(result).test_case_duration
134
+ duration = DurationExtractor.new(result).result_duration
135
135
  @current_feature_data[:time] += duration
136
136
  classname = @current_feature_data[:feature].name
137
137
  filename = @current_feature_data[:uri]
@@ -234,32 +234,5 @@ module Cucumber
234
234
  @name_suffix = " (outline example : #{@row_name})"
235
235
  end
236
236
  end
237
-
238
- class ResultBuilder
239
- attr_reader :test_case_duration
240
-
241
- def initialize(result)
242
- @test_case_duration = 0
243
- result.describe_to(self)
244
- end
245
-
246
- def passed(*) end
247
-
248
- def failed(*) end
249
-
250
- def undefined(*) end
251
-
252
- def skipped(*) end
253
-
254
- def pending(*) end
255
-
256
- def exception(*) end
257
-
258
- def duration(duration, *)
259
- duration.tap { |dur| @test_case_duration = dur.nanoseconds / 10**9.0 }
260
- end
261
-
262
- def attach(*) end
263
- end
264
237
  end
265
238
  end
@@ -15,6 +15,7 @@ module Cucumber
15
15
  end
16
16
 
17
17
  def output_envelope(envelope)
18
+ @repository.update(envelope)
18
19
  @io.write(envelope.to_json)
19
20
  @io.write("\n")
20
21
  end