rspec-core 3.5.4 → 3.6.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 (43) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/Changelog.md +67 -2
  4. data/lib/rspec/core/bisect/server.rb +6 -1
  5. data/lib/rspec/core/configuration.rb +98 -21
  6. data/lib/rspec/core/configuration_options.rb +2 -0
  7. data/lib/rspec/core/drb.rb +2 -0
  8. data/lib/rspec/core/example.rb +9 -5
  9. data/lib/rspec/core/example_group.rb +6 -2
  10. data/lib/rspec/core/formatters/base_text_formatter.rb +3 -5
  11. data/lib/rspec/core/formatters/console_codes.rb +7 -4
  12. data/lib/rspec/core/formatters/documentation_formatter.rb +2 -1
  13. data/lib/rspec/core/formatters/exception_presenter.rb +8 -3
  14. data/lib/rspec/core/formatters/html_formatter.rb +4 -2
  15. data/lib/rspec/core/formatters/html_snippet_extractor.rb +2 -0
  16. data/lib/rspec/core/formatters/json_formatter.rb +7 -2
  17. data/lib/rspec/core/formatters/progress_formatter.rb +1 -0
  18. data/lib/rspec/core/formatters/protocol.rb +26 -25
  19. data/lib/rspec/core/formatters/snippet_extractor.rb +1 -3
  20. data/lib/rspec/core/{source → formatters}/syntax_highlighter.rb +21 -1
  21. data/lib/rspec/core/formatters.rb +15 -5
  22. data/lib/rspec/core/invocations.rb +22 -4
  23. data/lib/rspec/core/memoized_helpers.rb +3 -0
  24. data/lib/rspec/core/metadata_filter.rb +29 -17
  25. data/lib/rspec/core/notifications.rb +18 -2
  26. data/lib/rspec/core/option_parser.rb +23 -3
  27. data/lib/rspec/core/output_wrapper.rb +29 -0
  28. data/lib/rspec/core/project_initializer/.rspec +0 -1
  29. data/lib/rspec/core/project_initializer/spec/spec_helper.rb +1 -4
  30. data/lib/rspec/core/reporter.rb +22 -10
  31. data/lib/rspec/core/runner.rb +6 -1
  32. data/lib/rspec/core/set.rb +5 -0
  33. data/lib/rspec/core/shared_example_group.rb +39 -15
  34. data/lib/rspec/core/version.rb +1 -1
  35. data/lib/rspec/core/world.rb +13 -5
  36. data/lib/rspec/core.rb +1 -1
  37. data.tar.gz.sig +0 -0
  38. metadata +8 -11
  39. metadata.gz.sig +0 -0
  40. data/lib/rspec/core/source/location.rb +0 -13
  41. data/lib/rspec/core/source/node.rb +0 -93
  42. data/lib/rspec/core/source/token.rb +0 -87
  43. data/lib/rspec/core/source.rb +0 -86
@@ -33,7 +33,7 @@ module RSpec
33
33
  # This will only be invoked once, and the next one to be invoked
34
34
  # is {#example_group_started}.
35
35
  #
36
- # @param notification [StartNotification]
36
+ # @param notification [Notifications::StartNotification]
37
37
 
38
38
  # @method example_group_started
39
39
  # @api public
@@ -45,8 +45,8 @@ module RSpec
45
45
  # The next method to be invoked after this is {#example_passed},
46
46
  # {#example_pending}, or {#example_group_finished}.
47
47
  #
48
- # @param notification [GroupNotification] containing example_group
49
- # subclass of `RSpec::Core::ExampleGroup`
48
+ # @param notification [Notifications::GroupNotification] containing example_group
49
+ # subclass of {ExampleGroup}
50
50
 
51
51
  # @method example_group_finished
52
52
  # @api public
@@ -54,8 +54,8 @@ module RSpec
54
54
  #
55
55
  # Invoked at the end of the execution of each example group.
56
56
  #
57
- # @param notification [GroupNotification] containing example_group
58
- # subclass of `RSpec::Core::ExampleGroup`
57
+ # @param notification [Notifications::GroupNotification] containing example_group
58
+ # subclass of {ExampleGroup}
59
59
 
60
60
  # @method example_started
61
61
  # @api public
@@ -63,8 +63,8 @@ module RSpec
63
63
  #
