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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/Changelog.md +67 -2
- data/lib/rspec/core/bisect/server.rb +6 -1
- data/lib/rspec/core/configuration.rb +98 -21
- data/lib/rspec/core/configuration_options.rb +2 -0
- data/lib/rspec/core/drb.rb +2 -0
- data/lib/rspec/core/example.rb +9 -5
- data/lib/rspec/core/example_group.rb +6 -2
- data/lib/rspec/core/formatters/base_text_formatter.rb +3 -5
- data/lib/rspec/core/formatters/console_codes.rb +7 -4
- data/lib/rspec/core/formatters/documentation_formatter.rb +2 -1
- data/lib/rspec/core/formatters/exception_presenter.rb +8 -3
- data/lib/rspec/core/formatters/html_formatter.rb +4 -2
- data/lib/rspec/core/formatters/html_snippet_extractor.rb +2 -0
- data/lib/rspec/core/formatters/json_formatter.rb +7 -2
- data/lib/rspec/core/formatters/progress_formatter.rb +1 -0
- data/lib/rspec/core/formatters/protocol.rb +26 -25
- data/lib/rspec/core/formatters/snippet_extractor.rb +1 -3
- data/lib/rspec/core/{source → formatters}/syntax_highlighter.rb +21 -1
- data/lib/rspec/core/formatters.rb +15 -5
- data/lib/rspec/core/invocations.rb +22 -4
- data/lib/rspec/core/memoized_helpers.rb +3 -0
- data/lib/rspec/core/metadata_filter.rb +29 -17
- data/lib/rspec/core/notifications.rb +18 -2
- data/lib/rspec/core/option_parser.rb +23 -3
- data/lib/rspec/core/output_wrapper.rb +29 -0
- data/lib/rspec/core/project_initializer/.rspec +0 -1
- data/lib/rspec/core/project_initializer/spec/spec_helper.rb +1 -4
- data/lib/rspec/core/reporter.rb +22 -10
- data/lib/rspec/core/runner.rb +6 -1
- data/lib/rspec/core/set.rb +5 -0
- data/lib/rspec/core/shared_example_group.rb +39 -15
- data/lib/rspec/core/version.rb +1 -1
- data/lib/rspec/core/world.rb +13 -5
- data/lib/rspec/core.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +8 -11
- metadata.gz.sig +0 -0
- data/lib/rspec/core/source/location.rb +0 -13
- data/lib/rspec/core/source/node.rb +0 -93
- data/lib/rspec/core/source/token.rb +0 -87
- 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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
175
|
-
# up
|
|
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.
|
|
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
|
-
|
|
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`
|
|
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 :
|
|
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
|
|
251
|
-
RSpec::
|
|
252
|
-
|
|
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
|
-
|
|
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, :
|
|
76
|
+
PrintHelp = Struct.new(:parser, :hidden_options) do
|
|
59
77
|
def call(_options, _err, out)
|
|
60
|
-
# Removing the
|
|
61
|
-
out.puts parser.to_s.gsub(/^\s+(#{
|
|
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,
|
|
16
|
+
def filter_applies?(key, filter_value, metadata)
|
|
17
17
|
silence_metadata_example_group_deprecations do
|
|
18
|
-
return location_filter_applies?(
|
|
19
|
-
return id_filter_applies?(
|
|
20
|
-
return filters_apply?(key,
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
return
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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', '--
|
|
135
|
-
|
|
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,
|
|
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
|
|
@@ -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 =
|
|
80
|
+
config.default_formatter = "doc"
|
|
84
81
|
end
|
|
85
82
|
|
|
86
83
|
# Print the 10 slowest examples and example groups at the
|
data/lib/rspec/core/reporter.rb
CHANGED
|
@@ -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
|
|
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
|
data/lib/rspec/core/runner.rb
CHANGED
|
@@ -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
|
-
|
|
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
|