rspec-core 3.8.2

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 (84) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/.document +5 -0
  5. data/.yardopts +8 -0
  6. data/Changelog.md +2243 -0
  7. data/LICENSE.md +26 -0
  8. data/README.md +384 -0
  9. data/exe/rspec +4 -0
  10. data/lib/rspec/autorun.rb +3 -0
  11. data/lib/rspec/core.rb +185 -0
  12. data/lib/rspec/core/backtrace_formatter.rb +65 -0
  13. data/lib/rspec/core/bisect/coordinator.rb +62 -0
  14. data/lib/rspec/core/bisect/example_minimizer.rb +173 -0
  15. data/lib/rspec/core/bisect/fork_runner.rb +134 -0
  16. data/lib/rspec/core/bisect/server.rb +61 -0
  17. data/lib/rspec/core/bisect/shell_command.rb +126 -0
  18. data/lib/rspec/core/bisect/shell_runner.rb +73 -0
  19. data/lib/rspec/core/bisect/utilities.rb +58 -0
  20. data/lib/rspec/core/configuration.rb +2308 -0
  21. data/lib/rspec/core/configuration_options.rb +233 -0
  22. data/lib/rspec/core/drb.rb +113 -0
  23. data/lib/rspec/core/dsl.rb +98 -0
  24. data/lib/rspec/core/example.rb +656 -0
  25. data/lib/rspec/core/example_group.rb +889 -0
  26. data/lib/rspec/core/example_status_persister.rb +235 -0
  27. data/lib/rspec/core/filter_manager.rb +231 -0
  28. data/lib/rspec/core/flat_map.rb +20 -0
  29. data/lib/rspec/core/formatters.rb +269 -0
  30. data/lib/rspec/core/formatters/base_bisect_formatter.rb +45 -0
  31. data/lib/rspec/core/formatters/base_formatter.rb +70 -0
  32. data/lib/rspec/core/formatters/base_text_formatter.rb +75 -0
  33. data/lib/rspec/core/formatters/bisect_drb_formatter.rb +29 -0
  34. data/lib/rspec/core/formatters/bisect_progress_formatter.rb +157 -0
  35. data/lib/rspec/core/formatters/console_codes.rb +68 -0
  36. data/lib/rspec/core/formatters/deprecation_formatter.rb +223 -0
  37. data/lib/rspec/core/formatters/documentation_formatter.rb +70 -0
  38. data/lib/rspec/core/formatters/exception_presenter.rb +508 -0
  39. data/lib/rspec/core/formatters/fallback_message_formatter.rb +28 -0
  40. data/lib/rspec/core/formatters/helpers.rb +110 -0
  41. data/lib/rspec/core/formatters/html_formatter.rb +153 -0
  42. data/lib/rspec/core/formatters/html_printer.rb +414 -0
  43. data/lib/rspec/core/formatters/html_snippet_extractor.rb +120 -0
  44. data/lib/rspec/core/formatters/json_formatter.rb +102 -0
  45. data/lib/rspec/core/formatters/profile_formatter.rb +68 -0
  46. data/lib/rspec/core/formatters/progress_formatter.rb +29 -0
  47. data/lib/rspec/core/formatters/protocol.rb +182 -0
  48. data/lib/rspec/core/formatters/snippet_extractor.rb +134 -0
  49. data/lib/rspec/core/formatters/syntax_highlighter.rb +91 -0
  50. data/lib/rspec/core/hooks.rb +624 -0
  51. data/lib/rspec/core/invocations.rb +87 -0
  52. data/lib/rspec/core/memoized_helpers.rb +554 -0
  53. data/lib/rspec/core/metadata.rb +498 -0
  54. data/lib/rspec/core/metadata_filter.rb +255 -0
  55. data/lib/rspec/core/minitest_assertions_adapter.rb +31 -0
  56. data/lib/rspec/core/mocking_adapters/flexmock.rb +31 -0
  57. data/lib/rspec/core/mocking_adapters/mocha.rb +57 -0
  58. data/lib/rspec/core/mocking_adapters/null.rb +14 -0
  59. data/lib/rspec/core/mocking_adapters/rr.rb +31 -0
  60. data/lib/rspec/core/mocking_adapters/rspec.rb +32 -0
  61. data/lib/rspec/core/notifications.rb +521 -0
  62. data/lib/rspec/core/option_parser.rb +309 -0
  63. data/lib/rspec/core/ordering.rb +158 -0
  64. data/lib/rspec/core/output_wrapper.rb +29 -0
  65. data/lib/rspec/core/pending.rb +165 -0
  66. data/lib/rspec/core/profiler.rb +34 -0
  67. data/lib/rspec/core/project_initializer.rb +48 -0
  68. data/lib/rspec/core/project_initializer/.rspec +1 -0
  69. data/lib/rspec/core/project_initializer/spec/spec_helper.rb +100 -0
  70. data/lib/rspec/core/rake_task.rb +168 -0
  71. data/lib/rspec/core/reporter.rb +257 -0
  72. data/lib/rspec/core/ruby_project.rb +53 -0
  73. data/lib/rspec/core/runner.rb +199 -0
  74. data/lib/rspec/core/sandbox.rb +37 -0
  75. data/lib/rspec/core/set.rb +54 -0
  76. data/lib/rspec/core/shared_context.rb +55 -0
  77. data/lib/rspec/core/shared_example_group.rb +269 -0
  78. data/lib/rspec/core/shell_escape.rb +49 -0
  79. data/lib/rspec/core/test_unit_assertions_adapter.rb +30 -0
  80. data/lib/rspec/core/version.rb +9 -0
  81. data/lib/rspec/core/warnings.rb +40 -0
  82. data/lib/rspec/core/world.rb +275 -0
  83. metadata +292 -0
  84. metadata.gz.sig +0 -0