64
64
  # Invoked at the beginning of the execution of each example.
65
65
  #
66
- # @param notification [ExampleNotification] containing example subclass
67
- # of `RSpec::Core::Example`
66
+ # @param notification [Notifications::ExampleNotification] containing example subclass
67
+ # of {Example}
68
68
 
69
69
  # @method example_finished
70
70
  # @api public
@@ -72,8 +72,8 @@ module RSpec
72
72
  #
73
73
  # Invoked at the end of the execution of each example.
74
74
  #
75
- # @param notification [ExampleNotification] containing example subclass
76
- # of `RSpec::Core::Example`
75
+ # @param notification [Notifications::ExampleNotification] containing example subclass
76
+ # of {Example}
77
77
 
78
78
  # @method example_passed
79
79
  # @api public
@@ -81,8 +81,8 @@ module RSpec
81
81
  #
82
82
  # Invoked when an example passes.
83
83
  #
84
- # @param notification [ExampleNotification] containing example subclass
85
- # of `RSpec::Core::Example`
84
+ # @param notification [Notifications::ExampleNotification] containing example subclass
85
+ # of {Example}
86
86
 
87
87
  # @method example_pending
88
88
  # @api public
@@ -90,8 +90,8 @@ module RSpec
90
90
  #
91
91
  # Invoked when an example is pending.
92
92
  #
93
- # @param notification [ExampleNotification] containing example subclass
94
- # of `RSpec::Core::Example`
93
+ # @param notification [Notifications::ExampleNotification] containing example subclass
94
+ # of {Example}
95
95
 
96
96
  # @method example_failed
97
97
  # @api public
@@ -99,8 +99,8 @@ module RSpec
99
99
  #
100
100
  # Invoked when an example fails.
101
101
  #
102
- # @param notification [ExampleNotification] containing example subclass
103
- # of `RSpec::Core::Example`
102
+ # @param notification [Notifications::ExampleNotification] containing example subclass
103
+ # of {Example}
104
104
 
105
105
  # @method message
106
106
  # @api public
@@ -108,7 +108,7 @@ module RSpec
108
108
  #
109
109
  # Used by the reporter to send messages to the output stream.
110
110
  #
111
- # @param notification [MessageNotification] containing message
111
+ # @param notification [Notifications::MessageNotification] containing message
112
112
 
113
113
  # @method stop
114
114
  # @api public
@@ -117,7 +117,7 @@ module RSpec
117
117
  # Invoked after all examples have executed, before dumping post-run
118
118
  # reports.
119
119
  #
120
- # @param notification [NullNotification]
120
+ # @param notification [Notifications::NullNotification]
121
121
 
122
122
  # @method start_dump
123
123
  # @api public
@@ -128,7 +128,7 @@ module RSpec
128
128
  # (BaseTextFormatter then calls {#dump_failures} once for each failed
129
129
  # example).
130
130
  #
131
- # @param notification [NullNotification]
131
+ # @param notification [Notifications::NullNotification]
132
132
 
133
133
  # @method dump_failures
134
134
  # @api public
@@ -136,7 +136,7 @@ module RSpec
136
136
  #
137
137
  # Dumps detailed information about each example failure.
138
138
  #
139
- # @param notification [NullNotification]
139
+ # @param notification [Notifications::NullNotification]
140
140
 
141
141
  # @method dump_summary
142
142
  # @api public
@@ -145,7 +145,7 @@ module RSpec
145
145
  # This method is invoked after the dumping of examples and failures.
146
146
  # Each parameter is assigned to a corresponding attribute.
147
147
  #
148
- # @param summary [SummaryNotification] containing duration,
148
+ # @param summary [Notifications::SummaryNotification] containing duration,
149
149
  # example_count, failure_count and pending_count
150
150
 
151
151
  # @method dump_profile
@@ -155,7 +155,7 @@ module RSpec
155
155
  # This method is invoked after the dumping the summary if profiling is
156
156
  # enabled.
157
157
  #
158
- # @param profile [ProfileNotification] containing duration,
158
+ # @param profile [Notifications::ProfileNotification] containing duration,
159
159
  # slowest_examples and slowest_example_groups
160
160
 
161
161
  # @method dump_pending
@@ -165,16 +165,17 @@ module RSpec
165
165
  # Outputs a report of pending examples. This gets invoked
