cucumber 6.0.0 → 8.0.0.rc.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +371 -168
  3. data/CONTRIBUTING.md +216 -55
  4. data/README.md +139 -21
  5. data/lib/autotest/cucumber_mixin.rb +5 -2
  6. data/lib/autotest/discover.rb +3 -2
  7. data/lib/cucumber/cli/configuration.rb +4 -1
  8. data/lib/cucumber/cli/main.rb +4 -3
  9. data/lib/cucumber/cli/options.rb +14 -4
  10. data/lib/cucumber/cli/profile_loader.rb +1 -5
  11. data/lib/cucumber/cli/rerun_file.rb +1 -1
  12. data/lib/cucumber/configuration.rb +5 -4
  13. data/lib/cucumber/constantize.rb +1 -1
  14. data/lib/cucumber/deprecate.rb +2 -1
  15. data/lib/cucumber/errors.rb +1 -1
  16. data/lib/cucumber/events/hook_test_step_created.rb +1 -2
  17. data/lib/cucumber/events/step_activated.rb +0 -6
  18. data/lib/cucumber/events/step_definition_registered.rb +0 -5
  19. data/lib/cucumber/events/test_case_created.rb +1 -2
  20. data/lib/cucumber/events/test_run_finished.rb +2 -1
  21. data/lib/cucumber/events/test_step_created.rb +1 -2
  22. data/lib/cucumber/events/undefined_parameter_type.rb +1 -2
  23. data/lib/cucumber/events.rb +2 -2
  24. data/lib/cucumber/file_specs.rb +2 -1
  25. data/lib/cucumber/filters/activate_steps.rb +1 -0
  26. data/lib/cucumber/filters/tag_limits/verifier.rb +1 -3
  27. data/lib/cucumber/filters/tag_limits.rb +1 -3
  28. data/lib/cucumber/formatter/ansicolor.rb +63 -70
  29. data/lib/cucumber/formatter/ast_lookup.rb +2 -2
  30. data/lib/cucumber/formatter/backtrace_filter.rb +1 -1
  31. data/lib/cucumber/formatter/console.rb +20 -4
  32. data/lib/cucumber/formatter/console_issues.rb +6 -1
  33. data/lib/cucumber/formatter/duration_extractor.rb +1 -0
  34. data/lib/cucumber/formatter/errors.rb +1 -0
  35. data/lib/cucumber/formatter/fanout.rb +1 -1
  36. data/lib/cucumber/formatter/http_io.rb +6 -1
  37. data/lib/cucumber/formatter/ignore_missing_messages.rb +1 -1
  38. data/lib/cucumber/formatter/io.rb +3 -1
  39. data/lib/cucumber/formatter/json.rb +32 -26
  40. data/lib/cucumber/formatter/junit.rb +6 -3
  41. data/lib/cucumber/formatter/message.rb +2 -1
  42. data/lib/cucumber/formatter/message_builder.rb +11 -10
  43. data/lib/cucumber/formatter/pretty.rb +34 -23
  44. data/lib/cucumber/formatter/progress.rb +1 -0
  45. data/lib/cucumber/formatter/publish_banner_printer.rb +1 -1
  46. data/lib/cucumber/formatter/query/hook_by_test_step.rb +1 -0
  47. data/lib/cucumber/formatter/query/test_case_started_by_test_case.rb +2 -0
  48. data/lib/cucumber/formatter/rerun.rb +2 -0
  49. data/lib/cucumber/formatter/steps.rb +5 -2
  50. data/lib/cucumber/formatter/summary.rb +1 -0
  51. data/lib/cucumber/formatter/unicode.rb +4 -4
  52. data/lib/cucumber/formatter/usage.rb +9 -7
  53. data/lib/cucumber/gherkin/data_table_parser.rb +2 -1
  54. data/lib/cucumber/gherkin/formatter/ansi_escapes.rb +2 -2
  55. data/lib/cucumber/gherkin/steps_parser.rb +1 -1
  56. data/lib/cucumber/glue/dsl.rb +19 -5
  57. data/lib/cucumber/glue/hook.rb +2 -1
  58. data/lib/cucumber/glue/invoke_in_world.rb +4 -4
  59. data/lib/cucumber/glue/proto_world.rb +12 -9
  60. data/lib/cucumber/glue/registry_and_more.rb +20 -5
  61. data/lib/cucumber/glue/registry_wrapper.rb +31 -0
  62. data/lib/cucumber/glue/step_definition.rb +9 -7
  63. data/lib/cucumber/hooks.rb +1 -0
  64. data/lib/cucumber/multiline_argument/data_table/diff_matrices.rb +2 -1
  65. data/lib/cucumber/multiline_argument/data_table.rb +58 -71
  66. data/lib/cucumber/platform.rb +2 -2
  67. data/lib/cucumber/rake/task.rb +10 -7
  68. data/lib/cucumber/rspec/disable_option_parser.rb +6 -3
  69. data/lib/cucumber/running_test_case.rb +1 -0
  70. data/lib/cucumber/runtime/meta_message_builder.rb +106 -0
  71. data/lib/cucumber/runtime/support_code.rb +3 -0
  72. data/lib/cucumber/runtime/user_interface.rb +5 -4
  73. data/lib/cucumber/runtime.rb +42 -23
  74. data/lib/cucumber/step_match.rb +6 -10
  75. data/lib/cucumber/step_match_search.rb +3 -2
  76. data/lib/cucumber/term/ansicolor.rb +74 -50
  77. data/lib/cucumber/term/banner.rb +1 -0
  78. data/lib/cucumber/version +1 -1
  79. data/lib/cucumber.rb +2 -1
  80. data/lib/simplecov_setup.rb +1 -1
  81. metadata +90 -89
  82. data/lib/cucumber/core_ext/string.rb +0 -11
