rspec-core 3.8.2

Sign up to get free protection for your applications and to get access to all the features.
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,37 @@
1
+ module RSpec
2
+ module Core
3
+ # A sandbox isolates the enclosed code into an environment that looks 'new'
4
+ # meaning globally accessed objects are reset for the duration of the
5
+ # sandbox.
6
+ #
7
+ # @note This module is not normally available. You must require
8
+ # `rspec/core/sandbox` to load it.
9
+ module Sandbox
10
+ # Execute a provided block with RSpec global objects (configuration,
11
+ # world) reset. This is used to test RSpec with RSpec.
12
+ #
13
+ # When calling this the configuration is passed into the provided block.
14
+ # Use this to set custom configs for your sandboxed examples.
15
+ #
16
+ # ```
17
+ # Sandbox.sandboxed do |config|
18
+ # config.before(:context) { RSpec.current_example = nil }
19
+ # end
20
+ # ```
21
+ def self.sandboxed
22
+ orig_config = RSpec.configuration
23
+ orig_world = RSpec.world
24
+ orig_example = RSpec.current_example
25
+
26
+ RSpec.configuration = RSpec::Core::Configuration.new
27
+ RSpec.world = RSpec::Core::World.new(RSpec.configuration)
28
+
29
+ yield RSpec.configuration
30
+ ensure
31
+ RSpec.configuration = orig_config
32
+ RSpec.world = orig_world
33
+ RSpec.current_example = orig_example
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,54 @@
1
+ module RSpec
2
+ module Core
3
+ # @private
4
+ #
5
+ # We use this to replace `::Set` so we can have the advantage of
6
+ # constant time key lookups for unique arrays but without the
7
+ # potential to pollute a developers environment with an extra
8
+ # piece of the stdlib. This helps to prevent false positive
9
+ # builds.
10
+ #
11
+ class Set
12
+ include Enumerable
13
+
14
+ def initialize(array=[])
15
+ @values = {}
16
+ merge(array)
17
+ end
18
+
19
+ def empty?
20
+ @values.empty?
21
+ end
22
+
23
+ def <<(key)
24
+ @values[key] = true
25
+ self
26
+ end
27
+
28
+ def delete(key)
29
+ @values.delete(key)
30
+ end
31
+
32
+ def each(&block)
33
+ @values.keys.each(&block)
34
+ self
35
+ end
36
+
37
+ def include?(key)
38
+ @values.key?(key)
39
+ end
40
+
41
+ def merge(values)
42
+ values.each do |key|
43
+ @values[key] = true
44
+ end
45
+ self
46
+ end
47
+
48
+ def clear
49
+ @values.clear
50
+ self
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,55 @@
1
+ module RSpec
2
+ module Core
3
+ # Exposes {ExampleGroup}-level methods to a module, so you can include that
4
+ # module in an {ExampleGroup}.
5
+ #
6
+ # @example
7
+ #
8
+ # module LoggedInAsAdmin
9
+ # extend RSpec::Core::SharedContext
10
+ # before(:example) do
11
+ # log_in_as :admin
12
+ # end
13
+ # end
14
+ #
15
+ # describe "admin section" do
16
+ # include LoggedInAsAdmin
17
+ # # ...
18
+ # end
19
+ module SharedContext
20
+ # @private
21
+ def included(group)
22
+ __shared_context_recordings.each do |recording|
23
+ recording.playback_onto(group)
24
+ end
25
+ end
26
+
27
+ # @private
28
+ def __shared_context_recordings
29
+ @__shared_context_recordings ||= []
30
+ end
31
+
32
+ # @private
33
+ Recording = Struct.new(:method_name, :args, :block) do
34
+ def playback_onto(group)
35
+ group.__send__(method_name, *args, &block)
36
+ end
37
+ end
38
+
39
+ # @private
40
+ def self.record(methods)
41
+ methods.each do |meth|
42
+ define_method(meth) do |*args, &block|
43
+ __shared_context_recordings << Recording.new(meth, args, block)
44
+ end
45
+ end
46
+ end
47
+
48
+ # @private
49
+ record [:describe, :context] + Hooks.instance_methods(false) +
50
+ MemoizedHelpers::ClassMethods.instance_methods(false)
51
+ end
52
+ end
53
+ # @private
54
+ SharedContext = Core::SharedContext
55
+ end
@@ -0,0 +1,269 @@
1
+ module RSpec
2
+ module Core
3
+ # Represents some functionality that is shared with multiple example groups.
4
+ # The functionality is defined by the provided block, which is lazily
5
+ # eval'd when the `SharedExampleGroupModule` instance is included in an example
6
+ # group.
7
+ class SharedExampleGroupModule < Module
8
+ # @private
9
+ attr_reader :definition
10
+
11
+ def initialize(description, definition, metadata)
12
+ @description = description
13
+ @definition = definition
14
+ @metadata = metadata
15
+ end
16
+
17
+ # Provides a human-readable representation of this module.
18
+ def inspect
19
+ "#<#{self.class.name} #{@description.inspect}>"
20
+ end
21
+ alias to_s inspect
22
+
23
+ # Ruby callback for when a module is included in another module is class.
24
+ # Our definition evaluates the shared group block in the context of the
25
+ # including example group.
26
+ def included(klass)
27
+ inclusion_line = klass.metadata[:location]
28
+ include_in klass, inclusion_line, [], nil
29
+ end
30
+
31
+ # @private
32
+ def include_in(klass, inclusion_line, args, customization_block)
33
+ klass.update_inherited_metadata(@metadata) unless @metadata.empty?
34
+
35
+ SharedExampleGroupInclusionStackFrame.with_frame(@description, inclusion_line) do
36
+ klass.class_exec(*args, &@definition)
37
+ klass.class_exec(&customization_block) if customization_block
38
+ end
39
+ end
40
+ end
41
+
42
+ # Shared example groups let you define common context and/or common
43
+ # examples that you wish to use in multiple example groups.
44
+ #
45
+ # When defined, the shared group block is stored for later evaluation.
46
+ # It can later be included in an example group either explicitly
47
+ # (using `include_examples`, `include_context` or `it_behaves_like`)
48
+ # or implicitly (via matching metadata).
49
+ #
50
+ # Named shared example groups are scoped based on where they are
51
+ # defined. Shared groups defined in an example group are available
52
+ # for inclusion in that example group or any child example groups,
53
+ # but not in any parent or sibling example groups. Shared example
54
+ # groups defined at the top level can be included from any example group.
55
+ module SharedExampleGroup
56
+ # @overload shared_examples(name, &block)
57
+ # @param name [String, Symbol, Module] identifer to use when looking up
58
+ # this shared group
59
+ # @param block The block to be eval'd
60
+ # @overload shared_examples(name, metadata, &block)
61
+ # @param name [String, Symbol, Module] identifer to use when looking up
62
+ # this shared group
63
+ # @param metadata [Array<Symbol>, Hash] metadata to attach to this
64
+ # group; any example group or example with matching metadata will
65
+ # automatically include this shared example group.
66
+ # @param block The block to be eval'd
67
+ #
68
+ # Stores the block for later use. The block will be evaluated
69
+ # in the context of an example group via `include_examples`,
70
+ # `include_context`, or `it_behaves_like`.
71
+ #
72
+ # @example
73
+ # shared_examples "auditable" do
74
+ # it "stores an audit record on save!" do
75
+ # expect { auditable.save! }.to change(Audit, :count).by(1)
76
+ # end
77
+ # end
78
+ #
79
+ # describe Account do
80
+ # it_behaves_like "auditable" do
81
+ # let(:auditable) { Account.new }
82
+ # end
83
+ # end
84
+ #
85
+ # @see ExampleGroup.it_behaves_like
86
+ # @see ExampleGroup.include_examples
87
+ # @see ExampleGroup.include_context
88
+ def shared_examples(name, *args, &block)
89
+ top_level = self == ExampleGroup
90
+ if top_level && RSpec::Support.thread_local_data[:in_example_group]
91
+ raise "Creating isolated shared examples from within a context is " \
92
+ "not allowed. Remove `RSpec.` prefix or move this to a " \
93
+ "top-level scope."
94
+ end
95
+
96
+ RSpec.world.shared_example_group_registry.add(self, name, *args, &block)
97
+ end
98
+ alias shared_context shared_examples
99
+ alias shared_examples_for shared_examples
100
+
101
+ # @api private
102
+ #
103
+ # Shared examples top level DSL.
104
+ module TopLevelDSL
105
+ # @private
106
+ def self.definitions
107
+ proc do
108
+ def shared_examples(name, *args, &block)
109
+ RSpec.world.shared_example_group_registry.add(:main, name, *args, &block)
110
+ end
111
+ alias shared_context shared_examples
112
+ alias shared_examples_for shared_examples
113
+ end
114
+ end
115
+
116
+ # @private
117
+ def self.exposed_globally?
118
+ @exposed_globally ||= false
119
+ end
120
+
121
+ # @api private
122
+ #
123
+ # Adds the top level DSL methods to Module and the top level binding.
124
+ def self.expose_globally!
125
+ return if exposed_globally?
126
+ Core::DSL.change_global_dsl(&definitions)
127
+ @exposed_globally = true
128
+ end
129
+
130
+ # @api private
131
+ #
132
+ # Removes the top level DSL methods to Module and the top level binding.
133
+ def self.remove_globally!
134
+ return unless exposed_globally?
135
+
136
+ Core::DSL.change_global_dsl do
137
+ undef shared_examples
138
+ undef shared_context
139
+ undef shared_examples_for
140
+ end
141
+
142
+ @exposed_globally = false
143
+ end
144
+ end
145
+
146
+ # @private
147
+ class Registry
148
+ def add(context, name, *metadata_args, &block)
149
+ unless block
150
+ RSpec.warning "Shared example group #{name} was defined without a "\
151
+ "block and will have no effect. Please define a "\
152
+ "block or remove the definition."
153
+ end
154
+
155
+ if RSpec.configuration.shared_context_metadata_behavior == :trigger_inclusion
156
+ return legacy_add(context, name, *metadata_args, &block)
157
+ end
158
+
159
+ unless valid_name?(name)
160
+ raise ArgumentError, "Shared example group names can only be a string, " \
161
+ "symbol or module but got: #{name.inspect}"
162
+ end
163
+
164
+ ensure_block_has_source_location(block) { CallerFilter.first_non_rspec_line }
165
+ warn_if_key_taken context, name, block
166
+
167
+ metadata = Metadata.build_hash_from(metadata_args)
168
+ shared_module = SharedExampleGroupModule.new(name, block, metadata)
169
+ shared_example_groups[context][name] = shared_module
170
+ end
171
+
172
+ def find(lookup_contexts, name)
173
+ lookup_contexts.each do |context|
174
+ found = shared_example_groups[context][name]
175
+ return found if found
176
+ end
177
+
178
+ shared_example_groups[:main][name]
179
+ end
180
+
181
+ private
182
+
183
+ # TODO: remove this in RSpec 4. This exists only to support
184
+ # `config.shared_context_metadata_behavior == :trigger_inclusion`,
185
+ # the legacy behavior of shared context metadata, which we do
186
+ # not want to support in RSpec 4.
187
+ def legacy_add(context, name, *metadata_args, &block)
188
+ ensure_block_has_source_location(block) { CallerFilter.first_non_rspec_line }
189
+ shared_module = SharedExampleGroupModule.new(name, block, {})
190
+
191
+ if valid_name?(name)
192
+ warn_if_key_taken context, name, block
193
+ shared_example_groups[context][name] = shared_module
194
+ else
195
+ metadata_args.unshift name
196
+ end
197
+
198
+ return if metadata_args.empty?
199
+ RSpec.configuration.include shared_module, *metadata_args
200
+ end
201
+
202
+ def shared_example_groups
203
+ @shared_example_groups ||= Hash.new { |hash, context| hash[context] = {} }
204
+ end
205
+
206
+ def valid_name?(candidate)
207
+ case candidate
208
+ when String, Symbol, Module then true
209
+ else false
210
+ end
211
+ end
212
+
213
+ def warn_if_key_taken(context, key, new_block)
214
+ existing_module = shared_example_groups[context][key]
215
+ return unless existing_module
216
+
217
+ old_definition_location = formatted_location existing_module.definition
218
+ new_definition_location = formatted_location new_block
219
+ loaded_spec_files = RSpec.configuration.loaded_spec_files
220
+
221
+ if loaded_spec_files.include?(new_definition_location) && old_definition_location == new_definition_location
222
+ RSpec.warn_with <<-WARNING.gsub(/^ +\|/, ''), :call_site => nil
223
+ |WARNING: Your shared example group, '#{key}', defined at:
224
+ | #{old_definition_location}
225
+ |was automatically loaded by RSpec because the file name
226
+ |matches the configured autoloading pattern (#{RSpec.configuration.pattern}),
227
+ |and is also being required from somewhere else. To fix this
228
+ |warning, either rename the file to not match the pattern, or
229
+ |do not explicitly require the file.
230
+ WARNING
231
+ else
232
+ RSpec.warn_with <<-WARNING.gsub(/^ +\|/, ''), :call_site => nil
233
+ |WARNING: Shared example group '#{key}' has been previously defined at:
234
+ | #{old_definition_location}
235
+ |...and you are now defining it at:
236
+ | #{new_definition_location}
237
+ |The new definition will overwrite the original one.
238
+ WARNING
239
+ end
240
+ end
241
+
242
+ if RUBY_VERSION.to_f >= 1.9
243
+ def formatted_location(block)
244
+ block.source_location.join(":")
245
+ end
246
+ else # 1.8.7
247
+ # :nocov:
248
+ def formatted_location(block)
249
+ block.source_location.join(":").gsub(/:in.*$/, '')
250
+ end
251
+ # :nocov:
252
+ end
253
+
254
+ if Proc.method_defined?(:source_location)
255
+ def ensure_block_has_source_location(_block); end
256
+ else # for 1.8.7
257
+ # :nocov:
258
+ def ensure_block_has_source_location(block)
259
+ source_location = yield.split(':')
260
+ block.extend(Module.new { define_method(:source_location) { source_location } })
261
+ end
262
+ # :nocov:
263
+ end
264
+ end
265
+ end
266
+ end
267
+
268
+ instance_exec(&Core::SharedExampleGroup::TopLevelDSL.definitions)
269
+ end
@@ -0,0 +1,49 @@
1
+ module RSpec
2
+ module Core
3
+ # @private
4
+ # Deals with the fact that `shellwords` only works on POSIX systems.
5
+ module ShellEscape
6
+ module_function
7
+
8
+ def quote(argument)
9
+ "'#{argument.to_s.gsub("'", "\\\\'")}'"
10
+ end
11
+
12
+ if RSpec::Support::OS.windows?
13
+ # :nocov:
14
+ alias escape quote
15
+ # :nocov:
16
+ else
17
+ require 'shellwords'
18
+
19
+ def escape(shell_command)
20
+ Shellwords.escape(shell_command.to_s)
21
+ end
22
+ end
23
+
24
+ # Known shells that require quoting: zsh, csh, tcsh.
25
+ #
26
+ # Feel free to add other shells to this list that are known to
27
+ # allow `rspec ./some_spec.rb[1:1]` syntax without quoting the id.
28
+ #
29
+ # @private
30
+ SHELLS_ALLOWING_UNQUOTED_IDS = %w[ bash ksh fish ]
31
+
32
+ def conditionally_quote(id)
33
+ return id if shell_allows_unquoted_ids?
34
+ quote(id)
35
+ end
36
+
37
+ def shell_allows_unquoted_ids?
38
+ # Note: ENV['SHELL'] isn't necessarily the shell the user is currently running.
39
+ # According to http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html:
40
+ # "This variable shall represent a pathname of the user's preferred command language interpreter."
41
+ #
42
+ # It's the best we can easily do, though. We err on the side of safety (quoting
43
+ # the id when not actually needed) so it's not a big deal if the user is actually
44
+ # using a different shell.
45
+ SHELLS_ALLOWING_UNQUOTED_IDS.include?(ENV['SHELL'].to_s.split('/').last)
46
+ end
47
+ end
48
+ end
49
+ end