rspec-core 3.1.7 → 3.2.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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.yardopts +1 -0
- data/Changelog.md +84 -0
- data/README.md +10 -1
- data/lib/rspec/core.rb +28 -8
- data/lib/rspec/core/backport_random.rb +12 -9
- data/lib/rspec/core/configuration.rb +350 -112
- data/lib/rspec/core/configuration_options.rb +14 -7
- data/lib/rspec/core/dsl.rb +7 -4
- data/lib/rspec/core/example.rb +86 -50
- data/lib/rspec/core/example_group.rb +247 -86
- data/lib/rspec/core/filter_manager.rb +38 -93
- data/lib/rspec/core/flat_map.rb +4 -4
- data/lib/rspec/core/formatters.rb +10 -6
- data/lib/rspec/core/formatters/base_formatter.rb +7 -4
- data/lib/rspec/core/formatters/base_text_formatter.rb +12 -12
- data/lib/rspec/core/formatters/console_codes.rb +8 -7
- data/lib/rspec/core/formatters/deprecation_formatter.rb +5 -3
- data/lib/rspec/core/formatters/documentation_formatter.rb +10 -4
- data/lib/rspec/core/formatters/helpers.rb +6 -4
- data/lib/rspec/core/formatters/html_formatter.rb +13 -8
- data/lib/rspec/core/formatters/html_printer.rb +26 -10
- data/lib/rspec/core/formatters/profile_formatter.rb +10 -7
- data/lib/rspec/core/formatters/protocol.rb +27 -18
- data/lib/rspec/core/formatters/snippet_extractor.rb +14 -7
- data/lib/rspec/core/hooks.rb +252 -211
- data/lib/rspec/core/memoized_helpers.rb +16 -16
- data/lib/rspec/core/metadata.rb +67 -28
- data/lib/rspec/core/metadata_filter.rb +151 -24
- data/lib/rspec/core/minitest_assertions_adapter.rb +5 -2
- data/lib/rspec/core/mocking_adapters/flexmock.rb +1 -1
- data/lib/rspec/core/mocking_adapters/mocha.rb +8 -8
- data/lib/rspec/core/notifications.rb +155 -94
- data/lib/rspec/core/option_parser.rb +16 -10
- data/lib/rspec/core/pending.rb +11 -9
- data/lib/rspec/core/project_initializer.rb +1 -1
- data/lib/rspec/core/project_initializer/spec/spec_helper.rb +10 -8
- data/lib/rspec/core/rake_task.rb +37 -52
- data/lib/rspec/core/reporter.rb +30 -7
- data/lib/rspec/core/ruby_project.rb +12 -4
- data/lib/rspec/core/runner.rb +5 -8
- data/lib/rspec/core/sandbox.rb +37 -0
- data/lib/rspec/core/shared_example_group.rb +41 -15
- data/lib/rspec/core/test_unit_assertions_adapter.rb +3 -3
- data/lib/rspec/core/version.rb +1 -1
- data/lib/rspec/core/warnings.rb +2 -2
- data/lib/rspec/core/world.rb +12 -28
- metadata +44 -31
- metadata.gz.sig +0 -0
@@ -1,71 +1,6 @@
|
|
1
1
|
module RSpec
|
2
2
|
module Core
|
3
3
|
# @private
|
4
|
-
# Manages the filtering of examples and groups by matching tags declared on
|
5
|
-
# the command line or options files, or filters declared via
|
6
|
-
# `RSpec.configure`, with hash key/values submitted within example group
|
7
|
-
# and/or example declarations. For example, given this declaration:
|
8
|
-
#
|
9
|
-
# describe Thing, :awesome => true do
|
10
|
-
# it "does something" do
|
11
|
-
# # ...
|
12
|
-
# end
|
13
|
-
# end
|
14
|
-
#
|
15
|
-
# That group (or any other with `:awesome => true`) would be filtered in
|
16
|
-
# with any of the following commands:
|
17
|
-
#
|
18
|
-
# rspec --tag awesome:true
|
19
|
-
# rspec --tag awesome
|
20
|
-
# rspec -t awesome:true
|
21
|
-
# rspec -t awesome
|
22
|
-
#
|
23
|
-
# Prefixing the tag names with `~` negates the tags, thus excluding this group with
|
24
|
-
# any of:
|
25
|
-
#
|
26
|
-
# rspec --tag ~awesome:true
|
27
|
-
# rspec --tag ~awesome
|
28
|
-
# rspec -t ~awesome:true
|
29
|
-
# rspec -t ~awesome
|
30
|
-
#
|
31
|
-
# ## Options files and command line overrides
|
32
|
-
#
|
33
|
-
# Tag declarations can be stored in `.rspec`, `~/.rspec`, or a custom
|
34
|
-
# options file. This is useful for storing defaults. For example, let's
|
35
|
-
# say you've got some slow specs that you want to suppress most of the
|
36
|
-
# time. You can tag them like this:
|
37
|
-
#
|
38
|
-
# describe Something, :slow => true do
|
39
|
-
#
|
40
|
-
# And then store this in `.rspec`:
|
41
|
-
#
|
42
|
-
# --tag ~slow:true
|
43
|
-
#
|
44
|
-
# Now when you run `rspec`, that group will be excluded.
|
45
|
-
#
|
46
|
-
# ## Overriding
|
47
|
-
#
|
48
|
-
# Of course, you probably want to run them sometimes, so you can override
|
49
|
-
# this tag on the command line like this:
|
50
|
-
#
|
51
|
-
# rspec --tag slow:true
|
52
|
-
#
|
53
|
-
# ## RSpec.configure
|
54
|
-
#
|
55
|
-
# You can also store default tags with `RSpec.configure`. We use `tag` on
|
56
|
-
# the command line (and in options files like `.rspec`), but for historical
|
57
|
-
# reasons we use the term `filter` in `RSpec.configure:
|
58
|
-
#
|
59
|
-
# RSpec.configure do |c|
|
60
|
-
# c.filter_run_including :foo => :bar
|
61
|
-
# c.filter_run_excluding :foo => :bar
|
62
|
-
# end
|
63
|
-
#
|
64
|
-
# These declarations can also be overridden from the command line.
|
65
|
-
#
|
66
|
-
# @see RSpec.configure
|
67
|
-
# @see Configuration#filter_run_including
|
68
|
-
# @see Configuration#filter_run_excluding
|
69
4
|
class FilterManager
|
70
5
|
attr_reader :exclusions, :inclusions
|
71
6
|
|
@@ -83,7 +18,7 @@ module RSpec
|
|
83
18
|
# { "path/to/file.rb" => [37, 42] }
|
84
19
|
locations = inclusions.delete(:locations) || Hash.new { |h, k| h[k] = [] }
|
85
20
|
locations[File.expand_path(file_path)].push(*line_numbers)
|
86
|
-
inclusions.
|
21
|
+
inclusions.add(:locations => locations)
|
87
22
|
end
|
88
23
|
|
89
24
|
def empty?
|
@@ -91,11 +26,13 @@ module RSpec
|
|
91
26
|
end
|
92
27
|
|
93
28
|
def prune(examples)
|
29
|
+
examples = prune_conditionally_filtered_examples(examples)
|
30
|
+
|
94
31
|
if inclusions.standalone?
|
95
|
-
|
96
|
-
examples.select { |e| !base_exclusions.include_example?(e) && include?(e) }
|
32
|
+
examples.select { |e| include?(e) }
|
97
33
|
else
|
98
|
-
|
34
|
+
locations = inclusions.fetch(:locations) { Hash.new([]) }
|
35
|
+
examples.select { |e| priority_include?(e, locations) || (!exclude?(e) && include?(e)) }
|
99
36
|
end
|
100
37
|
end
|
101
38
|
|
@@ -111,10 +48,6 @@ module RSpec
|
|
111
48
|
exclusions.add_with_low_priority(args.last)
|
112
49
|
end
|
113
50
|
|
114
|
-
def exclude?(example)
|
115
|
-
exclusions.include_example?(example)
|
116
|
-
end
|
117
|
-
|
118
51
|
def include(*args)
|
119
52
|
inclusions.add(args.last)
|
120
53
|
end
|
@@ -127,9 +60,32 @@ module RSpec
|
|
127
60
|
inclusions.add_with_low_priority(args.last)
|
128
61
|
end
|
129
62
|
|
63
|
+
private
|
64
|
+
|
65
|
+
def exclude?(example)
|
66
|
+
exclusions.include_example?(example)
|
67
|
+
end
|
68
|
+
|
130
69
|
def include?(example)
|
131
70
|
inclusions.include_example?(example)
|
132
71
|
end
|
72
|
+
|
73
|
+
def prune_conditionally_filtered_examples(examples)
|
74
|
+
examples.reject do |ex|
|
75
|
+
meta = ex.metadata
|
76
|
+
!meta.fetch(:if, true) || meta[:unless]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# When a user specifies a particular spec location, that takes priority
|
81
|
+
# over any exclusion filters (such as if the spec is tagged with `:slow`
|
82
|
+
# and there is a `:slow => true` exclusion filter), but only for specs
|
83
|
+
# defined in the same file as the location filters. Excluded specs in
|
84
|
+
# other files should still be excluded.
|
85
|
+
def priority_include?(example, locations)
|
86
|
+
return false if locations[example.metadata[:absolute_file_path]].empty?
|
87
|
+
MetadataFilter.filter_applies?(:locations, locations, example.metadata)
|
88
|
+
end
|
133
89
|
end
|
134
90
|
|
135
91
|
# @private
|
@@ -194,16 +150,17 @@ module RSpec
|
|
194
150
|
def description
|
195
151
|
rules.inspect.gsub(PROC_HEX_NUMBER, '').gsub(PROJECT_DIR, '.').gsub(' (lambda)', '')
|
196
152
|
end
|
153
|
+
|
154
|
+
def include_example?(example)
|
155
|
+
MetadataFilter.apply?(:any?, @rules, example.metadata)
|
156
|
+
end
|
197
157
|
end
|
198
158
|
|
199
159
|
# @private
|
200
|
-
|
201
|
-
STANDALONE_FILTERS = [:locations, :full_description]
|
202
|
-
|
203
|
-
def add_location(locations)
|
204
|
-
replace_filters(:locations => locations)
|
205
|
-
end
|
160
|
+
ExclusionRules = FilterRules
|
206
161
|
|
162
|
+
# @private
|
163
|
+
class InclusionRules < FilterRules
|
207
164
|
def add(*args)
|
208
165
|
apply_standalone_filter(*args) || super
|
209
166
|
end
|
@@ -217,7 +174,7 @@ module RSpec
|
|
217
174
|
end
|
218
175
|
|
219
176
|
def include_example?(example)
|
220
|
-
@rules.empty?
|
177
|
+
@rules.empty? || super
|
221
178
|
end
|
222
179
|
|
223
180
|
def standalone?
|
@@ -240,19 +197,7 @@ module RSpec
|
|
240
197
|
end
|
241
198
|
|
242
199
|
def is_standalone_filter?(rules)
|
243
|
-
|
244
|
-
end
|
245
|
-
end
|
246
|
-
|
247
|
-
# @private
|
248
|
-
class ExclusionRules < FilterRules
|
249
|
-
CONDITIONAL_FILTERS = {
|
250
|
-
:if => lambda { |value| !value },
|
251
|
-
:unless => lambda { |value| value }
|
252
|
-
}.freeze
|
253
|
-
|
254
|
-
def include_example?(example)
|
255
|
-
example.any_apply?(@rules) || example.any_apply?(CONDITIONAL_FILTERS)
|
200
|
+
rules.key?(:full_description)
|
256
201
|
end
|
257
202
|
end
|
258
203
|
end
|
data/lib/rspec/core/flat_map.rb
CHANGED
@@ -3,12 +3,12 @@ module RSpec
|
|
3
3
|
# @private
|
4
4
|
module FlatMap
|
5
5
|
if [].respond_to?(:flat_map)
|
6
|
-
def flat_map(array)
|
7
|
-
array.flat_map
|
6
|
+
def flat_map(array, &block)
|
7
|
+
array.flat_map(&block)
|
8
8
|
end
|
9
9
|
else # for 1.8.7
|
10
|
-
def flat_map(array)
|
11
|
-
array.map
|
10
|
+
def flat_map(array, &block)
|
11
|
+
array.map(&block).flatten(1)
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
@@ -1,10 +1,12 @@
|
|
1
1
|
RSpec::Support.require_rspec_support "directory_maker"
|
2
2
|
# ## Built-in Formatters
|
3
3
|
#
|
4
|
-
# * progress (default) -
|
5
|
-
#
|
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).
|
6
8
|
# * html
|
7
|
-
# * json -
|
9
|
+
# * json - Useful for archiving data for subsequent analysis.
|
8
10
|
#
|
9
11
|
# The progress formatter is the default, but you can choose any one or more of
|
10
12
|
# the other formatters by passing with the `--format` (or `-f` for short)
|
@@ -72,7 +74,8 @@ module RSpec::Core::Formatters
|
|
72
74
|
|
73
75
|
# Register the formatter class
|
74
76
|
# @param formatter_class [Class] formatter class to register
|
75
|
-
# @param notifications [Symbol, ...] one or more notifications to be
|
77
|
+
# @param notifications [Symbol, ...] one or more notifications to be
|
78
|
+
# registered to the specified formatter
|
76
79
|
#
|
77
80
|
# @see RSpec::Core::Formatters::BaseFormatter
|
78
81
|
def self.register(formatter_class, *notifications)
|
@@ -88,7 +91,7 @@ module RSpec::Core::Formatters
|
|
88
91
|
class Loader
|
89
92
|
# @api private
|
90
93
|
#
|
91
|
-
# Internal formatters are stored here when loaded
|
94
|
+
# Internal formatters are stored here when loaded.
|
92
95
|
def self.formatters
|
93
96
|
@formatters ||= {}
|
94
97
|
end
|
@@ -165,7 +168,8 @@ module RSpec::Core::Formatters
|
|
165
168
|
def find_formatter(formatter_to_use)
|
166
169
|
built_in_formatter(formatter_to_use) ||
|
167
170
|
custom_formatter(formatter_to_use) ||
|
168
|
-
(raise ArgumentError, "Formatter '#{formatter_to_use}' unknown -
|
171
|
+
(raise ArgumentError, "Formatter '#{formatter_to_use}' unknown - " \
|
172
|
+
"maybe you meant 'documentation' or 'progress'?.")
|
169
173
|
end
|
170
174
|
|
171
175
|
def duplicate_formatter_exists?(new_formatter)
|
@@ -4,13 +4,15 @@ require 'stringio'
|
|
4
4
|
module RSpec
|
5
5
|
module Core
|
6
6
|
module Formatters
|
7
|
-
# RSpec's built-in formatters are all subclasses of
|
7
|
+
# RSpec's built-in formatters are all subclasses of
|
8
|
+
# RSpec::Core::Formatters::BaseTextFormatter.
|
8
9
|
#
|
9
10
|
# @see RSpec::Core::Formatters::BaseTextFormatter
|
10
11
|
# @see RSpec::Core::Reporter
|
11
12
|
# @see RSpec::Core::Formatters::Protocol
|
12
13
|
class BaseFormatter
|
13
|
-
#
|
14
|
+
# All formatters inheriting from this formatter will receive these
|
15
|
+
# notifications.
|
14
16
|
Formatters.register self, :start, :example_group_started, :close
|
15
17
|
attr_accessor :example_group
|
16
18
|
attr_reader :output
|
@@ -34,7 +36,8 @@ module RSpec
|
|
34
36
|
|
35
37
|
# @api public
|
36
38
|
#
|
37
|
-
# @param notification [GroupNotification] containing example_group
|
39
|
+
# @param notification [GroupNotification] containing example_group
|
40
|
+
# subclass of `RSpec::Core::ExampleGroup`
|
38
41
|
# @see RSpec::Core::Formatters::Protocol#example_group_started
|
39
42
|
def example_group_started(notification)
|
40
43
|
@example_group = notification.group
|
@@ -42,7 +45,7 @@ module RSpec
|
|
42
45
|
|
43
46
|
# @api public
|
44
47
|
#
|
45
|
-
# @param
|
48
|
+
# @param _notification [NullNotification] (Ignored)
|
46
49
|
# @see RSpec::Core::Formatters::Protocol#close
|
47
50
|
def close(_notification)
|
48
51
|
restore_sync_output
|
@@ -4,8 +4,9 @@ RSpec::Support.require_rspec_core "formatters/console_codes"
|
|
4
4
|
module RSpec
|
5
5
|
module Core
|
6
6
|
module Formatters
|
7
|
-
# Base for all of RSpec's built-in formatters. See
|
8
|
-
# to learn more about all of the
|
7
|
+
# Base for all of RSpec's built-in formatters. See
|
8
|
+
# RSpec::Core::Formatters::BaseFormatter to learn more about all of the
|
9
|
+
# methods called by the reporter.
|
9
10
|
#
|
10
11
|
# @see RSpec::Core::Formatters::BaseFormatter
|
11
12
|
# @see RSpec::Core::Reporter
|
@@ -13,7 +14,6 @@ module RSpec
|
|
13
14
|
Formatters.register self,
|
14
15
|
:message, :dump_summary, :dump_failures, :dump_pending, :seed
|
15
16
|
|
16
|
-
# @method message
|
17
17
|
# @api public
|
18
18
|
#
|
19
19
|
# Used by the reporter to send messages to the output stream.
|
@@ -23,7 +23,6 @@ module RSpec
|
|
23
23
|
output.puts notification.message
|
24
24
|
end
|
25
25
|
|
26
|
-
# @method dump_failures
|
27
26
|
# @api public
|
28
27
|
#
|
29
28
|
# Dumps detailed information about each example failure.
|
@@ -34,14 +33,13 @@ module RSpec
|
|
34
33
|
output.puts notification.fully_formatted_failed_examples
|
35
34
|
end
|
36
35
|
|
37
|
-
# @method dump_summary
|
38
36
|
# @api public
|
39
37
|
#
|
40
|
-
# This method is invoked after the dumping of examples and failures.
|
41
|
-
# is assigned to a corresponding attribute.
|
38
|
+
# This method is invoked after the dumping of examples and failures.
|
39
|
+
# Each parameter is assigned to a corresponding attribute.
|
42
40
|
#
|
43
|
-
# @param summary [SummaryNotification] containing duration,
|
44
|
-
#
|
41
|
+
# @param summary [SummaryNotification] containing duration,
|
42
|
+
# example_count, failure_count and pending_count
|
45
43
|
def dump_summary(summary)
|
46
44
|
output.puts summary.fully_formatted
|
47
45
|
end
|
@@ -63,12 +61,14 @@ module RSpec
|
|
63
61
|
# Invoked at the very end, `close` allows the formatter to clean
|
64
62
|
# up resources, e.g. open streams, etc.
|
65
63
|
#
|
66
|
-
# @param
|
64
|
+
# @param _notification [NullNotification] (Ignored)
|
67
65
|
def close(_notification)
|
68
66
|
return unless IO === output
|
69
|
-
return if output.closed?
|
67
|
+
return if output.closed?
|
68
|
+
|
69
|
+
output.puts
|
70
70
|
|
71
|
-
output.close
|
71
|
+
output.close unless output == $stdout
|
72
72
|
end
|
73
73
|
end
|
74
74
|
end
|
@@ -22,14 +22,20 @@ module RSpec
|
|
22
22
|
|
23
23
|
module_function
|
24
24
|
|
25
|
+
# @private
|
26
|
+
CONFIG_COLORS_TO_METHODS = Configuration.instance_methods.grep(/_color\z/).inject({}) do |hash, method|
|
27
|
+
hash[method.to_s.sub(/_color\z/, '').to_sym] = method
|
28
|
+
hash
|
29
|
+
end
|
30
|
+
|
25
31
|
# Fetches the correct code for the supplied symbol, or checks
|
26
32
|
# that a code is valid. Defaults to white (37).
|
27
33
|
#
|
28
34
|
# @param code_or_symbol [Symbol, Fixnum] Symbol or code to check
|
29
35
|
# @return [Fixnum] a console code
|
30
36
|
def console_code_for(code_or_symbol)
|
31
|
-
if
|
32
|
-
console_code_for
|
37
|
+
if (config_method = CONFIG_COLORS_TO_METHODS[code_or_symbol])
|
38
|
+
console_code_for RSpec.configuration.__send__(config_method)
|
33
39
|
elsif VT100_CODE_VALUES.key?(code_or_symbol)
|
34
40
|
code_or_symbol
|
35
41
|
else
|
@@ -53,11 +59,6 @@ module RSpec
|
|
53
59
|
text
|
54
60
|
end
|
55
61
|
end
|
56
|
-
|
57
|
-
# @private
|
58
|
-
def configuration_color(code)
|
59
|
-
RSpec.configuration.__send__(:"#{code}_color")
|
60
|
-
end
|
61
62
|
end
|
62
63
|
end
|
63
64
|
end
|
@@ -21,7 +21,8 @@ module RSpec
|
|
21
21
|
def printer
|
22
22
|
@printer ||= case deprecation_stream
|
23
23
|
when File
|
24
|
-
ImmediatePrinter.new(FileStream.new(deprecation_stream),
|
24
|
+
ImmediatePrinter.new(FileStream.new(deprecation_stream),
|
25
|
+
summary_stream, self)
|
25
26
|
when RaiseErrorStream
|
26
27
|
ImmediatePrinter.new(deprecation_stream, summary_stream, self)
|
27
28
|
else
|
@@ -209,14 +210,15 @@ module RSpec
|
|
209
210
|
end
|
210
211
|
|
211
212
|
def summarize(summary_stream, deprecation_count)
|
212
|
-
|
213
|
+
path = @file.respond_to?(:path) ? @file.path : @file.inspect
|
214
|
+
summary_stream.puts "\n#{Helpers.pluralize(deprecation_count, 'deprecation')} logged to #{path}"
|
213
215
|
puts RAISE_ERROR_CONFIG_NOTICE
|
214
216
|
end
|
215
217
|
end
|
216
218
|
end
|
217
219
|
end
|
218
220
|
|
219
|
-
# Deprecation Error
|
221
|
+
# Deprecation Error.
|
220
222
|
DeprecationError = Class.new(StandardError)
|
221
223
|
end
|
222
224
|
end
|
@@ -29,11 +29,13 @@ module RSpec
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def example_pending(pending)
|
32
|
-
output.puts pending_output(pending.example,
|
32
|
+
output.puts pending_output(pending.example,
|
33
|
+
pending.example.execution_result.pending_message)
|
33
34
|
end
|
34
35
|
|
35
36
|
def example_failed(failure)
|
36
|
-
output.puts failure_output(failure.example,
|
37
|
+
output.puts failure_output(failure.example,
|
38
|
+
failure.example.execution_result.exception)
|
37
39
|
end
|
38
40
|
|
39
41
|
private
|
@@ -43,11 +45,15 @@ module RSpec
|
|
43
45
|
end
|
44
46
|
|
45
47
|
def pending_output(example, message)
|
46
|
-
ConsoleCodes.wrap("#{current_indentation}#{example.description.strip}
|
48
|
+
ConsoleCodes.wrap("#{current_indentation}#{example.description.strip} " \
|
49
|
+
"(PENDING: #{message})",
|
50
|
+
:pending)
|
47
51
|
end
|
48
52
|
|
49
53
|
def failure_output(example, _exception)
|
50
|
-
ConsoleCodes.wrap("#{current_indentation}#{example.description.strip}
|
54
|
+
ConsoleCodes.wrap("#{current_indentation}#{example.description.strip} " \
|
55
|
+
"(FAILED - #{next_failure_index})",
|
56
|
+
:failure)
|
51
57
|
end
|
52
58
|
|
53
59
|
def next_failure_index
|