@@ -2,15 +2,17 @@
2
2
 
3
3
  require 'fileutils'
4
4
  require 'cucumber/configuration'
5
- require 'cucumber/create_meta'
5
+ require 'cucumber/deprecate'
6
6
  require 'cucumber/load_path'
7
7
  require 'cucumber/formatter/duration'
8
8
  require 'cucumber/file_specs'
9
9
  require 'cucumber/filters'
10
10
  require 'cucumber/formatter/fanout'
11
11
  require 'cucumber/gherkin/i18n'
12
+ require 'cucumber/glue/registry_wrapper'
12
13
  require 'cucumber/step_match_search'
13
14
  require 'cucumber/messages'
15
+ require 'cucumber/runtime/meta_message_builder'
14
16
  require 'sys/uname'
15
17
 
16
18
  module Cucumber
@@ -24,8 +26,8 @@ module Cucumber
24
26
  attr_reader :path
25
27
 
26
28
  def initialize(original_exception, path)
27
- super(original_exception)
28
29
  @path = path
30
+ super(original_exception)
29
31
  end
30
32
  end
31
33
 
@@ -35,6 +37,7 @@ module Cucumber
35
37
  class FeatureFolderNotFoundException < RuntimeError
36
38
  def initialize(path)
37
39
  @path = path
40
+ super
38
41
  end
39
42
 
40
43
  def message
@@ -63,21 +66,22 @@ module Cucumber
63
66
  @support_code.configure(@configuration)
64
67
  end
65
68
 
66
- require 'cucumber/wire/plugin'
67
69
  def run!
68
70
  @configuration.notify :envelope, Cucumber::Messages::Envelope.new(
69
- meta: Cucumber::CreateMeta.create_meta('cucumber-ruby', Cucumber::VERSION)
71
+ meta: MetaMessageBuilder.build_meta_message
70
72
  )
71
73
 
72
74
  load_step_definitions
73
- install_wire_plugin
74
- fire_after_configuration_hook
75
+ fire_install_plugin_hook
76
+ fire_before_all_hook unless dry_run?
75
77
  # TODO: can we remove this state?
