rspec-core 2.99.0 → 3.0.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 +8 -8
- checksums.yaml.gz.sig +0 -0
- data/.yardopts +1 -0
- data/Changelog.md +339 -1
- data/License.txt +1 -0
- data/README.md +19 -37
- data/exe/rspec +2 -23
- data/lib/rspec/core/backport_random.rb +336 -0
- data/lib/rspec/core/backtrace_formatter.rb +70 -0
- data/lib/rspec/core/configuration.rb +479 -577
- data/lib/rspec/core/configuration_options.rb +71 -54
- data/lib/rspec/core/drb.rb +111 -0
- data/lib/rspec/core/dsl.rb +86 -18
- data/lib/rspec/core/example.rb +267 -119
- data/lib/rspec/core/example_group.rb +381 -393
- data/lib/rspec/core/filter_manager.rb +133 -114
- data/lib/rspec/core/flat_map.rb +18 -0
- data/lib/rspec/core/formatters/base_formatter.rb +51 -125
- data/lib/rspec/core/formatters/base_text_formatter.rb +34 -286
- data/lib/rspec/core/formatters/console_codes.rb +24 -1
- data/lib/rspec/core/formatters/deprecation_formatter.rb +25 -26
- data/lib/rspec/core/formatters/documentation_formatter.rb +27 -25
- data/lib/rspec/core/formatters/helpers.rb +14 -36
- data/lib/rspec/core/formatters/html_formatter.rb +58 -65
- data/lib/rspec/core/formatters/html_printer.rb +12 -18
- data/lib/rspec/core/formatters/json_formatter.rb +54 -31
- data/lib/rspec/core/formatters/profile_formatter.rb +67 -0
- data/lib/rspec/core/formatters/progress_formatter.rb +11 -15
- data/lib/rspec/core/formatters/snippet_extractor.rb +22 -11
- data/lib/rspec/core/formatters.rb +90 -43
- data/lib/rspec/core/hooks.rb +325 -270
- data/lib/rspec/core/memoized_helpers.rb +45 -156
- data/lib/rspec/core/metadata.rb +284 -236
- data/lib/rspec/core/metadata_filter.rb +86 -0
- data/lib/rspec/core/mocking_adapters/flexmock.rb +29 -0
- data/lib/rspec/core/{mocking/with_mocha.rb → mocking_adapters/mocha.rb} +19 -16
- data/lib/rspec/core/mocking_adapters/null.rb +12 -0
- data/lib/rspec/core/mocking_adapters/rr.rb +29 -0
- data/lib/rspec/core/mocking_adapters/rspec.rb +30 -0
- data/lib/rspec/core/notifications.rb +511 -0
- data/lib/rspec/core/option_parser.rb +49 -74
- data/lib/rspec/core/ordering.rb +156 -0
- data/lib/rspec/core/pending.rb +94 -96
- data/lib/rspec/core/project_initializer/.rspec +3 -0
- data/lib/rspec/core/project_initializer/spec/spec_helper.rb +78 -0
- data/lib/rspec/core/project_initializer.rb +24 -64
- data/lib/rspec/core/rake_task.rb +44 -130
- data/lib/rspec/core/reporter.rb +76 -59
- data/lib/rspec/core/ruby_project.rb +2 -1
- data/lib/rspec/core/runner.rb +117 -52
- data/lib/rspec/core/shared_context.rb +10 -10
- data/lib/rspec/core/shared_example_group.rb +108 -121
- data/lib/rspec/core/version.rb +3 -1
- data/lib/rspec/core/warnings.rb +40 -0
- data/lib/rspec/core/world.rb +66 -10
- data/lib/rspec/core.rb +64 -104
- data.tar.gz.sig +3 -0
- metadata +75 -322
- metadata.gz.sig +1 -0
- data/exe/autospec +0 -13
- data/features/Autotest.md +0 -38
- data/features/README.md +0 -17
- data/features/Upgrade.md +0 -364
- data/features/command_line/README.md +0 -28
- data/features/command_line/example_name_option.feature +0 -97
- data/features/command_line/exit_status.feature +0 -82
- data/features/command_line/format_option.feature +0 -75
- data/features/command_line/init.feature +0 -18
- data/features/command_line/line_number_appended_to_path.feature +0 -140
- data/features/command_line/line_number_option.feature +0 -53
- data/features/command_line/order.feature +0 -26
- data/features/command_line/pattern_option.feature +0 -49
- data/features/command_line/rake_task.feature +0 -122
- data/features/command_line/require_option.feature +0 -43
- data/features/command_line/ruby.feature +0 -22
- data/features/command_line/tag.feature +0 -98
- data/features/command_line/warnings_option.feature +0 -29
- data/features/configuration/alias_example_to.feature +0 -48
- data/features/configuration/backtrace_clean_patterns.feature +0 -102
- data/features/configuration/custom_settings.feature +0 -84
- data/features/configuration/default_path.feature +0 -38
- data/features/configuration/deprecation_stream.feature +0 -58
- data/features/configuration/fail_fast.feature +0 -77
- data/features/configuration/failure_exit_code.feature +0 -36
- data/features/configuration/order_and_seed.feature +0 -3
- data/features/configuration/output_stream.feature +0 -24
- data/features/configuration/pattern.feature +0 -38
- data/features/configuration/profile.feature +0 -220
- data/features/configuration/read_options_from_file.feature +0 -90
- data/features/configuration/run_all_when_everything_filtered.feature +0 -76
- data/features/configuration/show_failures_in_pending_blocks.feature +0 -61
- data/features/configuration/treat_symbols_as_metadata_keys_with_true_values.feature +0 -52
- data/features/example_groups/basic_structure.feature +0 -55
- data/features/example_groups/shared_context.feature +0 -74
- data/features/example_groups/shared_examples.feature +0 -294
- data/features/expectation_framework_integration/configure_expectation_framework.feature +0 -197
- data/features/filtering/exclusion_filters.feature +0 -138
- data/features/filtering/if_and_unless.feature +0 -168
- data/features/filtering/inclusion_filters.feature +0 -105
- data/features/formatters/configurable_colors.feature +0 -31
- data/features/formatters/custom_formatter.feature +0 -36
- data/features/formatters/json_formatter.feature +0 -30
- data/features/formatters/text_formatter.feature +0 -46
- data/features/helper_methods/arbitrary_methods.feature +0 -40
- data/features/helper_methods/let.feature +0 -50
- data/features/helper_methods/modules.feature +0 -149
- data/features/hooks/around_hooks.feature +0 -343
- data/features/hooks/before_and_after_hooks.feature +0 -427
- data/features/hooks/filtering.feature +0 -234
- data/features/metadata/current_example.feature +0 -56
- data/features/metadata/described_class.feature +0 -17
- data/features/metadata/user_defined.feature +0 -113
- data/features/mock_framework_integration/use_any_framework.feature +0 -106
- data/features/mock_framework_integration/use_flexmock.feature +0 -96
- data/features/mock_framework_integration/use_mocha.feature +0 -97
- data/features/mock_framework_integration/use_rr.feature +0 -98
- data/features/mock_framework_integration/use_rspec.feature +0 -97
- data/features/pending/pending_examples.feature +0 -229
- data/features/spec_files/arbitrary_file_suffix.feature +0 -13
- data/features/step_definitions/additional_cli_steps.rb +0 -49
- data/features/subject/attribute_of_subject.feature +0 -124
- data/features/subject/explicit_subject.feature +0 -101
- data/features/subject/implicit_subject.feature +0 -63
- data/features/subject/one_liner_syntax.feature +0 -71
- data/features/support/env.rb +0 -14
- data/features/support/rubinius.rb +0 -6
- 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/command_line.rb +0 -47
- data/lib/rspec/core/deprecated_mutable_array_proxy.rb +0 -32
- data/lib/rspec/core/deprecation.rb +0 -26
- data/lib/rspec/core/drb_command_line.rb +0 -26
- data/lib/rspec/core/drb_options.rb +0 -87
- 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/text_mate_formatter.rb +0 -34
- data/lib/rspec/core/metadata_hash_builder.rb +0 -97
- data/lib/rspec/core/mocking/with_absolutely_nothing.rb +0 -11
- data/lib/rspec/core/mocking/with_flexmock.rb +0 -27
- data/lib/rspec/core/mocking/with_rr.rb +0 -27
- data/lib/rspec/core/mocking/with_rspec.rb +0 -27
- data/lib/rspec/core/shared_example_group/collection.rb +0 -45
- 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/command_line/order_spec.rb +0 -204
- data/spec/rspec/core/backtrace_cleaner_spec.rb +0 -68
- data/spec/rspec/core/caller_filter_spec.rb +0 -58
- data/spec/rspec/core/command_line_spec.rb +0 -127
- data/spec/rspec/core/command_line_spec_output.txt +0 -0
- data/spec/rspec/core/configuration_options_spec.rb +0 -417
- data/spec/rspec/core/configuration_spec.rb +0 -2072
- data/spec/rspec/core/deprecation_spec.rb +0 -27
- data/spec/rspec/core/deprecations_spec.rb +0 -59
- data/spec/rspec/core/drb_command_line_spec.rb +0 -102
- data/spec/rspec/core/drb_options_spec.rb +0 -193
- data/spec/rspec/core/dsl_spec.rb +0 -25
- data/spec/rspec/core/example_group_spec.rb +0 -1337
- data/spec/rspec/core/example_spec.rb +0 -502
- data/spec/rspec/core/filter_manager_spec.rb +0 -246
- data/spec/rspec/core/formatters/base_formatter_spec.rb +0 -108
- data/spec/rspec/core/formatters/base_text_formatter_spec.rb +0 -524
- data/spec/rspec/core/formatters/console_codes_spec.rb +0 -50
- data/spec/rspec/core/formatters/deprecation_formatter_spec.rb +0 -263
- data/spec/rspec/core/formatters/documentation_formatter_spec.rb +0 -89
- data/spec/rspec/core/formatters/helpers_spec.rb +0 -104
- data/spec/rspec/core/formatters/html_formatted.html +0 -397
- data/spec/rspec/core/formatters/html_formatter_spec.rb +0 -131
- data/spec/rspec/core/formatters/json_formatter_spec.rb +0 -115
- data/spec/rspec/core/formatters/progress_formatter_spec.rb +0 -30
- data/spec/rspec/core/formatters/snippet_extractor_spec.rb +0 -26
- data/spec/rspec/core/formatters/text_mate_formatted.html +0 -397
- data/spec/rspec/core/formatters/text_mate_formatter_spec.rb +0 -107
- data/spec/rspec/core/hooks_filtering_spec.rb +0 -227
- data/spec/rspec/core/hooks_spec.rb +0 -269
- data/spec/rspec/core/kernel_extensions_spec.rb +0 -9
- data/spec/rspec/core/memoized_helpers_spec.rb +0 -776
- data/spec/rspec/core/metadata_spec.rb +0 -514
- data/spec/rspec/core/option_parser_spec.rb +0 -297
- data/spec/rspec/core/pending_example_spec.rb +0 -260
- data/spec/rspec/core/pending_spec.rb +0 -27
- data/spec/rspec/core/project_initializer_spec.rb +0 -130
- data/spec/rspec/core/rake_task_spec.rb +0 -202
- data/spec/rspec/core/reporter_spec.rb +0 -167
- data/spec/rspec/core/resources/a_bar.rb +0 -0
- data/spec/rspec/core/resources/a_foo.rb +0 -0
- data/spec/rspec/core/resources/a_spec.rb +0 -1
- data/spec/rspec/core/resources/custom_example_group_runner.rb +0 -14
- data/spec/rspec/core/resources/formatter_specs.rb +0 -60
- data/spec/rspec/core/resources/utf8_encoded.rb +0 -8
- data/spec/rspec/core/rspec_matchers_spec.rb +0 -45
- data/spec/rspec/core/ruby_project_spec.rb +0 -26
- data/spec/rspec/core/runner_spec.rb +0 -82
- data/spec/rspec/core/shared_context_spec.rb +0 -114
- data/spec/rspec/core/shared_example_group/collection_spec.rb +0 -70
- data/spec/rspec/core/shared_example_group_spec.rb +0 -138
- data/spec/rspec/core/world_spec.rb +0 -142
- data/spec/rspec/core_spec.rb +0 -108
- data/spec/spec_helper.rb +0 -135
- data/spec/support/config_options_helper.rb +0 -15
- data/spec/support/helper_methods.rb +0 -55
- data/spec/support/in_sub_process.rb +0 -37
- data/spec/support/isolate_load_path_mutation.rb +0 -6
- data/spec/support/isolated_directory.rb +0 -10
- data/spec/support/isolated_home_directory.rb +0 -16
- data/spec/support/matchers.rb +0 -65
- data/spec/support/mathn_integration_support.rb +0 -12
- data/spec/support/sandboxed_mock_space.rb +0 -116
- data/spec/support/shared_example_groups.rb +0 -42
- data/spec/support/silence_dsl_deprecations.rb +0 -32
- data/spec/support/spec_files.rb +0 -44
|
@@ -12,183 +12,278 @@ module RSpec
|
|
|
12
12
|
# The object returned by `it "does something"` is an instance of Example,
|
|
13
13
|
# which serves as a wrapper for an instance of the ExampleGroup in which it
|
|
14
14
|
# is declared.
|
|
15
|
+
#
|
|
16
|
+
# Example group bodies (e.g. `describe` or `context` blocks) are evaluated
|
|
17
|
+
# in the context of a new subclass of ExampleGroup. Individual examples are
|
|
18
|
+
# evalutaed in the context of an instance of the specific ExampleGroup subclass
|
|
19
|
+
# to which they belong.
|
|
20
|
+
#
|
|
21
|
+
# Besides the class methods defined here, there are other interesting macros
|
|
22
|
+
# defined in {Hooks}, {MemoizedHelpers::ClassMethods} and {SharedExampleGroup}.
|
|
23
|
+
# There are additional instance methods available to your examples defined in
|
|
24
|
+
# {MemoizedHelpers} and {Pending}.
|
|
15
25
|
class ExampleGroup
|
|
16
|
-
extend MetadataHashBuilder::WithDeprecationWarning
|
|
17
|
-
extend Extensions::ModuleEvalWithArgs
|
|
18
26
|
extend Hooks
|
|
19
27
|
|
|
20
28
|
include MemoizedHelpers
|
|
21
|
-
|
|
29
|
+
extend MemoizedHelpers::ClassMethods
|
|
22
30
|
include Pending
|
|
23
|
-
|
|
24
|
-
extend SharedExampleGroup
|
|
31
|
+
extend SharedExampleGroup
|
|
25
32
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
33
|
+
unless respond_to?(:define_singleton_method)
|
|
34
|
+
# @private
|
|
35
|
+
def self.define_singleton_method(*a, &b)
|
|
36
|
+
(class << self; self; end).__send__(:define_method, *a, &b)
|
|
37
|
+
end
|
|
29
38
|
end
|
|
30
39
|
|
|
31
|
-
#
|
|
32
|
-
|
|
33
|
-
|
|
40
|
+
# @!group Metadata
|
|
41
|
+
|
|
42
|
+
# The [Metadata](Metadata) object associated with this group.
|
|
43
|
+
# @see Metadata
|
|
44
|
+
def self.metadata
|
|
45
|
+
@metadata if defined?(@metadata)
|
|
34
46
|
end
|
|
35
47
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
metadata[:example_group][name]
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
end
|
|
48
|
+
# @private
|
|
49
|
+
# @return [Metadata] belonging to the parent of a nested {ExampleGroup}
|
|
50
|
+
def self.superclass_metadata
|
|
51
|
+
@superclass_metadata ||= self.superclass.respond_to?(:metadata) ? self.superclass.metadata : nil
|
|
52
|
+
end
|
|
45
53
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
54
|
+
# @private
|
|
55
|
+
def self.delegate_to_metadata(*names)
|
|
56
|
+
names.each do |name|
|
|
57
|
+
define_singleton_method(name) { metadata.fetch(name) }
|
|
49
58
|
end
|
|
59
|
+
end
|
|
50
60
|
|
|
51
|
-
|
|
61
|
+
delegate_to_metadata :described_class, :file_path, :location
|
|
52
62
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
end
|
|
63
|
+
# @return [String] the current example group description
|
|
64
|
+
def self.description
|
|
65
|
+
description = metadata[:description]
|
|
66
|
+
RSpec.configuration.format_docstrings_block.call(description)
|
|
67
|
+
end
|
|
59
68
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
69
|
+
# Returns the class or module passed to the `describe` method (or alias).
|
|
70
|
+
# Returns nil if the subject is not a class or module.
|
|
71
|
+
# @example
|
|
72
|
+
# describe Thing do
|
|
73
|
+
# it "does something" do
|
|
74
|
+
# described_class == Thing
|
|
75
|
+
# end
|
|
76
|
+
# end
|
|
77
|
+
#
|
|
78
|
+
#
|
|
79
|
+
def described_class
|
|
80
|
+
self.class.described_class
|
|
66
81
|
end
|
|
67
82
|
|
|
83
|
+
# @!endgroup
|
|
84
|
+
|
|
85
|
+
# @!group Defining Examples
|
|
86
|
+
|
|
68
87
|
# @private
|
|
69
88
|
# @macro [attach] define_example_method
|
|
70
|
-
#
|
|
71
|
-
# @param [
|
|
72
|
-
# @param [
|
|
89
|
+
# @!scope class
|
|
90
|
+
# @param name [String]
|
|
91
|
+
# @param extra_options [Hash]
|
|
92
|
+
# @param implementation [Block]
|
|
73
93
|
# @yield [Example] the example object
|
|
94
|
+
# @example
|
|
95
|
+
# $1 do
|
|
96
|
+
# end
|
|
97
|
+
#
|
|
98
|
+
# $1 "does something" do
|
|
99
|
+
# end
|
|
100
|
+
#
|
|
101
|
+
# $1 "does something", :with => 'additional metadata' do
|
|
102
|
+
# end
|
|
103
|
+
#
|
|
104
|
+
# $1 "does something" do |ex|
|
|
105
|
+
# # ex is the Example object that contains metadata about the example
|
|
106
|
+
# end
|
|
74
107
|
def self.define_example_method(name, extra_options={})
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
|
91
|
-
EOS
|
|
92
|
-
end
|
|
93
|
-
options = build_metadata_hash_from(args)
|
|
94
|
-
options.update(:pending => RSpec::Core::Pending::NOT_YET_IMPLEMENTED) unless block
|
|
95
|
-
# Backport from RSpec 3 to assist with upgrading
|
|
96
|
-
options.update(:pending => options[:skip]) if options[:skip]
|
|
97
|
-
options.update(#{extra_options.inspect})
|
|
98
|
-
examples << RSpec::Core::Example.new(self, desc, options, block)
|
|
99
|
-
examples.last
|
|
108
|
+
define_singleton_method(name) do |*all_args, &block|
|
|
109
|
+
desc, *args = *all_args
|
|
110
|
+
options = Metadata.build_hash_from(args)
|
|
111
|
+
options.update(:skip => RSpec::Core::Pending::NOT_YET_IMPLEMENTED) unless block
|
|
112
|
+
options.update(extra_options)
|
|
113
|
+
|
|
114
|
+
# Metadata inheritance normally happens in `Example#initialize`,
|
|
115
|
+
# but for `:pending` specifically we need it earlier.
|
|
116
|
+
pending_metadata = options[:pending] || metadata[:pending]
|
|
117
|
+
|
|
118
|
+
if pending_metadata
|
|
119
|
+
options, block = ExampleGroup.pending_metadata_and_block_for(
|
|
120
|
+
options.merge(:pending => pending_metadata),
|
|
121
|
+
block
|
|
122
|
+
)
|
|
100
123
|
end
|
|
101
|
-
|
|
124
|
+
|
|
125
|
+
examples << RSpec::Core::Example.new(self, desc, options, block)
|
|
126
|
+
examples.last
|
|
127
|
+
end
|
|
102
128
|
end
|
|
103
129
|
|
|
104
130
|
# Defines an example within a group.
|
|
105
|
-
# @example
|
|
106
|
-
# example do
|
|
107
|
-
# end
|
|
108
|
-
#
|
|
109
|
-
# example "does something" do
|
|
110
|
-
# end
|
|
111
|
-
#
|
|
112
|
-
# example "does something", :with => 'additional metadata' do
|
|
113
|
-
# end
|
|
114
|
-
#
|
|
115
|
-
# example "does something" do |ex|
|
|
116
|
-
# # ex is the Example object that evals this block
|
|
117
|
-
# end
|
|
118
131
|
define_example_method :example
|
|
119
132
|
# Defines an example within a group.
|
|
120
|
-
#
|
|
133
|
+
# This is the primary API to define a code example.
|
|
121
134
|
define_example_method :it
|
|
122
135
|
# Defines an example within a group.
|
|
123
|
-
#
|
|
124
|
-
#
|
|
125
|
-
#
|
|
136
|
+
# Useful for when your docstring does not read well off of `it`.
|
|
137
|
+
# @example
|
|
138
|
+
# RSpec.describe MyClass do
|
|
139
|
+
# specify "#do_something is deprecated" do
|
|
140
|
+
# # ...
|
|
141
|
+
# end
|
|
142
|
+
# end
|
|
126
143
|
define_example_method :specify
|
|
127
144
|
|
|
128
|
-
# Shortcut to define an example with `:focus
|
|
145
|
+
# Shortcut to define an example with `:focus => true`
|
|
129
146
|
# @see example
|
|
130
|
-
define_example_method :focus,
|
|
131
|
-
# Shortcut to define an example with `:focus
|
|
147
|
+
define_example_method :focus, :focus => true
|
|
148
|
+
# Shortcut to define an example with `:focus => true`
|
|
132
149
|
# @see example
|
|
133
|
-
define_example_method :
|
|
134
|
-
|
|
135
|
-
# Shortcut to define an example with :pending => true
|
|
150
|
+
define_example_method :fexample, :focus => true
|
|
151
|
+
# Shortcut to define an example with `:focus => true`
|
|
136
152
|
# @see example
|
|
137
|
-
define_example_method :
|
|
138
|
-
# Shortcut to define an example with
|
|
139
|
-
# Backported from RSpec 3 to aid migration.
|
|
153
|
+
define_example_method :fit, :focus => true
|
|
154
|
+
# Shortcut to define an example with `:focus => true`
|
|
140
155
|
# @see example
|
|
141
|
-
define_example_method :
|
|
142
|
-
# Shortcut to define an example with
|
|
156
|
+
define_example_method :fspecify, :focus => true
|
|
157
|
+
# Shortcut to define an example with `:skip => 'Temporarily skipped with xexample'`
|
|
143
158
|
# @see example
|
|
144
|
-
define_example_method :xexample, :
|
|
145
|
-
# Shortcut to define an example with
|
|
159
|
+
define_example_method :xexample, :skip => 'Temporarily skipped with xexample'
|
|
160
|
+
# Shortcut to define an example with `:skip => 'Temporarily skipped with xit'`
|
|
146
161
|
# @see example
|
|
147
|
-
define_example_method :xit, :
|
|
148
|
-
# Shortcut to define an example with
|
|
162
|
+
define_example_method :xit, :skip => 'Temporarily skipped with xit'
|
|
163
|
+
# Shortcut to define an example with `:skip => 'Temporarily skipped with xspecify'`
|
|
149
164
|
# @see example
|
|
150
|
-
define_example_method :xspecify, :
|
|
151
|
-
|
|
152
|
-
#
|
|
165
|
+
define_example_method :xspecify, :skip => 'Temporarily skipped with xspecify'
|
|
166
|
+
# Shortcut to define an example with `:skip => true`
|
|
167
|
+
# @see example
|
|
168
|
+
define_example_method :skip, :skip => true
|
|
169
|
+
# Shortcut to define an example with `:pending => true`
|
|
153
170
|
# @see example
|
|
154
|
-
|
|
155
|
-
RSpec.deprecate("`RSpec::Core::ExampleGroup.focused`",
|
|
156
|
-
:replacement => "`RSpec::Core::ExampleGroup.focus`")
|
|
171
|
+
define_example_method :pending, :pending => true
|
|
157
172
|
|
|
158
|
-
|
|
159
|
-
metadata.merge!(:focus => true, :focused => true)
|
|
160
|
-
args << metadata
|
|
173
|
+
# @!endgroup
|
|
161
174
|
|
|
162
|
-
|
|
163
|
-
end
|
|
175
|
+
# @!group Defining Example Groups
|
|
164
176
|
|
|
165
|
-
#
|
|
166
|
-
#
|
|
177
|
+
# @private
|
|
178
|
+
# @macro [attach] alias_example_group_to
|
|
179
|
+
# @!scope class
|
|
180
|
+
# @param name [String] The example group doc string
|
|
181
|
+
# @param metadata [Hash] Additional metadata to attach to the example group
|
|
182
|
+
# @yield The example group definition
|
|
183
|
+
#
|
|
184
|
+
# Generates a subclass of this example group which inherits
|
|
185
|
+
# everything except the examples themselves.
|
|
186
|
+
#
|
|
187
|
+
# @example
|
|
188
|
+
#
|
|
189
|
+
# RSpec.describe "something" do # << This describe method is defined in
|
|
190
|
+
# # << RSpec::Core::DSL, included in the
|
|
191
|
+
# # << global namespace (optional)
|
|
192
|
+
# before do
|
|
193
|
+
# do_something_before
|
|
194
|
+
# end
|
|
167
195
|
#
|
|
168
|
-
#
|
|
169
|
-
#
|
|
170
|
-
#
|
|
171
|
-
#
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
196
|
+
# let(:thing) { Thing.new }
|
|
197
|
+
#
|
|
198
|
+
# $1 "attribute (of something)" do
|
|
199
|
+
# # examples in the group get the before hook
|
|
200
|
+
# # declared above, and can access `thing`
|
|
201
|
+
# end
|
|
202
|
+
# end
|
|
203
|
+
#
|
|
204
|
+
# @see DSL#describe
|
|
205
|
+
def self.define_example_group_method(name, metadata={})
|
|
206
|
+
define_singleton_method(name) do |*args, &example_group_block|
|
|
207
|
+
thread_data = RSpec.thread_local_metadata
|
|
208
|
+
top_level = self == ExampleGroup
|
|
209
|
+
|
|
210
|
+
if top_level
|
|
211
|
+
if thread_data[:in_example_group]
|
|
212
|
+
raise "Creating an isolated context from within a context is " +
|
|
213
|
+
"not allowed. Change `RSpec.#{name}` to `#{name}` or " +
|
|
214
|
+
"move this to a top-level scope."
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
thread_data[:in_example_group] = true
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
begin
|
|
221
|
+
|
|
222
|
+
description = args.shift
|
|
223
|
+
combined_metadata = metadata.dup
|
|
224
|
+
combined_metadata.merge!(args.pop) if args.last.is_a? Hash
|
|
225
|
+
args << combined_metadata
|
|
226
|
+
|
|
227
|
+
subclass(self, description, args, &example_group_block).tap do |child|
|
|
228
|
+
children << child
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
ensure
|
|
232
|
+
thread_data.delete(:in_example_group) if top_level
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
RSpec::Core::DSL.expose_example_group_alias(name)
|
|
176
237
|
end
|
|
177
238
|
|
|
239
|
+
define_example_group_method :example_group
|
|
240
|
+
|
|
241
|
+
# An alias of `example_group`. Generally used when grouping
|
|
242
|
+
# examples by a thing you are describing (e.g. an object, class or method).
|
|
243
|
+
# @see example_group
|
|
244
|
+
define_example_group_method :describe
|
|
245
|
+
|
|
246
|
+
# An alias of `example_group`. Generally used when grouping examples
|
|
247
|
+
# contextually (e.g. "with xyz", "when xyz" or "if xyz").
|
|
248
|
+
# @see example_group
|
|
249
|
+
define_example_group_method :context
|
|
250
|
+
|
|
251
|
+
# Shortcut to temporarily make an example group skipped.
|
|
252
|
+
# @see example_group
|
|
253
|
+
define_example_group_method :xdescribe, :skip => "Temporarily skipped with xdescribe"
|
|
254
|
+
|
|
255
|
+
# Shortcut to temporarily make an example group skipped.
|
|
256
|
+
# @see example_group
|
|
257
|
+
define_example_group_method :xcontext, :skip => "Temporarily skipped with xcontext"
|
|
258
|
+
|
|
259
|
+
# Shortcut to define an example group with `:focus => true`.
|
|
260
|
+
# @see example_group
|
|
261
|
+
define_example_group_method :fdescribe, :focus => true
|
|
262
|
+
|
|
263
|
+
# Shortcut to define an example group with `:focus => true`.
|
|
264
|
+
# @see example_group
|
|
265
|
+
define_example_group_method :fcontext, :focus => true
|
|
266
|
+
|
|
267
|
+
# @!endgroup
|
|
268
|
+
|
|
269
|
+
# @!group Including Shared Example Groups
|
|
270
|
+
|
|
178
271
|
# @private
|
|
179
272
|
# @macro [attach] define_nested_shared_group_method
|
|
273
|
+
# @!scope class
|
|
180
274
|
#
|
|
181
275
|
# @see SharedExampleGroup
|
|
182
|
-
def self.define_nested_shared_group_method(new_name, report_label=
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
group
|
|
276
|
+
def self.define_nested_shared_group_method(new_name, report_label="it should behave like")
|
|
277
|
+
define_singleton_method(new_name) do |name, *args, &customization_block|
|
|
278
|
+
# Pass :caller so the :location metadata is set properly...
|
|
279
|
+
# otherwise, it'll be set to the next line because that's
|
|
280
|
+
# the block's source_location.
|
|
281
|
+
group = example_group("#{report_label} #{name}", :caller => caller) do
|
|
282
|
+
find_and_eval_shared("examples", name, *args, &customization_block)
|
|
190
283
|
end
|
|
191
|
-
|
|
284
|
+
group.metadata[:shared_group_name] = name
|
|
285
|
+
group
|
|
286
|
+
end
|
|
192
287
|
end
|
|
193
288
|
|
|
194
289
|
# Generates a nested example group and includes the shared content
|
|
@@ -198,19 +293,6 @@ module RSpec
|
|
|
198
293
|
# mapped to `name` in the nested group.
|
|
199
294
|
define_nested_shared_group_method :it_should_behave_like
|
|
200
295
|
|
|
201
|
-
# Works like `alias_method :name, :it_behaves_like` with the added
|
|
202
|
-
# benefit of assigning default metadata to the generated example.
|
|
203
|
-
#
|
|
204
|
-
# @note Use with caution. This extends the language used in your
|
|
205
|
-
# specs, but does not add any additional documentation. We use this
|
|
206
|
-
# in rspec to define `it_should_behave_like` (for backward
|
|
207
|
-
# compatibility), but we also add docs for that method.
|
|
208
|
-
def self.alias_it_behaves_like_to name, *args, &block
|
|
209
|
-
RSpec.deprecate("`RSpec::Core::ExampleGroup.alias_it_behaves_like_to`",
|
|
210
|
-
:replacement => "`RSpec::Core::Configuration#alias_it_behaves_like_to`")
|
|
211
|
-
define_nested_shared_group_method name, *args, &block
|
|
212
|
-
end
|
|
213
|
-
|
|
214
296
|
# Includes shared content mapped to `name` directly in the group in which
|
|
215
297
|
# it is declared, as opposed to `it_behaves_like`, which creates a nested
|
|
216
298
|
# group. If given a block, that block is also eval'd in the current context.
|
|
@@ -229,156 +311,75 @@ module RSpec
|
|
|
229
311
|
find_and_eval_shared("examples", name, *args, &block)
|
|
230
312
|
end
|
|
231
313
|
|
|
232
|
-
if Proc.method_defined?(:parameters) # for >= 1.9
|
|
233
|
-
# Warn when submitting the name of more than one example group to
|
|
234
|
-
# include_examples, it_behaves_like, etc.
|
|
235
|
-
#
|
|
236
|
-
# Helpful when upgrading from rspec-1 (which supported multiple shared
|
|
237
|
-
# groups in one call) to rspec-2 (which does not).
|
|
238
|
-
#
|
|
239
|
-
# See https://github.com/rspec/rspec-core/issues/1066 for background.
|
|
240
|
-
def self.warn_unexpected_args(label, name, args, shared_block)
|
|
241
|
-
if !args.empty? && shared_block.parameters.count == 0
|
|
242
|
-
if shared_example_groups[args.first]
|
|
243
|
-
warn <<-WARNING
|
|
244
|
-
shared #{label} support#{'s' if /context/ =~ label.to_s} the name of only one example group, received #{[name, *args].inspect}
|
|
245
|
-
called from #{CallerFilter.first_non_rspec_line}"
|
|
246
|
-
WARNING
|
|
247
|
-
else
|
|
248
|
-
warn <<-WARNING
|
|
249
|
-
shared #{label} #{name.inspect} expected #{shared_block.arity} args, got #{args.inspect}
|
|
250
|
-
called from #{CallerFilter.first_non_rspec_line}"
|
|
251
|
-
WARNING
|
|
252
|
-
end
|
|
253
|
-
end
|
|
254
|
-
end
|
|
255
|
-
else
|
|
256
|
-
# no-op for Ruby < 1.9
|
|
257
|
-
#
|
|
258
|
-
# Ruby 1.8 reports lambda {}.arity == -1, so can't support this warning
|
|
259
|
-
# reliably
|
|
260
|
-
def self.warn_unexpected_args(*)
|
|
261
|
-
end
|
|
262
|
-
end
|
|
263
|
-
|
|
264
314
|
# @private
|
|
265
315
|
def self.find_and_eval_shared(label, name, *args, &customization_block)
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
warn_unexpected_args(label, name, args, shared_block)
|
|
316
|
+
unless shared_block = RSpec.world.shared_example_group_registry.find(parent_groups, name)
|
|
317
|
+
raise ArgumentError, "Could not find shared #{label} #{name.inspect}"
|
|
318
|
+
end
|
|
270
319
|
|
|
271
|
-
|
|
272
|
-
|
|
320
|
+
module_exec(*args, &shared_block)
|
|
321
|
+
module_exec(&customization_block) if customization_block
|
|
273
322
|
end
|
|
274
323
|
|
|
275
|
-
#
|
|
276
|
-
def self.examples
|
|
277
|
-
@examples ||= []
|
|
278
|
-
end
|
|
324
|
+
# @!endgroup
|
|
279
325
|
|
|
280
326
|
# @private
|
|
281
|
-
def self.
|
|
282
|
-
|
|
283
|
-
|
|
327
|
+
def self.subclass(parent, description, args, &example_group_block)
|
|
328
|
+
subclass = Class.new(parent)
|
|
329
|
+
subclass.set_it_up(description, *args, &example_group_block)
|
|
330
|
+
ExampleGroups.assign_const(subclass)
|
|
331
|
+
subclass.module_exec(&example_group_block) if example_group_block
|
|
284
332
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
333
|
+
# The LetDefinitions module must be included _after_ other modules
|
|
334
|
+
# to ensure that it takes precedence when there are name collisions.
|
|
335
|
+
# Thus, we delay including it until after the example group block
|
|
336
|
+
# has been eval'd.
|
|
337
|
+
MemoizedHelpers.define_helpers_on(subclass)
|
|
289
338
|
|
|
290
|
-
|
|
291
|
-
# @see Metadata
|
|
292
|
-
def self.metadata
|
|
293
|
-
@metadata if defined?(@metadata)
|
|
339
|
+
subclass
|
|
294
340
|
end
|
|
295
341
|
|
|
296
342
|
# @private
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
343
|
+
def self.set_it_up(*args, &example_group_block)
|
|
344
|
+
# Ruby 1.9 has a bug that can lead to infinite recursion and a
|
|
345
|
+
# SystemStackError if you include a module in a superclass after
|
|
346
|
+
# including it in a subclass: https://gist.github.com/845896
|
|
347
|
+
# To prevent this, we must include any modules in RSpec::Core::ExampleGroup
|
|
348
|
+
# before users create example groups and have a chance to include
|
|
349
|
+
# the same module in a subclass of RSpec::Core::ExampleGroup.
|
|
350
|
+
# So we need to configure example groups here.
|
|
351
|
+
ensure_example_groups_are_configured
|
|
301
352
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
# ## Examples
|
|
306
|
-
#
|
|
307
|
-
# describe "something" do # << This describe method is defined in
|
|
308
|
-
# # << RSpec::Core::DSL, included in the
|
|
309
|
-
# # << global namespace
|
|
310
|
-
# before do
|
|
311
|
-
# do_something_before
|
|
312
|
-
# end
|
|
313
|
-
#
|
|
314
|
-
# let(:thing) { Thing.new }
|
|
315
|
-
#
|
|
316
|
-
# describe "attribute (of something)" do
|
|
317
|
-
# # examples in the group get the before hook
|
|
318
|
-
# # declared above, and can access `thing`
|
|
319
|
-
# end
|
|
320
|
-
# end
|
|
321
|
-
#
|
|
322
|
-
# @see DSL#describe
|
|
323
|
-
def self.describe(*args, &example_group_block)
|
|
324
|
-
@_subclass_count ||= 0
|
|
325
|
-
@_subclass_count += 1
|
|
326
|
-
|
|
327
|
-
if Symbol === args.first || Hash === args.first
|
|
328
|
-
description_arg_behavior_changing_in_rspec_3 = DescriptionBehaviorChange.new(
|
|
329
|
-
args.first, CallerFilter.first_non_rspec_line
|
|
330
|
-
)
|
|
331
|
-
end
|
|
353
|
+
description = args.shift
|
|
354
|
+
user_metadata = Metadata.build_hash_from(args)
|
|
355
|
+
args.unshift(description)
|
|
332
356
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
:example_group_block => example_group_block,
|
|
336
|
-
:description_arg_behavior_changing_in_rspec_3 => description_arg_behavior_changing_in_rspec_3
|
|
357
|
+
@metadata = Metadata::ExampleGroupHash.create(
|
|
358
|
+
superclass_metadata, user_metadata, *args, &example_group_block
|
|
337
359
|
)
|
|
338
360
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
"Nested_#{@_subclass_count}",
|
|
342
|
-
subclass(self, args, &example_group_block)
|
|
343
|
-
)
|
|
344
|
-
children << child
|
|
345
|
-
child
|
|
346
|
-
end
|
|
347
|
-
|
|
348
|
-
DescriptionBehaviorChange = Struct.new(:arg, :call_site) do
|
|
349
|
-
def warning
|
|
350
|
-
<<-EOS.gsub(/^\s+\|/, '')
|
|
351
|
-
|The semantics of `describe <a #{arg.class.name}>` are changing in RSpec 3. In RSpec 2,
|
|
352
|
-
|this would be treated as metadata, but as the first `describe` argument,
|
|
353
|
-
|this will be treated as the described object in RSpec 3. If you want this
|
|
354
|
-
|to be treated as metadata, pass a description as the first argument.
|
|
355
|
-
|(Example group defined at #{call_site})
|
|
356
|
-
EOS
|
|
357
|
-
end
|
|
361
|
+
hooks.register_globals(self, RSpec.configuration.hooks)
|
|
362
|
+
RSpec.world.configure_group(self)
|
|
358
363
|
end
|
|
359
364
|
|
|
360
|
-
|
|
361
|
-
|
|
365
|
+
# @private
|
|
366
|
+
def self.examples
|
|
367
|
+
@examples ||= []
|
|
362
368
|
end
|
|
363
369
|
|
|
364
370
|
# @private
|
|
365
|
-
def self.
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
subclass.module_eval(&example_group_block) if example_group_block
|
|
369
|
-
|
|
370
|
-
# The LetDefinitions module must be included _after_ other modules
|
|
371
|
-
# to ensure that it takes precendence when there are name collisions.
|
|
372
|
-
# Thus, we delay including it until after the example group block
|
|
373
|
-
# has been eval'd.
|
|
374
|
-
MemoizedHelpers.define_helpers_on(subclass)
|
|
371
|
+
def self.filtered_examples
|
|
372
|
+
RSpec.world.filtered_examples[self]
|
|
373
|
+
end
|
|
375
374
|
|
|
376
|
-
|
|
375
|
+
# @private
|
|
376
|
+
def self.descendant_filtered_examples
|
|
377
|
+
@descendant_filtered_examples ||= filtered_examples + children.inject([]){|l,c| l + c.descendant_filtered_examples}
|
|
377
378
|
end
|
|
378
379
|
|
|
379
380
|
# @private
|
|
380
381
|
def self.children
|
|
381
|
-
@children ||= []
|
|
382
|
+
@children ||= []
|
|
382
383
|
end
|
|
383
384
|
|
|
384
385
|
# @private
|
|
@@ -406,124 +407,103 @@ WARNING
|
|
|
406
407
|
end
|
|
407
408
|
|
|
408
409
|
# @private
|
|
409
|
-
def self.
|
|
410
|
-
|
|
411
|
-
# SystemStackError if you include a module in a superclass after
|
|
412
|
-
# including it in a subclass: https://gist.github.com/845896
|
|
413
|
-
# To prevent this, we must include any modules in RSpec::Core::ExampleGroup
|
|
414
|
-
# before users create example groups and have a chance to include
|
|
415
|
-
# the same module in a subclass of RSpec::Core::ExampleGroup.
|
|
416
|
-
# So we need to configure example groups here.
|
|
417
|
-
ensure_example_groups_are_configured
|
|
418
|
-
|
|
419
|
-
symbol_description = args.shift if args.first.is_a?(Symbol)
|
|
420
|
-
args << build_metadata_hash_from(args)
|
|
421
|
-
args.unshift(symbol_description) if symbol_description
|
|
422
|
-
@metadata = RSpec::Core::Metadata.new(superclass_metadata).process(*args)
|
|
423
|
-
hooks.register_globals(self, RSpec.configuration.hooks)
|
|
424
|
-
world.configure_group(self)
|
|
425
|
-
end
|
|
426
|
-
|
|
427
|
-
# @private
|
|
428
|
-
def self.before_all_ivars
|
|
429
|
-
@before_all_ivars ||= {}
|
|
410
|
+
def self.before_context_ivars
|
|
411
|
+
@before_context_ivars ||= {}
|
|
430
412
|
end
|
|
431
413
|
|
|
432
414
|
# @private
|
|
433
|
-
def self.
|
|
415
|
+
def self.store_before_context_ivars(example_group_instance)
|
|
434
416
|
return if example_group_instance.instance_variables.empty?
|
|
435
417
|
|
|
436
418
|
example_group_instance.instance_variables.each { |ivar|
|
|
437
|
-
|
|
419
|
+
before_context_ivars[ivar] = example_group_instance.instance_variable_get(ivar)
|
|
438
420
|
}
|
|
439
421
|
end
|
|
440
422
|
|
|
441
423
|
# @private
|
|
442
|
-
def self.
|
|
443
|
-
ivars.each { |ivar, val| example_group_instance.instance_variable_set(ivar, val) }
|
|
444
|
-
end
|
|
445
|
-
|
|
446
|
-
# @private
|
|
447
|
-
def self.run_before_all_hooks(example_group_instance)
|
|
424
|
+
def self.run_before_context_hooks(example_group_instance)
|
|
448
425
|
return if descendant_filtered_examples.empty?
|
|
449
426
|
begin
|
|
450
|
-
|
|
427
|
+
set_ivars(example_group_instance, superclass.before_context_ivars)
|
|
451
428
|
|
|
452
|
-
|
|
453
|
-
|
|
429
|
+
ContextHookMemoizedHash::Before.isolate_for_context_hook(example_group_instance) do
|
|
430
|
+
hooks.run(:before, :context, example_group_instance)
|
|
454
431
|
end
|
|
455
432
|
ensure
|
|
456
|
-
|
|
433
|
+
store_before_context_ivars(example_group_instance)
|
|
457
434
|
end
|
|
458
435
|
end
|
|
459
436
|
|
|
460
437
|
# @private
|
|
461
|
-
def self.
|
|
462
|
-
run_hook(:around, :each, example, initial_procsy)
|
|
463
|
-
end
|
|
464
|
-
|
|
465
|
-
# @private
|
|
466
|
-
def self.run_before_each_hooks(example)
|
|
467
|
-
run_hook(:before, :each, example)
|
|
468
|
-
end
|
|
469
|
-
|
|
470
|
-
# @private
|
|
471
|
-
def self.run_after_each_hooks(example)
|
|
472
|
-
run_hook(:after, :each, example)
|
|
473
|
-
end
|
|
474
|
-
|
|
475
|
-
# @private
|
|
476
|
-
def self.run_after_all_hooks(example_group_instance)
|
|
438
|
+
def self.run_after_context_hooks(example_group_instance)
|
|
477
439
|
return if descendant_filtered_examples.empty?
|
|
478
|
-
|
|
440
|
+
set_ivars(example_group_instance, before_context_ivars)
|
|
479
441
|
|
|
480
|
-
|
|
481
|
-
|
|
442
|
+
ContextHookMemoizedHash::After.isolate_for_context_hook(example_group_instance) do
|
|
443
|
+
hooks.run(:after, :context, example_group_instance)
|
|
482
444
|
end
|
|
483
445
|
end
|
|
484
446
|
|
|
485
447
|
# Runs all the examples in this group
|
|
486
448
|
def self.run(reporter)
|
|
487
|
-
if RSpec.wants_to_quit
|
|
488
|
-
RSpec.clear_remaining_example_groups if top_level?
|
|
449
|
+
if RSpec.world.wants_to_quit
|
|
450
|
+
RSpec.world.clear_remaining_example_groups if top_level?
|
|
489
451
|
return
|
|
490
452
|
end
|
|
491
453
|
reporter.example_group_started(self)
|
|
492
454
|
|
|
493
455
|
begin
|
|
494
|
-
|
|
456
|
+
run_before_context_hooks(new)
|
|
495
457
|
result_for_this_group = run_examples(reporter)
|
|
496
|
-
results_for_descendants = children.
|
|
458
|
+
results_for_descendants = ordering_strategy.order(children).map { |child| child.run(reporter) }.all?
|
|
497
459
|
result_for_this_group && results_for_descendants
|
|
460
|
+
rescue Pending::SkipDeclaredInExample => ex
|
|
461
|
+
for_filtered_examples(reporter) {|example| example.skip_with_exception(reporter, ex) }
|
|
498
462
|
rescue Exception => ex
|
|
499
|
-
RSpec.wants_to_quit = true if fail_fast?
|
|
500
|
-
|
|
463
|
+
RSpec.world.wants_to_quit = true if fail_fast?
|
|
464
|
+
for_filtered_examples(reporter) {|example| example.fail_with_exception(reporter, ex) }
|
|
501
465
|
ensure
|
|
502
|
-
|
|
503
|
-
|
|
466
|
+
run_after_context_hooks(new)
|
|
467
|
+
before_context_ivars.clear
|
|
504
468
|
reporter.example_group_finished(self)
|
|
505
469
|
end
|
|
506
470
|
end
|
|
507
471
|
|
|
472
|
+
# @private
|
|
473
|
+
def self.ordering_strategy
|
|
474
|
+
order = metadata.fetch(:order, :global)
|
|
475
|
+
registry = RSpec.configuration.ordering_registry
|
|
476
|
+
|
|
477
|
+
registry.fetch(order) do
|
|
478
|
+
warn <<-WARNING.gsub(/^ +\|/, '')
|
|
479
|
+
|WARNING: Ignoring unknown ordering specified using `:order => #{order.inspect}` metadata.
|
|
480
|
+
| Falling back to configured global ordering.
|
|
481
|
+
| Unrecognized ordering specified at: #{location}
|
|
482
|
+
WARNING
|
|
483
|
+
|
|
484
|
+
registry.fetch(:global)
|
|
485
|
+
end
|
|
486
|
+
end
|
|
487
|
+
|
|
508
488
|
# @private
|
|
509
489
|
def self.run_examples(reporter)
|
|
510
|
-
filtered_examples.
|
|
511
|
-
next if RSpec.wants_to_quit
|
|
490
|
+
ordering_strategy.order(filtered_examples).map do |example|
|
|
491
|
+
next if RSpec.world.wants_to_quit
|
|
512
492
|
instance = new
|
|
513
|
-
set_ivars(instance,
|
|
493
|
+
set_ivars(instance, before_context_ivars)
|
|
514
494
|
succeeded = example.run(instance, reporter)
|
|
515
|
-
RSpec.wants_to_quit = true if fail_fast? && !succeeded
|
|
495
|
+
RSpec.world.wants_to_quit = true if fail_fast? && !succeeded
|
|
516
496
|
succeeded
|
|
517
497
|
end.all?
|
|
518
498
|
end
|
|
519
499
|
|
|
520
500
|
# @private
|
|
521
|
-
def self.
|
|
522
|
-
filtered_examples.each
|
|
501
|
+
def self.for_filtered_examples(reporter, &block)
|
|
502
|
+
filtered_examples.each(&block)
|
|
523
503
|
|
|
524
504
|
children.each do |child|
|
|
525
505
|
reporter.example_group_started(child)
|
|
526
|
-
child.
|
|
506
|
+
child.for_filtered_examples(reporter, &block)
|
|
527
507
|
reporter.example_group_finished(child)
|
|
528
508
|
end
|
|
529
509
|
false
|
|
@@ -536,17 +516,17 @@ WARNING
|
|
|
536
516
|
|
|
537
517
|
# @private
|
|
538
518
|
def self.any_apply?(filters)
|
|
539
|
-
|
|
519
|
+
MetadataFilter.any_apply?(filters, metadata)
|
|
540
520
|
end
|
|
541
521
|
|
|
542
522
|
# @private
|
|
543
523
|
def self.all_apply?(filters)
|
|
544
|
-
|
|
524
|
+
MetadataFilter.all_apply?(filters, metadata)
|
|
545
525
|
end
|
|
546
526
|
|
|
547
527
|
# @private
|
|
548
528
|
def self.declaration_line_numbers
|
|
549
|
-
@declaration_line_numbers ||= [metadata[:
|
|
529
|
+
@declaration_line_numbers ||= [metadata[:line_number]] +
|
|
550
530
|
examples.collect {|e| e.metadata[:line_number]} +
|
|
551
531
|
children.inject([]) {|l,c| l + c.declaration_line_numbers}
|
|
552
532
|
end
|
|
@@ -561,72 +541,80 @@ WARNING
|
|
|
561
541
|
ivars.each {|name, value| instance.instance_variable_set(name, value)}
|
|
562
542
|
end
|
|
563
543
|
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
544
|
+
# @private
|
|
545
|
+
def self.pending_metadata_and_block_for(options, block)
|
|
546
|
+
if String === options[:pending]
|
|
547
|
+
reason = options[:pending]
|
|
548
|
+
else
|
|
549
|
+
options[:pending] = true
|
|
550
|
+
reason = RSpec::Core::Pending::NO_REASON_GIVEN
|
|
551
|
+
end
|
|
567
552
|
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
RSpec.current_example
|
|
572
|
-
end
|
|
553
|
+
# Assign :caller so that the callback's source_location isn't used
|
|
554
|
+
# as the example location.
|
|
555
|
+
options[:caller] ||= Metadata.backtrace_from(block)
|
|
573
556
|
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
end
|
|
557
|
+
# This will fail if no block is provided, which is effectively the
|
|
558
|
+
# same as failing the example so it will be marked correctly as
|
|
559
|
+
# pending.
|
|
560
|
+
callback = Proc.new { pending(reason); instance_exec(&block) }
|
|
579
561
|
|
|
580
|
-
|
|
581
|
-
RSpec.warn_deprecation(<<-EOS.gsub(/^\s*\|/, ''))
|
|
582
|
-
|RSpec::Core::ExampleGroup##{name} is deprecated and will be removed
|
|
583
|
-
|in RSpec 3. There are a few options for what you can use instead:
|
|
584
|
-
|
|
|
585
|
-
| - rspec-core's DSL methods (`it`, `before`, `after`, `let`, `subject`, etc)
|
|
586
|
-
| now yield the example as a block argument, and that is the recommended
|
|
587
|
-
| way to access the current example from those contexts.
|
|
588
|
-
| - The current example is now exposed via `RSpec.current_example`,
|
|
589
|
-
| which is accessible from any context.
|
|
590
|
-
| - If you can't update the code at this call site (e.g. because it is in
|
|
591
|
-
| an extension gem), you can use this snippet to continue making this
|
|
592
|
-
| method available in RSpec 2.99 and RSpec 3:
|
|
593
|
-
|
|
|
594
|
-
| RSpec.configure do |c|
|
|
595
|
-
| c.expose_current_running_example_as :#{name}
|
|
596
|
-
| end
|
|
597
|
-
|
|
|
598
|
-
|(Called from #{CallerFilter.first_non_rspec_line})
|
|
599
|
-
EOS
|
|
562
|
+
return options, callback
|
|
600
563
|
end
|
|
564
|
+
end
|
|
601
565
|
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
# described_class == Thing
|
|
608
|
-
# end
|
|
609
|
-
# end
|
|
610
|
-
#
|
|
611
|
-
#
|
|
612
|
-
def described_class
|
|
613
|
-
self.class.described_class
|
|
566
|
+
# @private
|
|
567
|
+
# Unnamed example group used by `SuiteHookContext`.
|
|
568
|
+
class AnonymousExampleGroup < ExampleGroup
|
|
569
|
+
def self.metadata
|
|
570
|
+
{}
|
|
614
571
|
end
|
|
572
|
+
end
|
|
573
|
+
end
|
|
615
574
|
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
575
|
+
# @private
|
|
576
|
+
#
|
|
577
|
+
# Namespace for the example group subclasses generated by top-level `describe`.
|
|
578
|
+
module ExampleGroups
|
|
579
|
+
def self.assign_const(group)
|
|
580
|
+
base_name = base_name_for(group)
|
|
581
|
+
const_scope = constant_scope_for(group)
|
|
582
|
+
name = disambiguate(base_name, const_scope)
|
|
583
|
+
|
|
584
|
+
const_scope.const_set(name, group)
|
|
585
|
+
end
|
|
586
|
+
|
|
587
|
+
def self.constant_scope_for(group)
|
|
588
|
+
const_scope = group.superclass
|
|
589
|
+
const_scope = self if const_scope == Core::ExampleGroup
|
|
590
|
+
const_scope
|
|
591
|
+
end
|
|
592
|
+
|
|
593
|
+
def self.base_name_for(group)
|
|
594
|
+
return "Anonymous" if group.description.empty?
|
|
595
|
+
|
|
596
|
+
# convert to CamelCase
|
|
597
|
+
name = ' ' + group.description
|
|
598
|
+
name.gsub!(/[^0-9a-zA-Z]+([0-9a-zA-Z])/) { $1.upcase }
|
|
599
|
+
|
|
600
|
+
name.lstrip! # Remove leading whitespace
|
|
601
|
+
name.gsub!(/\W/, '') # JRuby, RBX and others don't like non-ascii in const names
|
|
602
|
+
|
|
603
|
+
# Ruby requires first const letter to be A-Z. Use `Nested`
|
|
604
|
+
# as necessary to enforce that.
|
|
605
|
+
name.gsub!(/\A([^A-Z]|\z)/, 'Nested\1')
|
|
606
|
+
|
|
607
|
+
name
|
|
608
|
+
end
|
|
609
|
+
|
|
610
|
+
def self.disambiguate(name, const_scope)
|
|
611
|
+
return name unless const_scope.const_defined?(name)
|
|
612
|
+
|
|
613
|
+
# Add a trailing number if needed to disambiguate from an existing constant.
|
|
614
|
+
name << "_2"
|
|
615
|
+
name.next! while const_scope.const_defined?(name)
|
|
616
|
+
name
|
|
630
617
|
end
|
|
631
618
|
end
|
|
632
619
|
end
|
|
620
|
+
|