rspec-core 2.99.2 → 3.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +14 -6
- checksums.yaml.gz.sig +2 -0
- data.tar.gz.sig +0 -0
- data/Changelog.md +103 -191
- data/License.txt +1 -0
- data/README.md +4 -25
- data/features/Upgrade.md +2 -14
- data/features/command_line/dry_run.feature +29 -0
- data/features/command_line/example_name_option.feature +1 -1
- data/features/command_line/fail_fast.feature +26 -0
- data/features/command_line/format_option.feature +3 -3
- data/features/command_line/line_number_option.feature +16 -11
- data/features/command_line/order.feature +2 -3
- data/features/command_line/pattern_option.feature +3 -3
- data/features/command_line/randomization.feature +63 -0
- data/features/command_line/require_option.feature +2 -2
- data/features/command_line/ruby.feature +1 -1
- data/features/configuration/alias_example_to.feature +13 -22
- data/features/configuration/{backtrace_clean_patterns.feature → backtrace_exclusion_patterns.feature} +17 -14
- data/features/configuration/custom_settings.feature +11 -11
- data/features/configuration/overriding_global_ordering.feature +93 -0
- data/features/configuration/profile.feature +13 -13
- data/features/configuration/read_options_from_file.feature +7 -7
- data/features/example_groups/basic_structure.feature +1 -1
- data/features/example_groups/shared_context.feature +8 -8
- data/features/example_groups/shared_examples.feature +6 -14
- data/features/expectation_framework_integration/configure_expectation_framework.feature +27 -122
- data/features/filtering/exclusion_filters.feature +2 -5
- data/features/filtering/inclusion_filters.feature +1 -5
- data/features/formatters/json_formatter.feature +2 -2
- data/features/formatters/text_formatter.feature +4 -4
- data/features/helper_methods/arbitrary_methods.feature +2 -2
- data/features/helper_methods/let.feature +5 -5
- data/features/helper_methods/modules.feature +5 -8
- data/features/hooks/around_hooks.feature +2 -2
- data/features/hooks/before_and_after_hooks.feature +14 -14
- data/features/hooks/filtering.feature +12 -14
- data/features/metadata/described_class.feature +1 -1
- data/features/metadata/user_defined.feature +16 -29
- data/features/mock_framework_integration/use_flexmock.feature +1 -1
- data/features/mock_framework_integration/use_mocha.feature +1 -1
- data/features/mock_framework_integration/use_rr.feature +1 -1
- data/features/mock_framework_integration/use_rspec.feature +5 -5
- data/features/pending/pending_examples.feature +5 -5
- data/features/spec_files/arbitrary_file_suffix.feature +1 -1
- data/features/step_definitions/additional_cli_steps.rb +3 -3
- data/features/subject/explicit_subject.feature +8 -8
- data/features/subject/implicit_receiver.feature +29 -0
- data/features/subject/implicit_subject.feature +4 -4
- data/features/support/env.rb +10 -3
- data/features/support/require_expect_syntax_in_aruba_specs.rb +16 -0
- data/lib/rspec/core.rb +11 -48
- data/lib/rspec/core/backport_random.rb +302 -0
- data/lib/rspec/core/backtrace_formatter.rb +65 -0
- data/lib/rspec/core/command_line.rb +7 -18
- data/lib/rspec/core/configuration.rb +202 -507
- data/lib/rspec/core/configuration_options.rb +17 -30
- data/lib/rspec/core/example.rb +29 -39
- data/lib/rspec/core/example_group.rb +166 -259
- data/lib/rspec/core/filter_manager.rb +30 -47
- data/lib/rspec/core/flat_map.rb +17 -0
- data/lib/rspec/core/formatters.rb +0 -138
- data/lib/rspec/core/formatters/base_formatter.rb +46 -1
- data/lib/rspec/core/formatters/base_text_formatter.rb +38 -61
- data/lib/rspec/core/formatters/deprecation_formatter.rb +21 -52
- data/lib/rspec/core/formatters/helpers.rb +0 -28
- data/lib/rspec/core/formatters/html_formatter.rb +1 -1
- data/lib/rspec/core/formatters/json_formatter.rb +38 -9
- data/lib/rspec/core/formatters/snippet_extractor.rb +14 -5
- data/lib/rspec/core/hooks.rb +55 -39
- data/lib/rspec/core/memoized_helpers.rb +17 -167
- data/lib/rspec/core/metadata.rb +16 -64
- data/lib/rspec/core/option_parser.rb +30 -39
- data/lib/rspec/core/ordering.rb +154 -0
- data/lib/rspec/core/pending.rb +12 -69
- data/lib/rspec/core/project_initializer.rb +12 -10
- data/lib/rspec/core/rake_task.rb +5 -108
- data/lib/rspec/core/reporter.rb +15 -18
- data/lib/rspec/core/runner.rb +16 -30
- data/lib/rspec/core/shared_context.rb +3 -5
- data/lib/rspec/core/shared_example_group.rb +3 -51
- data/lib/rspec/core/shared_example_group/collection.rb +1 -19
- data/lib/rspec/core/version.rb +1 -1
- data/lib/rspec/core/warnings.rb +22 -0
- data/lib/rspec/core/world.rb +12 -8
- data/spec/command_line/order_spec.rb +20 -23
- data/spec/rspec/core/backtrace_formatter_spec.rb +216 -0
- data/spec/rspec/core/command_line_spec.rb +32 -48
- data/spec/rspec/core/configuration_options_spec.rb +19 -50
- data/spec/rspec/core/configuration_spec.rb +142 -713
- data/spec/rspec/core/drb_command_line_spec.rb +2 -0
- data/spec/rspec/core/dsl_spec.rb +0 -1
- data/spec/rspec/core/example_group_spec.rb +192 -223
- data/spec/rspec/core/example_spec.rb +40 -16
- data/spec/rspec/core/filter_manager_spec.rb +2 -2
- data/spec/rspec/core/formatters/base_formatter_spec.rb +0 -41
- data/spec/rspec/core/formatters/base_text_formatter_spec.rb +5 -123
- data/spec/rspec/core/formatters/deprecation_formatter_spec.rb +2 -87
- data/spec/rspec/core/formatters/documentation_formatter_spec.rb +2 -3
- data/spec/rspec/core/formatters/{text_mate_formatted.html → html_formatted-1.8.7-jruby.html} +44 -25
- data/spec/rspec/core/formatters/html_formatted-1.8.7-rbx.html +477 -0
- data/spec/rspec/core/formatters/{html_formatted.html → html_formatted-1.8.7.html} +42 -25
- data/spec/rspec/core/formatters/html_formatted-1.9.2.html +425 -0
- data/spec/rspec/core/formatters/html_formatted-1.9.3-jruby.html +416 -0
- data/spec/rspec/core/formatters/html_formatted-1.9.3-rbx.html +477 -0
- data/spec/rspec/core/formatters/html_formatted-1.9.3.html +419 -0
- data/spec/rspec/core/formatters/html_formatted-2.0.0.html +425 -0
- data/spec/rspec/core/formatters/html_formatter_spec.rb +21 -46
- data/spec/rspec/core/formatters/json_formatter_spec.rb +97 -8
- data/spec/rspec/core/hooks_filtering_spec.rb +5 -5
- data/spec/rspec/core/hooks_spec.rb +61 -47
- data/spec/rspec/core/memoized_helpers_spec.rb +20 -322
- data/spec/rspec/core/metadata_spec.rb +1 -24
- data/spec/rspec/core/option_parser_spec.rb +20 -62
- data/spec/rspec/core/ordering_spec.rb +102 -0
- data/spec/rspec/core/pending_example_spec.rb +0 -40
- data/spec/rspec/core/project_initializer_spec.rb +1 -25
- data/spec/rspec/core/rake_task_spec.rb +5 -72
- data/spec/rspec/core/random_spec.rb +47 -0
- data/spec/rspec/core/reporter_spec.rb +23 -48
- data/spec/rspec/core/runner_spec.rb +31 -39
- data/spec/rspec/core/shared_context_spec.rb +3 -15
- data/spec/rspec/core/shared_example_group/collection_spec.rb +4 -17
- data/spec/rspec/core/shared_example_group_spec.rb +12 -45
- data/spec/rspec/core/{deprecation_spec.rb → warnings_spec.rb} +3 -1
- data/spec/rspec/core_spec.rb +4 -21
- data/spec/spec_helper.rb +41 -5
- data/spec/support/helper_methods.rb +0 -29
- data/spec/support/sandboxed_mock_space.rb +0 -16
- data/spec/support/shared_example_groups.rb +7 -36
- data/spec/support/stderr_splitter.rb +36 -0
- metadata +163 -157
- metadata.gz.sig +1 -0
- data/exe/autospec +0 -13
- data/features/Autotest.md +0 -38
- data/features/configuration/treat_symbols_as_metadata_keys_with_true_values.feature +0 -52
- data/features/subject/attribute_of_subject.feature +0 -124
- data/features/subject/one_liner_syntax.feature +0 -71
- data/lib/autotest/discover.rb +0 -10
- data/lib/autotest/rspec2.rb +0 -77
- data/lib/rspec/core/backtrace_cleaner.rb +0 -46
- data/lib/rspec/core/backward_compatibility.rb +0 -55
- data/lib/rspec/core/caller_filter.rb +0 -60
- data/lib/rspec/core/deprecated_mutable_array_proxy.rb +0 -32
- data/lib/rspec/core/deprecation.rb +0 -26
- data/lib/rspec/core/extensions/instance_eval_with_args.rb +0 -44
- data/lib/rspec/core/extensions/kernel.rb +0 -9
- data/lib/rspec/core/extensions/module_eval_with_args.rb +0 -38
- data/lib/rspec/core/extensions/ordered.rb +0 -27
- data/lib/rspec/core/formatters/console_codes.rb +0 -42
- data/lib/rspec/core/formatters/text_mate_formatter.rb +0 -34
- data/lib/rspec/core/metadata_hash_builder.rb +0 -97
- data/lib/rspec/core/minitest_assertions_adapter.rb +0 -28
- data/lib/rspec/core/test_unit_assertions_adapter.rb +0 -30
- data/spec/autotest/discover_spec.rb +0 -49
- data/spec/autotest/failed_results_re_spec.rb +0 -45
- data/spec/autotest/rspec_spec.rb +0 -133
- data/spec/rspec/core/backtrace_cleaner_spec.rb +0 -68
- data/spec/rspec/core/caller_filter_spec.rb +0 -58
- data/spec/rspec/core/deprecations_spec.rb +0 -59
- data/spec/rspec/core/formatters/console_codes_spec.rb +0 -50
- data/spec/rspec/core/formatters/text_mate_formatter_spec.rb +0 -107
- data/spec/rspec/core/kernel_extensions_spec.rb +0 -9
- data/spec/rspec/core/pending_spec.rb +0 -27
- data/spec/support/silence_dsl_deprecations.rb +0 -32
@@ -66,51 +66,44 @@ module RSpec
|
|
66
66
|
# @see Configuration#filter_run_including
|
67
67
|
# @see Configuration#filter_run_excluding
|
68
68
|
class FilterManager
|
69
|
-
|
70
|
-
def const_missing(name)
|
71
|
-
case name
|
72
|
-
when :DEFAULT_EXCLUSIONS
|
73
|
-
RSpec.deprecate("RSpec::Core::FilterManager::DEFAULT_EXCLUSIONS is deprecated")
|
74
|
-
default_exclusions
|
75
|
-
when :STANDALONE_FILTERS
|
76
|
-
RSpec.deprecate("RSpec::Core::FilterManager::STANDALONE_FILTERS is deprecated")
|
77
|
-
standalone_filters
|
78
|
-
else
|
79
|
-
super
|
80
|
-
end
|
81
|
-
end
|
69
|
+
STANDALONE_FILTERS = [:locations, :line_numbers, :full_description]
|
82
70
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
end
|
71
|
+
PROC_HEX_NUMBER = /0x[0-9a-f]+@/
|
72
|
+
PROJECT_DIR = File.expand_path('.')
|
73
|
+
|
74
|
+
def self.inspect_filter_hash(hash)
|
75
|
+
hash.inspect.gsub(PROC_HEX_NUMBER, '').gsub(PROJECT_DIR, '.').gsub(' (lambda)','')
|
76
|
+
end
|
90
77
|
|
91
|
-
|
92
|
-
def
|
93
|
-
|
78
|
+
class InclusionFilterHash < Hash
|
79
|
+
def description
|
80
|
+
FilterManager.inspect_filter_hash self
|
94
81
|
end
|
95
82
|
end
|
96
83
|
|
97
|
-
|
98
|
-
|
99
|
-
|
84
|
+
class ExclusionFilterHash < Hash
|
85
|
+
CONDITIONAL_FILTERS = {
|
86
|
+
:if => lambda { |value| !value },
|
87
|
+
:unless => lambda { |value| value }
|
88
|
+
}
|
89
|
+
|
90
|
+
def initialize(*)
|
91
|
+
super
|
92
|
+
CONDITIONAL_FILTERS.each {|k,v| store(k, v)}
|
93
|
+
end
|
100
94
|
|
101
95
|
def description
|
102
|
-
|
103
|
-
gsub(PROC_HEX_NUMBER, '').gsub(PROJECT_DIR, '.').gsub(' (lambda)','').gsub('__is_lambda__=true','')
|
96
|
+
FilterManager.inspect_filter_hash without_conditional_filters
|
104
97
|
end
|
105
98
|
|
106
99
|
def empty_without_conditional_filters?
|
107
|
-
|
108
|
-
rules_empty?
|
100
|
+
without_conditional_filters.empty?
|
109
101
|
end
|
110
102
|
|
111
|
-
|
112
|
-
|
113
|
-
|
103
|
+
private
|
104
|
+
|
105
|
+
def without_conditional_filters
|
106
|
+
reject {|k,v| CONDITIONAL_FILTERS[k] == v}
|
114
107
|
end
|
115
108
|
end
|
116
109
|
|
@@ -143,8 +136,8 @@ module RSpec
|
|
143
136
|
attr_reader :exclusions, :inclusions
|
144
137
|
|
145
138
|
def initialize
|
146
|
-
@exclusions =
|
147
|
-
@inclusions =
|
139
|
+
@exclusions = ExclusionFilterHash.new
|
140
|
+
@inclusions = InclusionFilterHash.new
|
148
141
|
extend(BackwardCompatibility)
|
149
142
|
end
|
150
143
|
|
@@ -159,7 +152,7 @@ module RSpec
|
|
159
152
|
end
|
160
153
|
|
161
154
|
def empty?
|
162
|
-
inclusions.empty? && exclusions.
|
155
|
+
inclusions.empty? && exclusions.empty_without_conditional_filters?
|
163
156
|
end
|
164
157
|
|
165
158
|
def prune(examples)
|
@@ -171,11 +164,6 @@ module RSpec
|
|
171
164
|
end
|
172
165
|
|
173
166
|
def exclude!(*args)
|
174
|
-
RSpec.deprecate("FilterManager#exclude! is deprecated. Use FilterManager#exclude_only")
|
175
|
-
exclude_only(*args)
|
176
|
-
end
|
177
|
-
|
178
|
-
def exclude_only(*args)
|
179
167
|
replace(@exclusions, @inclusions, *args)
|
180
168
|
end
|
181
169
|
|
@@ -192,11 +180,6 @@ module RSpec
|
|
192
180
|
end
|
193
181
|
|
194
182
|
def include!(*args)
|
195
|
-
RSpec.deprecate("FilterManager#include! is deprecated. Use FilterManager#include_only")
|
196
|
-
include_only(*args)
|
197
|
-
end
|
198
|
-
|
199
|
-
def include_only(*args)
|
200
183
|
unless_standalone(*args) { replace(@inclusions, @exclusions, *args) }
|
201
184
|
end
|
202
185
|
|
@@ -234,7 +217,7 @@ module RSpec
|
|
234
217
|
end
|
235
218
|
|
236
219
|
def is_standalone_filter?(filter)
|
237
|
-
|
220
|
+
STANDALONE_FILTERS.any? {|key| filter.has_key?(key)}
|
238
221
|
end
|
239
222
|
end
|
240
223
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Core
|
3
|
+
module FlatMap
|
4
|
+
if [].respond_to?(:flat_map)
|
5
|
+
def flat_map(array)
|
6
|
+
array.flat_map { |item| yield item }
|
7
|
+
end
|
8
|
+
else # for 1.8.7
|
9
|
+
def flat_map(array)
|
10
|
+
array.map { |item| yield item }.flatten
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module_function :flat_map
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -3,7 +3,6 @@
|
|
3
3
|
# * progress (default) - prints dots for passing examples, `F` for failures, `*` for pending
|
4
4
|
# * documentation - prints the docstrings passed to `describe` and `it` methods (and their aliases)
|
5
5
|
# * html
|
6
|
-
# * textmate - html plus links to editor
|
7
6
|
# * json - useful for archiving data for subsequent analysis
|
8
7
|
#
|
9
8
|
# The progress formatter is the default, but you can choose any one or more of
|
@@ -52,141 +51,4 @@
|
|
52
51
|
# @see RSpec::Core::Formatters::BaseTextFormatter
|
53
52
|
# @see RSpec::Core::Reporter
|
54
53
|
module RSpec::Core::Formatters
|
55
|
-
autoload :DocumentationFormatter, 'rspec/core/formatters/documentation_formatter'
|
56
|
-
autoload :HtmlFormatter, 'rspec/core/formatters/html_formatter'
|
57
|
-
autoload :ProgressFormatter, 'rspec/core/formatters/progress_formatter'
|
58
|
-
autoload :JsonFormatter, 'rspec/core/formatters/json_formatter'
|
59
|
-
autoload :TextMateFormatter, 'rspec/core/formatters/text_mate_formatter'
|
60
|
-
|
61
|
-
# @api private
|
62
|
-
#
|
63
|
-
# `RSpec::Core::Formatters::Loader` is an internal class for
|
64
|
-
# managing formatters used by a particular configuration. It is
|
65
|
-
# not expected to be used directly, but only through the configuration
|
66
|
-
# interface.
|
67
|
-
class Loader
|
68
|
-
|
69
|
-
# @api private
|
70
|
-
def initialize(reporter)
|
71
|
-
@formatters = []
|
72
|
-
@reporter = reporter
|
73
|
-
@setup = false
|
74
|
-
@default_formatter = 'progress'
|
75
|
-
end
|
76
|
-
|
77
|
-
# @return [Array] the loaded formatters
|
78
|
-
attr_reader :formatters
|
79
|
-
|
80
|
-
# @return [Reporter] the reporter
|
81
|
-
attr_reader :reporter
|
82
|
-
|
83
|
-
# @private
|
84
|
-
def setup_default(output_stream, deprecation_stream)
|
85
|
-
if @formatters.empty?
|
86
|
-
add @default_formatter, output_stream
|
87
|
-
end
|
88
|
-
unless @formatters.any? { |formatter| DeprecationFormatter === formatter }
|
89
|
-
add DeprecationFormatter, deprecation_stream, output_stream
|
90
|
-
end
|
91
|
-
@formatters.each do |formatter|
|
92
|
-
@reporter.register_listener formatter, *RSpec::Core::Reporter::NOTIFICATIONS
|
93
|
-
end
|
94
|
-
@setup = true
|
95
|
-
end
|
96
|
-
|
97
|
-
# @private
|
98
|
-
def add(formatter_to_use, *paths)
|
99
|
-
formatter_class = find_formatter(formatter_to_use)
|
100
|
-
|
101
|
-
args = paths.map { |p| p.respond_to?(:puts) ? p : file_at(p) }
|
102
|
-
|
103
|
-
formatter = formatter_class.new(*args)
|
104
|
-
if @setup
|
105
|
-
@reporter.register_listener formatter, *RSpec::Core::Reporter::NOTIFICATIONS
|
106
|
-
end
|
107
|
-
@formatters << formatter unless duplicate_formatter_exists?(formatter)
|
108
|
-
|
109
|
-
formatter
|
110
|
-
end
|
111
|
-
|
112
|
-
private
|
113
|
-
|
114
|
-
def find_formatter(formatter_to_use)
|
115
|
-
built_in_formatter(formatter_to_use) ||
|
116
|
-
custom_formatter(formatter_to_use) ||
|
117
|
-
(raise ArgumentError, "Formatter '#{formatter_to_use}' unknown - maybe you meant 'documentation' or 'progress'?.")
|
118
|
-
end
|
119
|
-
|
120
|
-
def duplicate_formatter_exists?(new_formatter)
|
121
|
-
@formatters.any? do |formatter|
|
122
|
-
formatter.class === new_formatter && formatter.output == new_formatter.output
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
def built_in_formatter(key)
|
127
|
-
case key.to_s
|
128
|
-
when 'd', 'doc', 'documentation'
|
129
|
-
DocumentationFormatter
|
130
|
-
when 's', 'n', 'spec', 'nested'
|
131
|
-
RSpec.deprecate "Using `#{key.to_s}` as a shortcut for the DocumentationFormatter",
|
132
|
-
:replacement => "`d`, `doc`, or `documentation`"
|
133
|
-
DocumentationFormatter
|
134
|
-
when 'h', 'html'
|
135
|
-
HtmlFormatter
|
136
|
-
when 'p', 'progress'
|
137
|
-
ProgressFormatter
|
138
|
-
when 'j', 'json'
|
139
|
-
JsonFormatter
|
140
|
-
when 't', 'textmate'
|
141
|
-
if defined?(::RSpec::Mate::Formatters::TextMateFormatter)
|
142
|
-
RSpec.deprecate "Using the text`#{key.to_s}` as a shortcut for the TextMateFormatter",
|
143
|
-
:replacement => "`::RSpec::Mate::Formatters::TextMateFormatter`"
|
144
|
-
else
|
145
|
-
RSpec.deprecate "Using rspec-core's `::RSpec::Core::TextMateFormatter`",
|
146
|
-
:replacement => "the `rspec-tmbundle` gem and it's `::RSpec::Mate::Formatters::TextMateFormatter`"
|
147
|
-
end
|
148
|
-
TextMateFormatter
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
def custom_formatter(formatter_ref)
|
153
|
-
if Class === formatter_ref
|
154
|
-
formatter_ref
|
155
|
-
elsif string_const?(formatter_ref)
|
156
|
-
begin
|
157
|
-
formatter_ref.gsub(/^::/,'').split('::').inject(Object) { |const,string| const.const_get string }
|
158
|
-
rescue NameError
|
159
|
-
require( path_for(formatter_ref) ) ? retry : raise
|
160
|
-
end
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
def string_const?(str)
|
165
|
-
str.is_a?(String) && /\A[A-Z][a-zA-Z0-9_:]*\z/ =~ str
|
166
|
-
end
|
167
|
-
|
168
|
-
def path_for(const_ref)
|
169
|
-
underscore_with_fix_for_non_standard_rspec_naming(const_ref)
|
170
|
-
end
|
171
|
-
|
172
|
-
def underscore_with_fix_for_non_standard_rspec_naming(string)
|
173
|
-
underscore(string).sub(%r{(^|/)r_spec($|/)}, '\\1rspec\\2')
|
174
|
-
end
|
175
|
-
|
176
|
-
# activesupport/lib/active_support/inflector/methods.rb, line 48
|
177
|
-
def underscore(camel_cased_word)
|
178
|
-
word = camel_cased_word.to_s.dup
|
179
|
-
word.gsub!(/::/, '/')
|
180
|
-
word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
|
181
|
-
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
182
|
-
word.tr!("-", "_")
|
183
|
-
word.downcase!
|
184
|
-
word
|
185
|
-
end
|
186
|
-
|
187
|
-
def file_at(path)
|
188
|
-
FileUtils.mkdir_p(File.dirname(path))
|
189
|
-
File.new(path, 'w')
|
190
|
-
end
|
191
|
-
end
|
192
54
|
end
|
@@ -161,6 +161,15 @@ module RSpec
|
|
161
161
|
def dump_pending
|
162
162
|
end
|
163
163
|
|
164
|
+
# @api public
|
165
|
+
#
|
166
|
+
# This methods is invoked form formatters to show slowest examples and example groups
|
167
|
+
# when using `--profile COUNT` (default 10).
|
168
|
+
#
|
169
|
+
# @return [nil]
|
170
|
+
def dump_profile
|
171
|
+
end
|
172
|
+
|
164
173
|
# @private not intended for use outside RSpec.
|
165
174
|
def seed(number)
|
166
175
|
end
|
@@ -178,7 +187,7 @@ module RSpec
|
|
178
187
|
# Formats the given backtrace based on configuration and
|
179
188
|
# the metadata of the given example.
|
180
189
|
def format_backtrace(backtrace, example)
|
181
|
-
|
190
|
+
configuration.backtrace_formatter.format_backtrace(backtrace, example.metadata)
|
182
191
|
end
|
183
192
|
|
184
193
|
protected
|
@@ -240,6 +249,42 @@ module RSpec
|
|
240
249
|
# Don't print out profiled info if there are failures and `--fail-fast` is used, it just clutters the output
|
241
250
|
!profile_examples? || (fail_fast? && failure_count != 0)
|
242
251
|
end
|
252
|
+
|
253
|
+
# @api private
|
254
|
+
def slowest_examples
|
255
|
+
number_of_examples = RSpec.configuration.profile_examples
|
256
|
+
sorted_examples = examples.sort_by {|example|
|
257
|
+
example.execution_result[:run_time] }.reverse.first(number_of_examples)
|
258
|
+
|
259
|
+
total, slows = [examples, sorted_examples].map do |exs|
|
260
|
+
exs.inject(0.0) {|i, e| i + e.execution_result[:run_time] }
|
261
|
+
end
|
262
|
+
{:examples => sorted_examples, :total => total, :slows => slows}
|
263
|
+
end
|
264
|
+
|
265
|
+
# @api private
|
266
|
+
def slowest_groups
|
267
|
+
number_of_examples = RSpec.configuration.profile_examples
|
268
|
+
example_groups = {}
|
269
|
+
|
270
|
+
examples.each do |example|
|
271
|
+
location = example.example_group.parent_groups.last.metadata[:example_group][:location]
|
272
|
+
|
273
|
+
example_groups[location] ||= Hash.new(0)
|
274
|
+
example_groups[location][:total_time] += example.execution_result[:run_time]
|
275
|
+
example_groups[location][:count] += 1
|
276
|
+
example_groups[location][:description] = example.example_group.top_level_description unless example_groups[location].has_key?(:description)
|
277
|
+
end
|
278
|
+
|
279
|
+
# stop if we've only one example group
|
280
|
+
return {} if example_groups.keys.length <= 1
|
281
|
+
|
282
|
+
example_groups.each_value do |hash|
|
283
|
+
hash[:average] = hash[:total_time].to_f / hash[:count]
|
284
|
+
end
|
285
|
+
|
286
|
+
example_groups.sort_by {|_, hash| -hash[:average]}.first(number_of_examples)
|
287
|
+
end
|
243
288
|
end
|
244
289
|
end
|
245
290
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'rspec/core/formatters/base_formatter'
|
2
|
-
require '
|
2
|
+
require 'set'
|
3
3
|
|
4
4
|
module RSpec
|
5
5
|
module Core
|
@@ -75,53 +75,31 @@ module RSpec
|
|
75
75
|
end
|
76
76
|
|
77
77
|
def dump_profile_slowest_examples
|
78
|
-
|
79
|
-
sorted_examples = examples.sort_by {|example|
|
80
|
-
example.execution_result[:run_time] }.reverse.first(number_of_examples)
|
78
|
+
sorted_examples = slowest_examples
|
81
79
|
|
82
|
-
|
83
|
-
exs.inject(0.0) {|i, e| i + e.execution_result[:run_time] }}
|
84
|
-
|
85
|
-
time_taken = slows / total
|
80
|
+
time_taken = sorted_examples[:slows] / sorted_examples[:total]
|
86
81
|
percentage = '%.1f' % ((time_taken.nan? ? 0.0 : time_taken) * 100)
|
87
82
|
|
88
|
-
output.puts "\nTop #{sorted_examples.size} slowest examples (#{format_seconds(slows)} seconds, #{percentage}% of total time):\n"
|
83
|
+
output.puts "\nTop #{sorted_examples[:examples].size} slowest examples (#{format_seconds(sorted_examples[:slows])} seconds, #{percentage}% of total time):\n"
|
89
84
|
|
90
|
-
sorted_examples.each do |example|
|
85
|
+
sorted_examples[:examples].each do |example|
|
91
86
|
output.puts " #{example.full_description}"
|
92
|
-
output.puts
|
87
|
+
output.puts " #{bold(format_seconds(example.execution_result[:run_time]))} #{bold("seconds")} #{format_caller(example.location)}"
|
93
88
|
end
|
94
89
|
end
|
95
90
|
|
96
91
|
def dump_profile_slowest_example_groups
|
97
|
-
number_of_examples = RSpec.configuration.profile_examples
|
98
|
-
example_groups = {}
|
99
|
-
|
100
|
-
examples.each do |example|
|
101
|
-
location = example.example_group.parent_groups.last.metadata[:example_group][:location]
|
102
|
-
|
103
|
-
example_groups[location] ||= Hash.new(0)
|
104
|
-
example_groups[location][:total_time] += example.execution_result[:run_time]
|
105
|
-
example_groups[location][:count] += 1
|
106
|
-
example_groups[location][:description] = example.example_group.top_level_description unless example_groups[location].has_key?(:description)
|
107
|
-
end
|
108
|
-
|
109
|
-
# stop if we've only one example group
|
110
|
-
return if example_groups.keys.length <= 1
|
111
|
-
|
112
|
-
example_groups.each do |loc, hash|
|
113
|
-
hash[:average] = hash[:total_time].to_f / hash[:count]
|
114
|
-
end
|
115
92
|
|
116
|
-
sorted_groups =
|
93
|
+
sorted_groups = slowest_groups
|
94
|
+
return if sorted_groups.empty?
|
117
95
|
|
118
96
|
output.puts "\nTop #{sorted_groups.size} slowest example groups:"
|
119
|
-
|
120
|
-
average = "#{
|
97
|
+
slowest_groups.each do |loc, hash|
|
98
|
+
average = "#{bold(format_seconds(hash[:average]))} #{bold("seconds")} average"
|
121
99
|
total = "#{format_seconds(hash[:total_time])} seconds"
|
122
100
|
count = pluralize(hash[:count], "example")
|
123
101
|
output.puts " #{hash[:description]}"
|
124
|
-
output.puts
|
102
|
+
output.puts " #{average} (#{total} / #{count}) #{loc}"
|
125
103
|
end
|
126
104
|
end
|
127
105
|
|
@@ -144,10 +122,8 @@ module RSpec
|
|
144
122
|
output.puts pending_color(" #{pending_example.full_description}")
|
145
123
|
output.puts detail_color(" # #{pending_example.execution_result[:pending_message]}")
|
146
124
|
output.puts detail_color(" # #{format_caller(pending_example.location)}")
|
147
|
-
# instance_variable_get is a hack to avoid a deprecation warning,
|
148
|
-
# it's only for 2.99.
|
149
125
|
if pending_example.execution_result[:exception] \
|
150
|
-
&& RSpec.configuration.
|
126
|
+
&& RSpec.configuration.show_failures_in_pending_blocks?
|
151
127
|
dump_failure_info(pending_example)
|
152
128
|
dump_backtrace(pending_example)
|
153
129
|
end
|
@@ -162,43 +138,44 @@ module RSpec
|
|
162
138
|
end
|
163
139
|
|
164
140
|
def close
|
165
|
-
|
166
|
-
return if output.closed? || output == $stdout
|
167
|
-
|
168
|
-
output.close
|
169
|
-
end
|
170
|
-
|
171
|
-
def self.const_missing(name)
|
172
|
-
base = "RSpec::Core::Formatters::"
|
173
|
-
case name
|
174
|
-
when :VT100_COLORS then
|
175
|
-
RSpec.deprecate("#{base}#{name}", :replacement => "#{base}ConsoleCodes::VT100_CODES")
|
176
|
-
RSpec::Core::Formatters::ConsoleCodes::VT100_CODES
|
177
|
-
when :VT100_COLOR_CODES then
|
178
|
-
RSpec.deprecate("#{base}#{name}", :replacement => "#{base}ConsoleCodes::VT100_CODE_VALUES")
|
179
|
-
require 'set'
|
180
|
-
RSpec::Core::Formatters::ConsoleCodes::VT100_CODES.to_set
|
181
|
-
else
|
182
|
-
super
|
183
|
-
end
|
141
|
+
output.close if IO === output && output != $stdout
|
184
142
|
end
|
185
143
|
|
144
|
+
VT100_COLORS = {
|
145
|
+
:black => 30,
|
146
|
+
:red => 31,
|
147
|
+
:green => 32,
|
148
|
+
:yellow => 33,
|
149
|
+
:blue => 34,
|
150
|
+
:magenta => 35,
|
151
|
+
:cyan => 36,
|
152
|
+
:white => 37
|
153
|
+
}
|
154
|
+
|
155
|
+
VT100_COLOR_CODES = VT100_COLORS.values.to_set
|
156
|
+
|
186
157
|
def color_code_for(code_or_symbol)
|
187
|
-
|
158
|
+
if VT100_COLOR_CODES.include?(code_or_symbol)
|
159
|
+
code_or_symbol
|
160
|
+
else
|
161
|
+
VT100_COLORS.fetch(code_or_symbol) do
|
162
|
+
color_code_for(:white)
|
163
|
+
end
|
164
|
+
end
|
188
165
|
end
|
189
166
|
|
190
167
|
def colorize(text, code_or_symbol)
|
191
|
-
|
168
|
+
"\e[#{color_code_for(code_or_symbol)}m#{text}\e[0m"
|
192
169
|
end
|
193
170
|
|
194
171
|
protected
|
195
172
|
|
196
173
|
def bold(text)
|
197
|
-
|
174
|
+
color_enabled? ? "\e[1m#{text}\e[0m" : text
|
198
175
|
end
|
199
176
|
|
200
177
|
def color(text, color_code)
|
201
|
-
|
178
|
+
color_enabled? ? colorize(text, color_code) : text
|
202
179
|
end
|
203
180
|
|
204
181
|
def failure_color(text)
|
@@ -271,7 +248,7 @@ module RSpec
|
|
271
248
|
private
|
272
249
|
|
273
250
|
def format_caller(caller_info)
|
274
|
-
backtrace_line(caller_info.to_s.split(':in `block').first)
|
251
|
+
configuration.backtrace_formatter.backtrace_line(caller_info.to_s.split(':in `block').first)
|
275
252
|
end
|
276
253
|
|
277
254
|
def dump_backtrace(example)
|
@@ -314,7 +291,7 @@ module RSpec
|
|
314
291
|
|
315
292
|
def dump_shared_failure_info(group)
|
316
293
|
output.puts "#{long_padding}Shared Example Group: \"#{group.metadata[:shared_group_name]}\" called from " +
|
317
|
-
"#{backtrace_line(group.metadata[:example_group][:location])}"
|
294
|
+
"#{configuration.backtrace_formatter.backtrace_line(group.metadata[:example_group][:location])}"
|
318
295
|
end
|
319
296
|
|
320
297
|
def find_shared_group(example)
|