76
78
  self.visitor = report
77
79
 
78
80
  receiver = Test::Runner.new(@configuration.event_bus)
79
81
  compile features, receiver, filters, @configuration.event_bus
80
- @configuration.notify :test_run_finished
82
+ @configuration.notify :test_run_finished, !failure?
83
+
84
+ fire_after_all_hook unless dry_run?
81
85
  end
82
86
 
83
87
  def features_paths
@@ -106,10 +110,26 @@ module Cucumber
106
110
  Core::Test::DocString.new(string_without_triple_quotes, content_type)
107
111
  end
108
112
 
113
+ def failure?
114
+ if @configuration.wip?
115
+ summary_report.test_cases.total_passed > 0
116
+ else
117
+ !summary_report.ok?(@configuration.strict)
118
+ end
119
+ end
120
+
109
121
  private
110
122
 
111
- def fire_after_configuration_hook #:nodoc:
112
- @support_code.fire_hook(:after_configuration, @configuration)
123
+ def fire_install_plugin_hook # :nodoc:
124
+ @support_code.fire_hook(:install_plugin, @configuration, registry_wrapper)
125
+ end
126
+
127
+ def fire_before_all_hook # :nodoc:
128
+ @support_code.fire_hook(:before_all)
129
+ end
130
+
131
+ def fire_after_all_hook # :nodoc:
132
+ @support_code.fire_hook(:after_all)
113
133
  end
114
134
 
115
135
  require 'cucumber/core/gherkin/document'
@@ -130,8 +150,8 @@ module Cucumber
130
150
  end
131
151
 
132
152
  class NormalisedEncodingFile
133
- COMMENT_OR_EMPTY_LINE_PATTERN = /^\s*#|^\s*$/ #:nodoc:
134
- ENCODING_PATTERN = /^\s*#\s*encoding\s*:\s*([^\s]+)/ #:nodoc:
153
+ COMMENT_OR_EMPTY_LINE_PATTERN = /^\s*#|^\s*$/ # :nodoc:
154
+ ENCODING_PATTERN = /^\s*#\s*encoding\s*:\s*([^\s]+)/ # :nodoc:
135
155
 
136
156
  def self.read(path)
137
157
  new(path).read
@@ -171,6 +191,7 @@ module Cucumber
171
191
 
172
192
  def report
173
193
  return @report if @report
194
+
174
195
  reports = [summary_report] + formatters
175
196
  reports << fail_fast_report if @configuration.fail_fast?
176
197
  reports << publish_banner_printer unless @configuration.publish_quiet?
@@ -199,10 +220,12 @@ module Cucumber
199
220
  def create_formatter(factory, formatter_options, path_or_io)
200
221
  if accept_options?(factory)
201
222
  return factory.new(@configuration, formatter_options) if path_or_io.nil?
223
+
202
224
  factory.new(@configuration.with_options(out_stream: path_or_io),
203
225
  formatter_options)
204
226
  else
205
227
  return factory.new(@configuration) if path_or_io.nil?
228
+
206
229
  factory.new(@configuration.with_options(out_stream: path_or_io))
207
230
  end
208
231
  end
@@ -211,15 +234,6 @@ module Cucumber
211
234
  factory.instance_method(:initialize).arity > 1
212
235
  end
213
236
 
214
- def failure?
215
- if @configuration.wip?
216
- summary_report.test_cases.total_passed > 0
217
- else
218
- !summary_report.ok?(@configuration.strict)
219
- end
220
- end
221
- public :failure?
222
-
223
237
  require 'cucumber/core/test/filters'
224
238
  def filters # rubocop:disable Metrics/AbcSize
225
239
  tag_expressions = @configuration.tag_expressions
@@ -235,12 +249,17 @@ module Cucumber
235
249
  step_match_search = StepMatchSearch.new(@support_code.registry.method(:step_matches), @configuration)