166
166
  # after the summary if option is set to do so.
167
167
  #
168
- # @param notification [NullNotification]
168
+ # @param notification [Notifications::NullNotification]
169
169
 
170
170
  # @method close
171
171
  # @api public
172
172
  # @group Suite Notifications
173
173
  #
174
- # Invoked at the very end, `close` allows the formatter to clean
175
- # up resources, e.g. open streams, etc.
174
+ # Invoked at the end of a suite run. Allows the formatter to do any
175
+ # tidying up, but be aware that formatter output streams may be used
176
+ # elsewhere so don't actually close them.
176
177
  #
177
- # @param notification [NullNotification]
178
+ # @param notification [Notifications::NullNotification]
178
179
  end
179
180
  end
180
181
  end
@@ -1,5 +1,3 @@
1
- RSpec::Support.require_rspec_core "source"
2
-
3
1
  module RSpec
4
2
  module Core
5
3
  module Formatters
@@ -17,7 +15,7 @@ module RSpec
17
15
 
18
16
  def self.source_from_file(path)
19
17
  raise NoSuchFileError unless File.exist?(path)
20
- RSpec.world.source_cache.source_from_file(path)
18
+ RSpec.world.source_from_file(path)
21
19
  end
22
20
 
23
21
  if RSpec::Support::RubyFeatures.ripper_supported?
@@ -1,6 +1,6 @@
1
1
  module RSpec
2
2
  module Core
3
- class Source
3
+ module Formatters
4
4
  # @private
5
5
  # Provides terminal syntax highlighting of code snippets
6
6
  # when coderay is available.
@@ -31,12 +31,32 @@ module RSpec
31
31
  def color_enabled_implementation
32
32
  @color_enabled_implementation ||= begin
33
33
  require 'coderay'
34
+ self.class.attempt_to_add_rspec_terms_to_coderay_keywords
34
35
  CodeRayImplementation
35
36
  rescue LoadError
36
37
  NoSyntaxHighlightingImplementation
37
38
  end
38
39
  end
39
40
 
41
+ # rubocop:disable Lint/RescueException
42
+ # rubocop:disable Lint/HandleExceptions
43
+ def self.attempt_to_add_rspec_terms_to_coderay_keywords
44
+ CodeRay::Scanners::Ruby::Patterns::IDENT_KIND.add(%w[
45
+ describe context
46
+ it specify
47
+ before after around
48
+ let subject
49
+ expect allow
50
+ ], :keyword)
51
+ rescue Exception
52
+ # Mutating CodeRay's contants like this is not a public API
53
+ # and might not always work. If we cannot add our keywords
54
+ # to CodeRay it is not a big deal and not worth raising an
55
+ # error over, so we ignore it.
56
+ end
57
+ # rubocop:enable Lint/HandleExceptions
58
+ # rubocop:enable Lint/RescueException
59
+
40
60
  # @private
41
61
  module CodeRayImplementation
42
62
  RESET_CODE = "\e[0m"
@@ -24,7 +24,7 @@ RSpec::Support.require_rspec_support "directory_maker"
24
24
  # ## Custom Formatters
25
25
  #
26
26
  # You can tell RSpec to use a custom formatter by passing its path and name to
27
- # the `rspec` commmand. For example, if you define MyCustomFormatter in
27
+ # the `rspec` command. For example, if you define MyCustomFormatter in
28
28
  # path/to/my_custom_formatter.rb, you would type this command:
29
29
  #
30
30
  # rspec --require path/to/my_custom_formatter.rb --format MyCustomFormatter
@@ -115,6 +115,11 @@ module RSpec::Core::Formatters
115
115
  # @return [String] the default formatter to setup, defaults to `progress`
116
116
  attr_accessor :default_formatter
117
117
 
118
+ # @private
119
+ def prepare_default(output_stream, deprecation_stream)
120
+ reporter.prepare_default(self, output_stream, deprecation_stream)
121
+ end
122
+
118
123
  # @private
119
124
  def setup_default(output_stream, deprecation_stream)
120
125
  add default_formatter, output_stream if @formatters.empty?
@@ -140,7 +145,7 @@ module RSpec::Core::Formatters
140
145
  def add(formatter_to_use, *paths)
141
146
  formatter_class = find_formatter(formatter_to_use)