@@ -0,0 +1,20 @@
1
+ module RSpec
2
+ module Core
3
+ # @private
4
+ module FlatMap
5
+ if [].respond_to?(:flat_map)
6
+ def flat_map(array, &block)
7
+ array.flat_map(&block)
8
+ end
9
+ else # for 1.8.7
10
+ # :nocov:
11
+ def flat_map(array, &block)
12
+ array.map(&block).flatten(1)
13
+ end
14
+ # :nocov:
15
+ end
16
+
17
+ module_function :flat_map
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,269 @@
1
+ RSpec::Support.require_rspec_support "directory_maker"
2
+ # ## Built-in Formatters
3
+ #
4
+ # * progress (default) - Prints dots for passing examples, `F` for failures, `*`
5
+ # for pending.
6
+ # * documentation - Prints the docstrings passed to `describe` and `it` methods
7
+ # (and their aliases).
8
+ # * html
9
+ # * json - Useful for archiving data for subsequent analysis.
10
+ #
11
+ # The progress formatter is the default, but you can choose any one or more of
12
+ # the other formatters by passing with the `--format` (or `-f` for short)
13
+ # command-line option, e.g.
14
+ #
15
+ # rspec --format documentation
16
+ #
17
+ # You can also send the output of multiple formatters to different streams, e.g.
18
+ #
19
+ # rspec --format documentation --format html --out results.html
20
+ #
21
+ # This example sends the output of the documentation formatter to `$stdout`, and
22
+ # the output of the html formatter to results.html.
23
+ #
24
+ # ## Custom Formatters
25
+ #
26
+ # You can tell RSpec to use a custom formatter by passing its path and name to
27
+ # the `rspec` command. For example, if you define MyCustomFormatter in
28
+ # path/to/my_custom_formatter.rb, you would type this command:
29
+ #
30
+ # rspec --require path/to/my_custom_formatter.rb --format MyCustomFormatter
31
+ #
32
+ # The reporter calls every formatter with this protocol:
33
+ #
34
+ # * To start
35
+ # * `start(StartNotification)`
36
+ # * Once per example group
37
+ # * `example_group_started(GroupNotification)`
38
+ # * Once per example
39
+ # * `example_started(ExampleNotification)`
40
+ # * One of these per example, depending on outcome
41
+ # * `example_passed(ExampleNotification)`
42
+ # * `example_failed(FailedExampleNotification)`
43
+ # * `example_pending(ExampleNotification)`
44
+ # * Optionally at any time
45
+ # * `message(MessageNotification)`
46
+ # * At the end of the suite
47
+ # * `stop(ExamplesNotification)`
48
+ # * `start_dump(NullNotification)`
49
+ # * `dump_pending(ExamplesNotification)`
50
+ # * `dump_failures(ExamplesNotification)`
51
+ # * `dump_summary(SummaryNotification)`
52
+ # * `seed(SeedNotification)`
53
+ # * `close(NullNotification)`
54
+ #
55
+ # Only the notifications to which you subscribe your formatter will be called
56
+ # on your formatter. To subscribe your formatter use:
57
+ # `RSpec::Core::Formatters#register` e.g.
58
+ #
59
+ # `RSpec::Core::Formatters.register FormatterClassName, :example_passed, :example_failed`
60
+ #
61
+ # We recommend you implement the methods yourself; for simplicity we provide the
62
+ # default formatter output via our notification objects but if you prefer you
63
+ # can subclass `RSpec::Core::Formatters::BaseTextFormatter` and override the
64
+ # methods you wish to enhance.
65
+ #
66
+ # @see RSpec::Core::Formatters::BaseTextFormatter
67
+ # @see RSpec::Core::Reporter
68
+ module RSpec::Core::Formatters
69
+ autoload :DocumentationFormatter, 'rspec/core/formatters/documentation_formatter'
70
+ autoload :HtmlFormatter, 'rspec/core/formatters/html_formatter'
71
+ autoload :FallbackMessageFormatter, 'rspec/core/formatters/fallback_message_formatter'
72
+ autoload :ProgressFormatter, 'rspec/core/formatters/progress_formatter'
73
+ autoload :ProfileFormatter, 'rspec/core/formatters/profile_formatter'
74
+ autoload :JsonFormatter, 'rspec/core/formatters/json_formatter'
75
+ autoload :BisectDRbFormatter, 'rspec/core/formatters/bisect_drb_formatter'
76
+ autoload :ExceptionPresenter, 'rspec/core/formatters/exception_presenter'
77
+
78
+ # Register the formatter class
79
+ # @param formatter_class [Class] formatter class to register
80
+ # @param notifications [Symbol, ...] one or more notifications to be
81
+ # registered to the specified formatter
82
+ #
83
+ # @see RSpec::Core::Formatters::BaseFormatter
84
+ def self.register(formatter_class, *notifications)
85
+ Loader.formatters[formatter_class] = notifications
86
+ end
87
+
88
+ # @api private
89
+ #
90
+ # `RSpec::Core::Formatters::Loader` is an internal class for
91
+ # managing formatters used by a particular configuration. It is
92
+ # not expected to be used directly, but only through the configuration
93
+ # interface.
94
+ class Loader
95
+ # @api private
96
+ #
97
+ # Internal formatters are stored here when loaded.
98
+ def self.formatters
99
+ @formatters ||= {}
100
+ end
101
+
102
+ # @api private
103
+ def initialize(reporter)
104
+ @formatters = []
105
+ @reporter = reporter
106
+ self.default_formatter = 'progress'
107
+ end
108
+
109
+ # @return [Array] the loaded formatters
110
+ attr_reader :formatters
111
+
112
+ # @return [Reporter] the reporter
113
+ attr_reader :reporter
114
+
115
+ # @return [String] the default formatter to setup, defaults to `progress`
116
+ attr_accessor :default_formatter
117
+
118
+ # @private
119
+ def prepare_default(output_stream, deprecation_stream)
120
+ reporter.prepare_default(self, output_stream, deprecation_stream)
121
+ end
122
+
123
+ # @private
124
+ def setup_default(output_stream, deprecation_stream)
125
+ add default_formatter, output_stream if @formatters.empty?
126
+
127
+ unless @formatters.any? { |formatter| DeprecationFormatter === formatter }
128
+ add DeprecationFormatter, deprecation_stream, output_stream
129
+ end
130
+
131
+ unless existing_formatter_implements?(:message)
132
+ add FallbackMessageFormatter, output_stream
133
+ end
134
+
135
+ return unless RSpec.configuration.profile_examples?
136
+ return if existing_formatter_implements?(:dump_profile)
137
+
138
+ add RSpec::Core::Formatters::ProfileFormatter, output_stream
139
+ end
140
+
141
+ # @private
142
+ def add(formatter_to_use, *paths)
143
+ # If a formatter instance was passed, we can register it directly,
144
+ # with no need for any of the further processing that happens below.
145
+ if Loader.formatters.key?(formatter_to_use.class)
146
+ register formatter_to_use, notifications_for(formatter_to_use.class)
147
+ return
148
+ end
149
+
150
+ formatter_class = find_formatter(formatter_to_use)
151
+
152
+ args = paths.map { |p| p.respond_to?(:puts) ? p : open_stream(p) }
153
+
154
+ if !Loader.formatters[formatter_class].nil?
155
+ formatter = formatter_class.new(*args)
156
+ register formatter, notifications_for(formatter_class)
157
+ elsif defined?(RSpec::LegacyFormatters)
158
+ formatter = RSpec::LegacyFormatters.load_formatter formatter_class, *args
159
+ register formatter, formatter.notifications
160
+ else
161
+ call_site = "Formatter added at: #{::RSpec::CallerFilter.first_non_rspec_line}"
162
+
163
+ RSpec.warn_deprecation <<-WARNING.gsub(/\s*\|/, ' ')
164
+ |The #{formatter_class} formatter uses the deprecated formatter
165
+ |interface not supported directly by RSpec 3.
166
+ |
167
+ |To continue to use this formatter you must install the
168
+ |`rspec-legacy_formatters` gem, which provides support
169
+ |for legacy formatters or upgrade the formatter to a
170
+ |compatible version.
171
+ |
172
+ |#{call_site}
173
+ WARNING
174
+ end
175
+ end
176
+
177
+ private
178
+
179
+ def find_formatter(formatter_to_use)
180
+ built_in_formatter(formatter_to_use) ||
181
+ custom_formatter(formatter_to_use) ||
182
+ (raise ArgumentError, "Formatter '#{formatter_to_use}' unknown - " \
183
+ "maybe you meant 'documentation' or 'progress'?.")
184
+ end
185
+
186
+ def register(formatter, notifications)
187
+ return if duplicate_formatter_exists?(formatter)
188
+ @reporter.register_listener formatter, *notifications
189
+ @formatters << formatter
190
+ formatter
191
+ end
192
+
193
+ def duplicate_formatter_exists?(new_formatter)
194
+ @formatters.any? do |formatter|
195
+ formatter.class == new_formatter.class && formatter.output == new_formatter.output
196
+ end
197
+ end
198
+
199
+ def existing_formatter_implements?(notification)
200
+ @reporter.registered_listeners(notification).any?
201
+ end
202
+
203
+ def built_in_formatter(key)
204
+ case key.to_s
205
+ when 'd', 'doc', 'documentation'
206
+ DocumentationFormatter
207
+ when 'h', 'html'
208
+ HtmlFormatter
209
+ when 'p', 'progress'
210
+ ProgressFormatter
211
+ when 'j', 'json'
212
+ JsonFormatter
213
+ when 'bisect-drb'
214
+ BisectDRbFormatter
215
+ end
216
+ end
217
+
218
+ def notifications_for(formatter_class)
219
+ formatter_class.ancestors.inject(::RSpec::Core::Set.new) do |notifications, klass|
220
+ notifications.merge Loader.formatters.fetch(klass) { ::RSpec::Core::Set.new }
221
+ end
222
+ end
223
+
224
+ def custom_formatter(formatter_ref)
225
+ if Class === formatter_ref
226
+ formatter_ref
227
+ elsif string_const?(formatter_ref)
228
+ begin
229
+ formatter_ref.gsub(/^::/, '').split('::').inject(Object) { |a, e| a.const_get e }
230
+ rescue NameError
231
+ require(path_for(formatter_ref)) ? retry : raise
232
+ end
233
+ end
234
+ end
235
+
236
+ def string_const?(str)
237
+ str.is_a?(String) && /\A[A-Z][a-zA-Z0-9_:]*\z/ =~ str
238
+ end
239
+
240
+ def path_for(const_ref)
241
+ underscore_with_fix_for_non_standard_rspec_naming(const_ref)
242
+ end
243
+
244
+ def underscore_with_fix_for_non_standard_rspec_naming(string)
245
+ underscore(string).sub(%r{(^|/)r_spec($|/)}, '\\1rspec\\2')
246
+ end
247
+
248
+ # activesupport/lib/active_support/inflector/methods.rb, line 48
249
+ def underscore(camel_cased_word)
250
+ word = camel_cased_word.to_s.dup
251
+ word.gsub!(/::/, '/')
252
+ word.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
253
+ word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
254
+ word.tr!("-", "_")
255
+ word.downcase!
256
+ word
257
+ end
258
+
259
+ def open_stream(path_or_wrapper)
260
+ if RSpec::Core::OutputWrapper === path_or_wrapper
261
+ path_or_wrapper.output = open_stream(path_or_wrapper.output)
262
+ path_or_wrapper
263
+ else
264
+ RSpec::Support::DirectoryMaker.mkdir_p(File.dirname(path_or_wrapper))
265
+ File.new(path_or_wrapper, 'w')
266
+ end
267
+ end
268
+ end
269
+ end
@@ -0,0 +1,45 @@
1
+ RSpec::Support.require_rspec_core "bisect/utilities"
2
+
3
+ module RSpec
4
+ module Core
5
+ module Formatters
6
+ # Contains common logic for formatters used by `--bisect` to communicate results
7
+ # back to the bisect runner.
8
+ #
9
+ # Subclasses must define a `notify_results(all_example_ids, failed_example_ids)`
10
+ # method.
11
+ # @private
12
+ class BaseBisectFormatter
13
+ def self.inherited(formatter)
14
+ Formatters.register formatter, :start_dump, :example_failed, :example_finished
15
+ end
16
+
17
+ def initialize(expected_failures)
18
+ @all_example_ids = []
19
+ @failed_example_ids = []
20
+ @remaining_failures = expected_failures
21
+ end
22
+
23
+ def example_failed(notification)
24
+ @failed_example_ids << notification.example.id
25
+ end
26
+
27
+ def example_finished(notification)
28
+ @all_example_ids << notification.example.id
29
+ return unless @remaining_failures.include?(notification.example.id)
30
+ @remaining_failures.delete(notification.example.id)
31
+
32
+ status = notification.example.execution_result.status
33
+ return if status == :failed && !@remaining_failures.empty?
34
+ RSpec.world.wants_to_quit = true
35
+ end
36
+
37
+ def start_dump(_notification)
38
+ # `notify_results` is defined in the subclass
39
+ notify_results(Bisect::ExampleSetDescriptor.new(
40
+ @all_example_ids, @failed_example_ids))
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,70 @@
1
+ RSpec::Support.require_rspec_core "formatters/helpers"
2
+ require 'stringio'
3
+
4
+ module RSpec
5
+ module Core
6
+ module Formatters
7
+ # RSpec's built-in formatters are all subclasses of
8
+ # RSpec::Core::Formatters::BaseFormatter.
9
+ #
10
+ # @see RSpec::Core::Formatters::BaseTextFormatter
11
+ # @see RSpec::Core::Reporter
12
+ # @see RSpec::Core::Formatters::Protocol
13
+ class BaseFormatter
14
+ # All formatters inheriting from this formatter will receive these
15
+ # notifications.
16
+ Formatters.register self, :start, :example_group_started, :close
17
+ attr_accessor :example_group
18
+ attr_reader :output
19
+
20
+ # @api public
21
+ # @param output [IO] the formatter output
22
+ # @see RSpec::Core::Formatters::Protocol#initialize
23
+ def initialize(output)
24
+ @output = output || StringIO.new
25
+ @example_group = nil
26
+ end
27
+
28
+ # @api public
29
+ #
30
+ # @param notification [StartNotification]
31
+ # @see RSpec::Core::Formatters::Protocol#start
32
+ def start(notification)
33
+ start_sync_output
34
+ @example_count = notification.count
35
+ end
36
+
37
+ # @api public
38
+ #
39
+ # @param notification [GroupNotification] containing example_group
40
+ # subclass of `RSpec::Core::ExampleGroup`
41
+ # @see RSpec::Core::Formatters::Protocol#example_group_started
42
+ def example_group_started(notification)
43
+ @example_group = notification.group
44
+ end
45
+
46
+ # @api public
47
+ #
48
+ # @param _notification [NullNotification] (Ignored)
49
+ # @see RSpec::Core::Formatters::Protocol#close
50
+ def close(_notification)
51
+ restore_sync_output
52
+ end
53
+
54
+ private
55
+
56
+ def start_sync_output
57
+ @old_sync, output.sync = output.sync, true if output_supports_sync
58
+ end
59
+
60
+ def restore_sync_output
61
+ output.sync = @old_sync if output_supports_sync && !output.closed?
62
+ end
63
+
64
+ def output_supports_sync
65
+ output.respond_to?(:sync=)
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,75 @@
1
+ RSpec::Support.require_rspec_core "formatters/base_formatter"
2
+
3
+ module RSpec
4
+ module Core
5
+ module Formatters
6
+ # Base for all of RSpec's built-in formatters. See
7
+ # RSpec::Core::Formatters::BaseFormatter to learn more about all of the
8
+ # methods called by the reporter.
9
+ #
10
+ # @see RSpec::Core::Formatters::BaseFormatter
11
+ # @see RSpec::Core::Reporter
12
+ class BaseTextFormatter < BaseFormatter
13
+ Formatters.register self,
14
+ :message, :dump_summary, :dump_failures, :dump_pending, :seed
15
+
16
+ # @api public
17
+ #
18
+ # Used by the reporter to send messages to the output stream.
19
+ #
20
+ # @param notification [MessageNotification] containing message
21
+ def message(notification)
22
+ output.puts notification.message
23
+ end
24
+
25
+ # @api public
26
+ #
27
+ # Dumps detailed information about each example failure.
28
+ #
29
+ # @param notification [NullNotification]
30
+ def dump_failures(notification)
31
+ return if notification.failure_notifications.empty?
32
+ output.puts notification.fully_formatted_failed_examples
33
+ end
34
+
35
+ # @api public
36
+ #
37
+ # This method is invoked after the dumping of examples and failures.
38
+ # Each parameter is assigned to a corresponding attribute.
39
+ #
40
+ # @param summary [SummaryNotification] containing duration,
41
+ # example_count, failure_count and pending_count
42
+ def dump_summary(summary)
43
+ output.puts summary.fully_formatted
44
+ end
45
+
46
+ # @private
47
+ def dump_pending(notification)
48
+ return if notification.pending_examples.empty?
49
+ output.puts notification.fully_formatted_pending_examples
50
+ end
51
+
52
+ # @private
53
+ def seed(notification)
54
+ return unless notification.seed_used?
55
+ output.puts notification.fully_formatted
56
+ end
57
+
58
+ # @api public
59
+ #
60
+ # Invoked at the end of a suite run. Allows the formatter to do any
61
+ # tidying up, but be aware that formatter output streams may be used
62
+ # elsewhere so don't actually close them.
63
+ #
64
+ # @param _notification [NullNotification] (Ignored)
65
+ def close(_notification)
66
+ return if output.closed?
67
+
68
+ output.puts
69
+
70
+ output.flush
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end