236
250
  filters << Filters::ActivateSteps.new(step_match_search, @configuration)
237
251
  @configuration.filters.each { |filter| filters << filter }
252
+
238
253
  unless configuration.dry_run?
239
254
  filters << Filters::ApplyAfterStepHooks.new(@support_code)
240
255
  filters << Filters::ApplyBeforeHooks.new(@support_code)
241
256
  filters << Filters::ApplyAfterHooks.new(@support_code)
242
257
  filters << Filters::ApplyAroundHooks.new(@support_code)
243
- filters << Filters::BroadcastTestCaseReadyEvent.new(@configuration)
258
+ end
259
+
260
+ filters << Filters::BroadcastTestCaseReadyEvent.new(@configuration)
261
+
262
+ unless configuration.dry_run?
244
263
  filters << Filters::BroadcastTestRunStartedEvent.new(@configuration)
245
264
  filters << Filters::Quit.new
246
265
  filters << Filters::Retry.new(@configuration)
@@ -255,8 +274,8 @@ module Cucumber
255
274
  @support_code.load_files!(files)
256
275
  end
257
276
 
258
- def install_wire_plugin
259
- Cucumber::Wire::Plugin.new(@configuration, @support_code.registry).install if @configuration.all_files_to_load.any? { |f| f =~ /\.wire$/ }
277
+ def registry_wrapper
278
+ Cucumber::Glue::RegistryWrapper.new(@support_code.registry)
260
279
  end
261
280
 
262
281
  def log
@@ -4,11 +4,12 @@ require 'cucumber/multiline_argument'
4
4
 
5
5
  module Cucumber
6
6
  # Represents the match found between a Test Step and its activation
7
- class StepMatch #:nodoc:
7
+ class StepMatch # :nodoc:
8
8
  attr_reader :step_definition, :step_arguments
9
9
 
10
10
  def initialize(step_definition, step_name, step_arguments)
11
11
  raise "step_arguments can't be nil (but it can be an empty array)" if step_arguments.nil?
12
+
12
13
  @step_definition = step_definition
13
14
  @name_to_match = step_name
14
15
  @step_arguments = step_arguments
@@ -28,7 +29,7 @@ module Cucumber
28
29
  end
29
30
 
30
31
  def invoke(multiline_arg)
31
- all_args = deep_clone_args
32
+ all_args = args
32
33
  multiline_arg.append_to(all_args)
33
34
  @step_definition.invoke(all_args)
34
35
  end
@@ -90,15 +91,9 @@ module Cucumber
90
91
  s
91
92
  end
92
93
 
93
- def inspect #:nodoc:
94
+ def inspect # :nodoc:
94
95
  "#<#{self.class}: #{location}>"
95
96
  end
96
-
97
- private
98
-
99
- def deep_clone_args
100
- Marshal.load(Marshal.dump(args))
101
- end
102
97
  end
103
98
 
104
99
  class SkippingStepMatch
@@ -107,7 +102,7 @@ module Cucumber
107
102
  end
108
103
  end
109
104
 
110
- class NoStepMatch #:nodoc:
105
+ class NoStepMatch # :nodoc:
111
106
  attr_reader :step_definition, :name
112
107
 
113
108
  def initialize(step, name)
@@ -121,6 +116,7 @@ module Cucumber
121
116
 
122
117
  def location
123
118
  raise "No location for #{@step}" unless @step.location
119
+
124
120
  @step.location
125
121
  end
126
122
 
@@ -20,6 +20,7 @@ module Cucumber
20
20
  def call(step_name)
21
21
  result = @search.call(step_name)
22
22
  raise Cucumber::Ambiguous.new(step_name, result, @configuration.guess?) if result.length > 1
23
+
23
24
  result
24
25
  end
25
26
  end
@@ -35,7 +36,7 @@ module Cucumber
35
36
 
36
37
  private
37
38
 