142
147
 
143
- args = paths.map { |p| p.respond_to?(:puts) ? p : file_at(p) }
148
+ args = paths.map { |p| p.respond_to?(:puts) ? p : open_stream(p) }
144
149
 
145
150
  if !Loader.formatters[formatter_class].nil?
146
151
  formatter = formatter_class.new(*args)
@@ -247,9 +252,14 @@ module RSpec::Core::Formatters
247
252
  word
248
253
  end
249
254
 
250
- def file_at(path)
251
- RSpec::Support::DirectoryMaker.mkdir_p(File.dirname(path))
252
- File.new(path, 'w')
255
+ def open_stream(path_or_wrapper)
256
+ if RSpec::Core::OutputWrapper === path_or_wrapper
257
+ path_or_wrapper.output = open_stream(path_or_wrapper.output)
258
+ path_or_wrapper
259
+ else
260
+ RSpec::Support::DirectoryMaker.mkdir_p(File.dirname(path_or_wrapper))
261
+ File.new(path_or_wrapper, 'w')
262
+ end
253
263
  end
254
264
  end
255
265
  end
@@ -49,16 +49,34 @@ module RSpec
49
49
  # @private
50
50
  class PrintVersion
51
51
  def call(_options, _err, out)
52
- out.puts RSpec::Core::Version::STRING
52
+ overall_version = RSpec::Core::Version::STRING
53
+ unless overall_version =~ /[a-zA-Z]+/
54
+ overall_version = overall_version.split('.').first(2).join('.')
55
+ end
56
+
57
+ out.puts "RSpec #{overall_version}"
58
+
59
+ [:Core, :Expectations, :Mocks, :Rails, :Support].each do |const_name|
60
+ lib_name = const_name.to_s.downcase
61
+ begin
62
+ require "rspec/#{lib_name}/version"
63
+ rescue LoadError
64
+ # Not worth mentioning libs that are not installed
65
+ nil
66
+ else
67
+ out.puts " - rspec-#{lib_name} #{RSpec.const_get(const_name)::Version::STRING}"
68
+ end
69
+ end
70
+
53
71
  0
54
72
  end
55
73
  end
56
74
 
57
75
  # @private
58
- PrintHelp = Struct.new(:parser, :invalid_options) do
76
+ PrintHelp = Struct.new(:parser, :hidden_options) do
59
77
  def call(_options, _err, out)