38
- def best_matches(_step_name, step_matches) #:nodoc:
39
+ def best_matches(_step_name, step_matches) # :nodoc:
39
40
  no_groups = step_matches.select { |step_match| step_match.args.empty? }
40
41
  max_arg_length = step_matches.map { |step_match| step_match.args.length }.max
41
42
  top_groups = step_matches.select { |step_match| step_match.args.length == max_arg_length }
@@ -54,7 +55,7 @@ module Cucumber
54
55
 
55
56
  require 'delegate'
56
57
  class CachesStepMatch < SimpleDelegator
57
- def call(step_name) #:nodoc:
58
+ def call(step_name) # :nodoc:
58
59
  @match_cache ||= {}
59
60
 
60
61
  matches = @match_cache[step_name]
@@ -2,8 +2,28 @@
2
2
 
3
3
  module Cucumber
4
4
  module Term
5
- # The ANSIColor module can be used for namespacing and mixed into your own
6
- # classes.
5
+ # This module allows to colorize text using ANSI escape sequences.
6
+ #
7
+ # Include the module in your class and use its methods to colorize text.
8
+ #
9
+ # Example:
10
+ #
11
+ # require 'cucumber/term/ansicolor'
12
+ #
13
+ # class MyFormatter
14
+ # include Cucumber::Term::ANSIColor
15
+ #
16
+ # def initialize(config)
17
+ # $stdout.puts yellow("Initializing formatter")
18
+ # $stdout.puts green("Coloring is active \o/") if Cucumber::Term::ANSIColor.coloring?
19
+ # $stdout.puts grey("Feature path:") + blue(bold(config.feature_dirs))
20
+ # end
21
+ # end
22
+ #
23
+ # To see what colours and effects are available, just run this in your shell:
24
+ #
25
+ # ruby -e "require 'rubygems'; require 'cucumber/term/ansicolor'; puts Cucumber::Term::ANSIColor.attributes"
26
+ #
7
27
  module ANSIColor
8
28
  # :stopdoc:
9
29
  ATTRIBUTES = [
@@ -27,6 +47,7 @@ module Cucumber
27
47
  [:magenta, 35],
28
48
  [:cyan, 36],
29
49
  [:white, 37],
50
+ [:grey, 90],
30
51
  [:on_black, 40],
31
52
  [:on_red, 41],
32
53
  [:on_green, 42],
@@ -40,72 +61,75 @@ module Cucumber
40
61
  ATTRIBUTE_NAMES = ATTRIBUTES.transpose.first
41
62
  # :startdoc:
42
63
 
43
- # Returns true, if the coloring function of this module
44
- # is switched on, false otherwise.
45
- def self.coloring?
46
- @coloring
47
- end
48
-
49
- # Turns the coloring on or off globally, so you can easily do
50
- # this for example:
51
- # Cucumber::Term::ANSIColor::coloring = STDOUT.isatty
52
- def self.coloring=(val)
53
- @coloring = val
54
- end
55
- self.coloring = true
56
-
57
- # rubocop:disable Security/Eval
58
- ATTRIBUTES.each do |c, v|
59
- eval <<-END_EVAL, binding, __FILE__, __LINE__ + 1
60
- def #{c}(string = nil)
61
- result = String.new
62
- result << "\e[#{v}m" if Cucumber::Term::ANSIColor.coloring?
63
- if block_given?
64
- result << yield
65
- elsif string
66
- result << string
67
- elsif respond_to?(:to_str)
68
- result << to_str
69
- else
70
- return result #only switch on
71
- end
72
- result << "\e[0m" if Cucumber::Term::ANSIColor.coloring?
73
- result
74
- end
75
- END_EVAL
76
- end
77
- # rubocop:enable Security/Eval
78
-
79
64
  # Regular expression that is used to scan for ANSI-sequences while
80
65
  # uncoloring strings.
81
66
  COLORED_REGEXP = /\e\[(?:[34][0-7]|[0-9])?m/
82
67
 
83
- def self.included(klass)
84
- return unless klass == String
85
- ATTRIBUTES.delete(:clear)
86
- ATTRIBUTE_NAMES.delete(:clear)
68
+ @coloring = true
69
+
70
+ class << self
71
+ # Turns the coloring on or off globally, so you can easily do
72
+ # this for example:
73
+ # Cucumber::Term::ANSIColor::coloring = $stdout.isatty
74
+ attr_accessor :coloring
75
+
76
+ # Returns true, if the coloring function of this module
77
+ # is switched on, false otherwise.
78
+ alias coloring? :coloring
79
+
80
+ def included(klass)
81
+ return unless klass == String
82
+
83
+ ATTRIBUTES.delete(:clear)
84
+ ATTRIBUTE_NAMES.delete(:clear)
85
+ end
87
86
  end
88
87
 
89
- # Returns an uncolored version of the string, that is all
88
+ ATTRIBUTES.each do |color_name, color_code|
89
+ define_method(color_name) do |text = nil, &block|
90
+ if block
91
+ colorize(block.call, color_code)
92
+ elsif text
93
+ colorize(text, color_code)
94
+ elsif respond_to?(:to_str)
95
+ colorize(to_str, color_code)
96
+ else
97
+ colorize(nil, color_code) # switch coloration on
98
+ end
99
+ end
100
+ end
101
+
102
+ # Returns an uncolored version of the string
90
103
  # ANSI-sequences are stripped from the string.
91
- def uncolored(string = nil)
104
+ def uncolored(text = nil)
92
105
  if block_given?
93
- yield.gsub(COLORED_REGEXP, '')
94
- elsif string
95
- string.gsub(COLORED_REGEXP, '')
106
+ uncolorize(yield)
107
+ elsif text
108
+ uncolorize(text)
96
109
  elsif respond_to?(:to_str)
97
- to_str.gsub(COLORED_REGEXP, '')
110
+ uncolorize(to_str)
98
111
  else
99
112
  ''
100
113
  end
101
114
  end
102
115
 
103
- module_function
104
-
105
116
  # Returns an array of all Cucumber::Term::ANSIColor attributes as symbols.
106
117
  def attributes
107
118
  ATTRIBUTE_NAMES
108
119
  end
120
+
121
+ private
122
+
123
+ def colorize(text, color_code)
124
+ return String.new(text || '') unless Cucumber::Term::ANSIColor.coloring?
125
+ return "\e[#{color_code}m" unless text
126
+
127
+ "\e[#{color_code}m#{text}\e[0m"
128
+ end
129
+
130
+ def uncolorize(string)
131
+ string.gsub(COLORED_REGEXP, '')
132
+ end
109
133
  end
110
134
  end
111
135
  end
@@ -30,6 +30,7 @@ module Cucumber
30
30
 
31
31
  def display_span(span)
32
32
  return apply_modifiers(span.shift, span) if span.is_a?(Array)
33
+
33
34
  span
34
35
  end
35
36
 
data/lib/cucumber/version CHANGED
@@ -1 +1 @@
1
- 6.0.0
1
+ 8.0.0.rc.1
data/lib/cucumber.rb CHANGED
@@ -14,7 +14,8 @@ module Cucumber
14
14
 
15
15
  def logger
16
16
  return @log if @log
17
- @log = Logger.new(STDOUT)
17
+
18
+ @log = Logger.new($stdout)
18
19
  @log.level = Logger::INFO
19
20
  @log
20
21
  end
@@ -7,7 +7,7 @@ if ENV['SIMPLECOV']
7
7
 
8
8
  require 'simplecov'
9
9
 
10
- SimpleCov.root(File.expand_path(File.dirname(__FILE__) + '/..'))
10
+ SimpleCov.root(File.expand_path("#{File.dirname(__FILE__)}/.."))
11
11
  SimpleCov.start do
12
12
  add_filter 'iso-8859-1_steps.rb'
13
13
  add_filter '.-ruby-core/'