60
- # Removing the blank invalid options from the output.
61
- out.puts parser.to_s.gsub(/^\s+(#{invalid_options.join('|')})\s*$\n/, '')
78
+ # Removing the hidden options from the output.
79
+ out.puts parser.to_s.gsub(/^\s+(#{hidden_options.join('|')})\b.*$\n/, '')
62
80
  0
63
81
  end
64
82
  end
@@ -285,6 +285,9 @@ EOS
285
285
  # We have to pass the block directly to `define_method` to
286
286
  # allow it to use method constructs like `super` and `return`.
287
287
  raise "#let or #subject called without a block" if block.nil?
288
+ raise(
289
+ "#let or #subject called with a reserved name #initialize"
290
+ ) if :initialize == name
288
291
  MemoizedHelpers.module_for(self).__send__(:define_method, name, &block)
289
292
 
290
293
  # Apply the memoization. The method has been defined in an ancestor
@@ -13,24 +13,19 @@ module RSpec
13
13
  end
14
14
 
15
15
  # @private
16
- def filter_applies?(key, value, metadata)
16
+ def filter_applies?(key, filter_value, metadata)
17
17
  silence_metadata_example_group_deprecations do
18
- return location_filter_applies?(value, metadata) if key == :locations
19
- return id_filter_applies?(value, metadata) if key == :ids
20
- return filters_apply?(key, value, metadata) if Hash === value
21
-
22
- return false unless metadata.key?(key)
23
- return true if TrueClass === value && !!metadata[key]
24
- return filter_applies_to_any_value?(key, value, metadata) if Array === metadata[key] && !(Proc === value)
25
-
26
- case value
27
- when Regexp
28
- metadata[key] =~ value
29
- when Proc
30
- proc_filter_applies?(key, value, metadata)
31
- else
32
- metadata[key].to_s == value.to_s
33
- end
18
+ return location_filter_applies?(filter_value, metadata) if key == :locations
19
+ return id_filter_applies?(filter_value, metadata) if key == :ids
20
+ return filters_apply?(key, filter_value, metadata) if Hash === filter_value
21
+
22
+ meta_value = metadata.fetch(key) { return false }
23
+
24
+ return true if TrueClass === filter_value && meta_value
25
+ return proc_filter_applies?(key, filter_value, metadata) if Proc === filter_value
26
+ return filter_applies_to_any_value?(key, filter_value, metadata) if Array === meta_value
27
+
28
+ filter_value === meta_value || filter_value.to_s == meta_value.to_s
34
29
  end
35
30
  end
36
31
 
@@ -116,6 +111,10 @@ module RSpec
116
111
  @items_and_filters.unshift [item, metadata]
117
112
  end
118
113
 
114
+ def delete(item, metadata)
115
+ @items_and_filters.delete [item, metadata]
116
+ end
117
+
119
118
  def items_for(request_meta)
120
119
  @items_and_filters.each_with_object([]) do |(item, item_meta), to_return|
121
120
  to_return << item if item_meta.empty? ||
@@ -172,6 +171,11 @@ module RSpec
172
171
  handle_mutation(metadata)
173
172
  end
174
173
 
174
+ def delete(item, metadata)
175
+ super
176
+ reconstruct_caches
177
+ end
178
+
175
179
  def items_for(metadata)
176
180
  # The filtering of `metadata` to `applicable_metadata` is the key thing
177
181
  # that makes the memoization actually useful in practice, since each
@@ -196,6 +200,14 @@ module RSpec
196
200
 
197
201
  private
198
202
 
203
+ def reconstruct_caches
204
+ @applicable_keys.clear
205
+ @proc_keys.clear
206
+ @items_and_filters.each do |_item, metadata|
207
+ handle_mutation(metadata)
208
+ end
209
+ end
210
+
199
211
  def handle_mutation(metadata)
200
212
  @applicable_keys.merge(metadata.keys)
201
213
  @proc_keys.merge(proc_keys_from metadata)
@@ -1,3 +1,4 @@
1
+ RSpec::Support.require_rspec_core "formatters/console_codes"
1
2
  RSpec::Support.require_rspec_core "formatters/exception_presenter"
2
3
  RSpec::Support.require_rspec_core "formatters/helpers"
3
4
  RSpec::Support.require_rspec_core "shell_escape"
@@ -199,6 +200,12 @@ module RSpec::Core
199
200
  @exception_presenter.fully_formatted(failure_number, colorizer)
200
201
  end
201
202
 
203
+ # @return [Array<string>] The failure information fully formatted in the way that
204
+ # RSpec's built-in formatters emit, split by line.
205
+ def fully_formatted_lines(failure_number, colorizer=::RSpec::Core::Formatters::ConsoleCodes)
206
+ @exception_presenter.fully_formatted_lines(failure_number, colorizer)
207
+ end
208
+
202
209
  private
203
210
 
204
211
  def initialize(example, exception_presenter=Formatters::ExceptionPresenter::Factory.new(example).build)
@@ -280,8 +287,12 @@ module RSpec::Core
280
287
  # @attr pending_examples [Array<RSpec::Core::Example>] the pending examples
281
288
  # @attr load_time [Float] the number of seconds taken to boot RSpec
282
289
  # and load the spec files
290
+ # @attr errors_outside_of_examples_count [Integer] the number of errors that
291
+ # have occurred processing
292
+ # the spec suite
283
293
  SummaryNotification = Struct.new(:duration, :examples, :failed_examples,
284
- :pending_examples, :load_time)
294
+ :pending_examples, :load_time,
295
+ :errors_outside_of_examples_count)
285
296
  class SummaryNotification
286
297
  # @api
287
298
  # @return [Fixnum] the number of examples run
@@ -307,6 +318,11 @@ module RSpec::Core
307
318
  summary = Formatters::Helpers.pluralize(example_count, "example")
308
319
  summary << ", " << Formatters::Helpers.pluralize(failure_count, "failure")
309
320
  summary << ", #{pending_count} pending" if pending_count > 0
321
+ if errors_outside_of_examples_count > 0
322
+ summary << ", "
323
+ summary << Formatters::Helpers.pluralize(errors_outside_of_examples_count, "error")
324
+ summary << " occurred outside of examples"
325
+ end
310
326
  summary
311
327
  end
312
328
 
@@ -320,7 +336,7 @@ module RSpec::Core
320
336
  # specific colors.
321
337
  # @return [String] A colorized results line.
322
338
  def colorized_totals_line(colorizer=::RSpec::Core::Formatters::ConsoleCodes)
323
- if failure_count > 0
339
+ if failure_count > 0 || errors_outside_of_examples_count > 0
324
340
  colorizer.wrap(totals_line, RSpec.configuration.failure_color)
325
341
  elsif pending_count > 0
326
342
  colorizer.wrap(totals_line, RSpec.configuration.pending_color)
@@ -39,6 +39,8 @@ module RSpec::Core
39
39
  # rubocop:disable PerceivedComplexity
40
40
  def parser(options)
41
41
  OptionParser.new do |parser|
42
+ parser.summary_width = 34
43
+
42
44
  parser.banner = "Usage: rspec [options] [files or directories]\n\n"
43
45
 
44
46
  parser.on('-I PATH', 'Specify PATH to add to $LOAD_PATH (may be used more than once).') do |dirs|
@@ -131,8 +133,24 @@ module RSpec::Core
131
133
  options[:full_backtrace] = true
132
134
  end
133
135
 
134
- parser.on('-c', '--[no-]color', '--[no-]colour', 'Enable color in the output.') do |o|
135
- options[:color] = o
136
+ parser.on('-c', '--color', '--colour', '') do |_o|
137
+ # flag will be excluded from `--help` output because it is deprecated
138
+ options[:color] = true
139
+ options[:color_mode] = :automatic
140
+ end
141
+
142
+ parser.on('--force-color', '--force-colour', 'Force the output to be in color, even if the output is not a TTY') do |_o|
143
+ if options[:color_mode] == :off
144
+ abort "Please only use one of `--force-color` and `--no-color`"
145
+ end
146
+ options[:color_mode] = :on
147
+ end
148
+
149
+ parser.on('--no-color', '--no-colour', 'Force the output to not be in color, even if the output is a TTY') do |_o|
150
+ if options[:color_mode] == :on
151
+ abort "Please only use one of --force-color and --no-color"
152
+ end
153
+ options[:color_mode] = :off
136
154
  end
137
155
 
138
156
  parser.on('-p', '--[no-]profile [COUNT]',
@@ -256,8 +274,10 @@ FILTERING
256
274
  # trigger --default-path.
257
275
  invalid_options = %w[-d --I]
258
276
 
277
+ hidden_options = invalid_options + %w[-c]
278
+
259
279
  parser.on_tail('-h', '--help', "You're looking at it.") do
260
- options[:runner] = RSpec::Core::Invocations::PrintHelp.new(parser, invalid_options)
280
+ options[:runner] = RSpec::Core::Invocations::PrintHelp.new(parser, hidden_options)
261
281
  end
262
282
 
263
283
  # This prevents usage of the invalid_options.
@@ -0,0 +1,29 @@
1
+ module RSpec
2
+ module Core
3
+ # @private
4
+ class OutputWrapper
5
+ # @private
6
+ attr_accessor :output
7
+
8
+ # @private
9
+ def initialize(output)
10
+ @output = output
11
+ end
12
+
13
+ def respond_to?(name, priv=false)
14
+ output.respond_to?(name, priv)
15
+ end
16
+
17
+ def method_missing(name, *args, &block)
18
+ output.send(name, *args, &block)
19
+ end
20
+
21
+ # Redirect calls for IO interface methods
22
+ IO.instance_methods(false).each do |method|
23
+ define_method(method) do |*args, &block|
24
+ output.send(method, *args, &block)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,2 +1 @@
1
- --color
2
1
  --require spec_helper
@@ -12,9 +12,6 @@
12
12
  # the additional setup, and require it from the spec files that actually need
13
13
  # it.
14
14
  #
15
- # The `.rspec` file also contains a few flags that are not defaults but that
16
- # users commonly want.
17
- #
18
15
  # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
19
16
  RSpec.configure do |config|
20
17
  # rspec-expectations config goes here. You can use an alternate
@@ -80,7 +77,7 @@ RSpec.configure do |config|
80
77
  # Use the documentation formatter for detailed output,
81
78
  # unless a formatter has already been configured
82
79
  # (e.g. via a command-line flag).
83
- config.default_formatter = 'doc'
80
+ config.default_formatter = "doc"
84
81
  end
85
82
 
86
83
  # Print the 10 slowest examples and example groups at the
@@ -18,19 +18,14 @@ module RSpec::Core
18
18
  @failed_examples = []
19
19
  @pending_examples = []
20
20
  @duration = @start = @load_time = nil
21
+ @non_example_exception_count = 0
22
+ @setup_default = lambda {}
23
+ @setup = false
21
24
  end
22
25
 
23
26
  # @private
24
27
  attr_reader :examples, :failed_examples, :pending_examples
25
28
 
26
- # @private
27
- def reset
28
- @examples = []
29
- @failed_examples = []
30
- @pending_examples = []
31
- @profiler = Profiler.new if defined?(@profiler)
32
- end
33
-
34
29
  # @private
35
30
  def setup_profiler
36
31
  @profiler = Profiler.new
@@ -51,6 +46,13 @@ module RSpec::Core
51
46
  true
52
47
  end
53
48
 
49
+ # @private
50
+ def prepare_default(loader, output_stream, deprecation_stream)
51
+ @setup_default = lambda do
52
+ loader.setup_default output_stream, deprecation_stream
53
+ end
54
+ end
55
+
54
56
  # @private
55
57
  def registered_listeners(notification)
56
58
  @listeners[notification].to_a
@@ -153,10 +155,11 @@ module RSpec::Core
153
155
 
154
156
  # @private
155
157
  # Provides a way to notify of an exception that is not tied to any
156
- # particular exception (such as an exception encountered in a :suite hook).
158
+ # particular example (such as an exception encountered in a :suite hook).
157
159
  # Exceptions will be formatted the same way they normally are.
158
160
  def notify_non_example_exception(exception, context_description)
159
161
  @configuration.world.non_example_failure = true
162
+ @non_example_exception_count += 1
160
163
 
161
164
  example = Example.new(AnonymousExampleGroup, context_description, {})
162
165
  presenter = Formatters::ExceptionPresenter.new(exception, example, :indentation => 0)
@@ -177,7 +180,8 @@ module RSpec::Core
177
180
  @profiler.example_groups)
178
181
  end
179
182
  notify :dump_summary, Notifications::SummaryNotification.new(@duration, @examples, @failed_examples,
180
- @pending_examples, @load_time)
183
+ @pending_examples, @load_time,
184
+ @non_example_exception_count)
181
185
  notify :seed, Notifications::SeedNotification.new(@configuration.seed, seed_used?)
182
186
  end
183
187
  end
@@ -197,6 +201,7 @@ module RSpec::Core
197
201
 
198
202
  # @private
199
203
  def notify(event, notification)
204
+ ensure_listeners_ready
200
205
  registered_listeners(event).each do |formatter|
201
206
  formatter.__send__(event, notification)
202
207
  end
@@ -222,6 +227,13 @@ module RSpec::Core
222
227
 
223
228
  private
224
229
 
230
+ def ensure_listeners_ready
231
+ return if @setup
232
+
233
+ @setup_default.call
234
+ @setup = true
235
+ end
236
+
225
237
  def close
226
238
  notify :close, Notifications::NullNotification
227
239
  end
@@ -108,8 +108,13 @@ module RSpec
108
108
  # or the configured failure exit code (1 by default) if specs
109
109
  # failed.
110
110
  def run_specs(example_groups)
111
- success = @configuration.reporter.report(@world.example_count(example_groups)) do |reporter|
111
+ examples_count = @world.example_count(example_groups)
112
+ success = @configuration.reporter.report(examples_count) do |reporter|
112
113
  @configuration.with_suite_hooks do
114
+ if examples_count == 0 && @configuration.fail_if_no_examples
115
+ return @configuration.failure_exit_code
116
+ end
117
+
113
118
  example_groups.map { |g| g.run(reporter) }.all?
114
119
  end
115
120
  end && !@world.non_example_failure
@@ -44,6 +44,11 @@ module RSpec
44
44
  end
45
45
  self
46
46
  end
47
+
48
+ def clear
49
+ @values.clear
50
+ self
51
+ end
47
52
  end
48
53
  end
49
54
  end