rspec-core 3.0.0.beta2 → 3.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.yardopts +1 -0
- data/Changelog.md +297 -57
- data/README.md +16 -13
- data/lib/rspec/core.rb +55 -84
- data/lib/rspec/core/backport_random.rb +35 -3
- data/lib/rspec/core/backtrace_formatter.rb +4 -13
- data/lib/rspec/core/configuration.rb +330 -114
- data/lib/rspec/core/configuration_options.rb +38 -22
- data/lib/rspec/core/drb.rb +111 -0
- data/lib/rspec/core/dsl.rb +8 -2
- data/lib/rspec/core/example.rb +203 -94
- data/lib/rspec/core/example_group.rb +344 -316
- data/lib/rspec/core/filter_manager.rb +135 -90
- data/lib/rspec/core/flat_map.rb +1 -0
- data/lib/rspec/core/formatters.rb +50 -14
- data/lib/rspec/core/formatters/base_formatter.rb +32 -138
- data/lib/rspec/core/formatters/base_text_formatter.rb +32 -253
- data/lib/rspec/core/formatters/console_codes.rb +65 -0
- data/lib/rspec/core/formatters/deprecation_formatter.rb +24 -15
- data/lib/rspec/core/formatters/documentation_formatter.rb +7 -10
- data/lib/rspec/core/formatters/helpers.rb +15 -9
- data/lib/rspec/core/formatters/html_formatter.rb +17 -16
- data/lib/rspec/core/formatters/html_printer.rb +1 -0
- data/lib/rspec/core/formatters/json_formatter.rb +18 -20
- data/lib/rspec/core/formatters/profile_formatter.rb +67 -0
- data/lib/rspec/core/formatters/progress_formatter.rb +6 -7
- data/lib/rspec/core/formatters/snippet_extractor.rb +8 -6
- data/lib/rspec/core/hooks.rb +131 -125
- data/lib/rspec/core/memoized_helpers.rb +31 -26
- data/lib/rspec/core/metadata.rb +277 -184
- data/lib/rspec/core/metadata_filter.rb +86 -0
- data/lib/rspec/core/minitest_assertions_adapter.rb +28 -0
- data/lib/rspec/core/mocking_adapters/flexmock.rb +1 -1
- data/lib/rspec/core/mocking_adapters/mocha.rb +1 -1
- data/lib/rspec/core/mocking_adapters/null.rb +1 -1
- data/lib/rspec/core/mocking_adapters/rr.rb +2 -1
- data/lib/rspec/core/mocking_adapters/rspec.rb +1 -1
- data/lib/rspec/core/notifications.rb +435 -24
- data/lib/rspec/core/option_parser.rb +16 -25
- data/lib/rspec/core/ordering.rb +3 -1
- data/lib/rspec/core/pending.rb +57 -33
- data/lib/rspec/core/project_initializer.rb +2 -0
- data/lib/rspec/core/project_initializer/spec_helper.rb +5 -4
- data/lib/rspec/core/rake_task.rb +45 -20
- data/lib/rspec/core/reporter.rb +50 -22
- data/lib/rspec/core/ruby_project.rb +1 -0
- data/lib/rspec/core/runner.rb +93 -39
- data/lib/rspec/core/shared_context.rb +7 -5
- data/lib/rspec/core/shared_example_group.rb +85 -77
- data/lib/rspec/core/test_unit_assertions_adapter.rb +30 -0
- data/lib/rspec/core/version.rb +3 -1
- data/lib/rspec/core/warnings.rb +35 -17
- data/lib/rspec/core/world.rb +57 -5
- metadata +56 -369
- metadata.gz.sig +3 -3
- data/features/README.md +0 -13
- data/features/Upgrade.md +0 -352
- data/features/command_line/README.md +0 -25
- data/features/command_line/dry_run.feature +0 -29
- data/features/command_line/example_name_option.feature +0 -97
- data/features/command_line/exit_status.feature +0 -82
- data/features/command_line/fail_fast.feature +0 -26
- data/features/command_line/format_option.feature +0 -75
- data/features/command_line/init.feature +0 -57
- data/features/command_line/line_number_appended_to_path.feature +0 -140
- data/features/command_line/line_number_option.feature +0 -58
- data/features/command_line/order.feature +0 -25
- data/features/command_line/pattern_option.feature +0 -49
- data/features/command_line/rake_task.feature +0 -122
- data/features/command_line/randomization.feature +0 -63
- data/features/command_line/require_option.feature +0 -43
- data/features/command_line/ruby.feature +0 -23
- 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 -39
- data/features/configuration/backtrace_exclusion_patterns.feature +0 -105
- 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/enable_global_dsl.feature +0 -54
- 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/overriding_global_ordering.feature +0 -93
- 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/example_groups/aliasing.feature +0 -48
- 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 -286
- data/features/expectation_framework_integration/configure_expectation_framework.feature +0 -102
- data/features/filtering/exclusion_filters.feature +0 -135
- data/features/filtering/if_and_unless.feature +0 -138
- data/features/filtering/inclusion_filters.feature +0 -101
- data/features/formatters/configurable_colors.feature +0 -31
- data/features/formatters/custom_formatter.feature +0 -68
- data/features/formatters/json_formatter.feature +0 -30
- data/features/formatters/regression_tests.feature +0 -95
- 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 -146
- data/features/hooks/around_hooks.feature +0 -344
- data/features/hooks/before_and_after_hooks.feature +0 -427
- data/features/hooks/filtering.feature +0 -232
- data/features/metadata/current_example.feature +0 -56
- data/features/metadata/described_class.feature +0 -17
- data/features/metadata/user_defined.feature +0 -100
- data/features/mock_framework_integration/use_any_framework.feature +0 -106
- data/features/mock_framework_integration/use_flexmock.feature +0 -94
- data/features/mock_framework_integration/use_mocha.feature +0 -95
- data/features/mock_framework_integration/use_rr.feature +0 -96
- data/features/mock_framework_integration/use_rspec.feature +0 -95
- data/features/pending_and_skipped_examples/README.md +0 -3
- data/features/pending_and_skipped_examples/pending_examples.feature +0 -118
- data/features/pending_and_skipped_examples/skipped_examples.feature +0 -106
- data/features/spec_files/arbitrary_file_suffix.feature +0 -13
- data/features/step_definitions/additional_cli_steps.rb +0 -83
- 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 -21
- data/features/support/require_expect_syntax_in_aruba_specs.rb +0 -16
- data/features/support/rubinius.rb +0 -6
- data/lib/rspec/core/command_line.rb +0 -35
- data/lib/rspec/core/drb_command_line.rb +0 -26
- data/lib/rspec/core/drb_options.rb +0 -87
- data/lib/rspec/core/formatters/legacy_formatter.rb +0 -227
- data/lib/rspec/core/shared_example_group/collection.rb +0 -27
- data/spec/command_line/order_spec.rb +0 -211
- data/spec/rspec/core/backtrace_formatter_spec.rb +0 -230
- data/spec/rspec/core/command_line_spec.rb +0 -112
- data/spec/rspec/core/command_line_spec_output.txt +0 -0
- data/spec/rspec/core/configuration_options_spec.rb +0 -409
- data/spec/rspec/core/configuration_spec.rb +0 -1479
- 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 -88
- data/spec/rspec/core/example_group_spec.rb +0 -1533
- data/spec/rspec/core/example_spec.rb +0 -642
- data/spec/rspec/core/filter_manager_spec.rb +0 -229
- data/spec/rspec/core/formatters/base_formatter_spec.rb +0 -64
- data/spec/rspec/core/formatters/base_text_formatter_spec.rb +0 -303
- data/spec/rspec/core/formatters/deprecation_formatter_spec.rb +0 -208
- data/spec/rspec/core/formatters/documentation_formatter_spec.rb +0 -75
- data/spec/rspec/core/formatters/helpers_spec.rb +0 -104
- data/spec/rspec/core/formatters/html_formatted-2.1.0.html +0 -392
- data/spec/rspec/core/formatters/html_formatted.html +0 -397
- data/spec/rspec/core/formatters/html_formatter_spec.rb +0 -122
- data/spec/rspec/core/formatters/json_formatter_spec.rb +0 -206
- data/spec/rspec/core/formatters/legacy_formatter_spec.rb +0 -137
- data/spec/rspec/core/formatters/progress_formatter_spec.rb +0 -43
- data/spec/rspec/core/formatters/snippet_extractor_spec.rb +0 -26
- data/spec/rspec/core/formatters_spec.rb +0 -120
- data/spec/rspec/core/hooks_filtering_spec.rb +0 -227
- data/spec/rspec/core/hooks_spec.rb +0 -294
- data/spec/rspec/core/memoized_helpers_spec.rb +0 -495
- data/spec/rspec/core/metadata_spec.rb +0 -491
- data/spec/rspec/core/option_parser_spec.rb +0 -262
- data/spec/rspec/core/ordering_spec.rb +0 -102
- data/spec/rspec/core/pending_example_spec.rb +0 -117
- data/spec/rspec/core/pending_spec.rb +0 -8
- data/spec/rspec/core/project_initializer_spec.rb +0 -73
- data/spec/rspec/core/rake_task_spec.rb +0 -146
- data/spec/rspec/core/random_spec.rb +0 -47
- data/spec/rspec/core/reporter_spec.rb +0 -155
- 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 -58
- 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 -151
- data/spec/rspec/core/shared_context_spec.rb +0 -102
- data/spec/rspec/core/shared_example_group/collection_spec.rb +0 -57
- data/spec/rspec/core/shared_example_group_spec.rb +0 -114
- data/spec/rspec/core/warnings_spec.rb +0 -29
- data/spec/rspec/core/world_spec.rb +0 -142
- data/spec/rspec/core_spec.rb +0 -91
- data/spec/spec_helper.rb +0 -160
- data/spec/support/config_options_helper.rb +0 -13
- data/spec/support/formatter_support.rb +0 -83
- data/spec/support/helper_methods.rb +0 -26
- data/spec/support/isolate_load_path_mutation.rb +0 -5
- data/spec/support/isolated_directory.rb +0 -10
- data/spec/support/isolated_home_directory.rb +0 -16
- data/spec/support/legacy_formatter_using_sub_classing_example.rb +0 -87
- data/spec/support/matchers.rb +0 -85
- data/spec/support/mathn_integration_support.rb +0 -12
- data/spec/support/old_style_formatter_example.rb +0 -69
- data/spec/support/shared_example_groups.rb +0 -13
- data/spec/support/spec_files.rb +0 -44
- data/spec/support/stderr_splitter.rb +0 -36
@@ -12,199 +12,287 @@ 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
26
|
extend Hooks
|
17
27
|
|
18
28
|
include MemoizedHelpers
|
29
|
+
extend MemoizedHelpers::ClassMethods
|
19
30
|
include Pending
|
20
|
-
extend
|
31
|
+
extend SharedExampleGroup
|
21
32
|
|
22
|
-
|
23
|
-
|
24
|
-
|
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
|
38
|
+
end
|
39
|
+
|
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)
|
25
46
|
end
|
26
47
|
|
27
48
|
# @private
|
28
|
-
|
29
|
-
|
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
|
30
52
|
end
|
31
53
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
define_method name do
|
37
|
-
metadata[:example_group][name]
|
38
|
-
end
|
39
|
-
end
|
54
|
+
# @private
|
55
|
+
def self.delegate_to_metadata(*names)
|
56
|
+
names.each do |name|
|
57
|
+
define_singleton_method(name) { metadata.fetch(name) }
|
40
58
|
end
|
59
|
+
end
|
41
60
|
|
42
|
-
|
43
|
-
description = metadata[:example_group][:description]
|
44
|
-
RSpec.configuration.format_docstrings_block.call(description)
|
45
|
-
end
|
61
|
+
delegate_to_metadata :described_class, :file_path, :location
|
46
62
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
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
|
51
68
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
pending_metadata = options[:pending] || metadata[:pending]
|
68
|
-
|
69
|
-
if pending_metadata
|
70
|
-
options, block = ExampleGroup.pending_metadata_and_block_for(
|
71
|
-
options.merge(:pending => pending_metadata),
|
72
|
-
block
|
73
|
-
)
|
74
|
-
end
|
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
|
81
|
+
end
|
82
|
+
|
83
|
+
# @!endgroup
|
75
84
|
|
76
|
-
|
77
|
-
|
85
|
+
# @!group Defining Examples
|
86
|
+
|
87
|
+
# @private
|
88
|
+
# @macro [attach] define_example_method
|
89
|
+
# @!scope class
|
90
|
+
# @param name [String]
|
91
|
+
# @param extra_options [Hash]
|
92
|
+
# @param implementation [Block]
|
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
|
107
|
+
def self.define_example_method(name, extra_options={})
|
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
|
+
)
|
78
123
|
end
|
124
|
+
|
125
|
+
examples << RSpec::Core::Example.new(self, desc, options, block)
|
126
|
+
examples.last
|
79
127
|
end
|
128
|
+
end
|
80
129
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
130
|
+
# Defines an example within a group.
|
131
|
+
define_example_method :example
|
132
|
+
# Defines an example within a group.
|
133
|
+
# This is the primary API to define a code example.
|
134
|
+
define_example_method :it
|
135
|
+
# Defines an example within a group.
|
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
|
143
|
+
define_example_method :specify
|
144
|
+
|
145
|
+
# Shortcut to define an example with `:focus => true`
|
146
|
+
# @see example
|
147
|
+
define_example_method :focus, :focus => true
|
148
|
+
# Shortcut to define an example with `:focus => true`
|
149
|
+
# @see example
|
150
|
+
define_example_method :fexample, :focus => true
|
151
|
+
# Shortcut to define an example with `:focus => true`
|
152
|
+
# @see example
|
153
|
+
define_example_method :fit, :focus => true
|
154
|
+
# Shortcut to define an example with `:focus => true`
|
155
|
+
# @see example
|
156
|
+
define_example_method :fspecify, :focus => true
|
157
|
+
# Shortcut to define an example with `:skip => 'Temporarily skipped with xexample'`
|
158
|
+
# @see example
|
159
|
+
define_example_method :xexample, :skip => 'Temporarily skipped with xexample'
|
160
|
+
# Shortcut to define an example with `:skip => 'Temporarily skipped with xit'`
|
161
|
+
# @see example
|
162
|
+
define_example_method :xit, :skip => 'Temporarily skipped with xit'
|
163
|
+
# Shortcut to define an example with `:skip => 'Temporarily skipped with xspecify'`
|
164
|
+
# @see example
|
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`
|
170
|
+
# @see example
|
171
|
+
define_example_method :pending, :pending => true
|
172
|
+
|
173
|
+
# @!endgroup
|
174
|
+
|
175
|
+
# @!group Defining Example Groups
|
88
176
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
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
|
195
|
+
#
|
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
|
93
216
|
|
94
|
-
|
95
|
-
|
217
|
+
thread_data[:in_example_group] = true
|
218
|
+
end
|
96
219
|
|
97
|
-
|
98
|
-
# @example
|
99
|
-
# example do
|
100
|
-
# end
|
101
|
-
#
|
102
|
-
# example "does something" do
|
103
|
-
# end
|
104
|
-
#
|
105
|
-
# example "does something", :with => 'additional metadata' do
|
106
|
-
# end
|
107
|
-
#
|
108
|
-
# example "does something" do |ex|
|
109
|
-
# # ex is the Example object that evals this block
|
110
|
-
# end
|
111
|
-
define_example_method :example
|
112
|
-
# Defines an example within a group.
|
113
|
-
# @example
|
114
|
-
define_example_method :it
|
115
|
-
# Defines an example within a group.
|
116
|
-
# This is here primarily for backward compatibility with early versions
|
117
|
-
# of RSpec which used `context` and `specify` instead of `describe` and
|
118
|
-
# `it`.
|
119
|
-
define_example_method :specify
|
120
|
-
|
121
|
-
# Shortcut to define an example with `:focus` => true
|
122
|
-
# @see example
|
123
|
-
define_example_method :focus, :focused => true, :focus => true
|
124
|
-
# Shortcut to define an example with `:focus` => true
|
125
|
-
# @see example
|
126
|
-
define_example_method :focused, :focused => true, :focus => true
|
127
|
-
# Shortcut to define an example with `:focus` => true
|
128
|
-
# @see example
|
129
|
-
define_example_method :fit, :focused => true, :focus => true
|
130
|
-
|
131
|
-
# Shortcut to define an example with :skip => 'Temporarily skipped with xexample'
|
132
|
-
# @see example
|
133
|
-
define_example_method :xexample, :skip => 'Temporarily skipped with xexample'
|
134
|
-
# Shortcut to define an example with :skip => 'Temporarily skipped with xit'
|
135
|
-
# @see example
|
136
|
-
define_example_method :xit, :skip => 'Temporarily skipped with xit'
|
137
|
-
# Shortcut to define an example with :skip => 'Temporarily skipped with xspecify'
|
138
|
-
# @see example
|
139
|
-
define_example_method :xspecify, :skip => 'Temporarily skipped with xspecify'
|
140
|
-
# Shortcut to define an example with :skip => true
|
141
|
-
# @see example
|
142
|
-
define_example_method :skip, :skip => true
|
143
|
-
# Shortcut to define an example with :pending => true
|
144
|
-
# @see example
|
145
|
-
define_example_method :pending, :pending => true
|
146
|
-
|
147
|
-
# Works like `alias_method :name, :example` with the added benefit of
|
148
|
-
# assigning default metadata to the generated example.
|
149
|
-
#
|
150
|
-
# @note Use with caution. This extends the language used in your
|
151
|
-
# specs, but does not add any additional documentation. We use this
|
152
|
-
# in rspec to define methods like `focus` and `xit`, but we also add
|
153
|
-
# docs for those methods.
|
154
|
-
def alias_example_to name, extra={}
|
155
|
-
(class << self; self; end).define_example_method name, extra
|
156
|
-
end
|
220
|
+
begin
|
157
221
|
|
158
|
-
|
159
|
-
# @macro [attach] alias_example_group_to
|
160
|
-
# @scope class
|
161
|
-
# @param [String] docstring The example group doc string
|
162
|
-
# @param [Hash] metadata Additional metadata to attach to the example group
|
163
|
-
# @yield The example group definition
|
164
|
-
def alias_example_group_to(name, metadata={})
|
165
|
-
(class << self; self; end).__send__(:define_method, name) do |*args, &block|
|
222
|
+
description = args.shift
|
166
223
|
combined_metadata = metadata.dup
|
167
224
|
combined_metadata.merge!(args.pop) if args.last.is_a? Hash
|
168
225
|
args << combined_metadata
|
169
|
-
example_group(*args, &block)
|
170
|
-
end
|
171
|
-
|
172
|
-
RSpec::Core::DSL.expose_example_group_alias(name)
|
173
|
-
end
|
174
226
|
|
175
|
-
|
176
|
-
|
177
|
-
#
|
178
|
-
# @see SharedExampleGroup
|
179
|
-
def self.define_nested_shared_group_method(new_name, report_label="it should behave like")
|
180
|
-
define_method(new_name) do |name, *args, &customization_block|
|
181
|
-
group = example_group("#{report_label} #{name}") do
|
182
|
-
find_and_eval_shared("examples", name, *args, &customization_block)
|
227
|
+
subclass(self, description, args, &example_group_block).tap do |child|
|
228
|
+
children << child
|
183
229
|
end
|
184
|
-
|
185
|
-
|
230
|
+
|
231
|
+
ensure
|
232
|
+
thread_data.delete(:in_example_group) if top_level
|
186
233
|
end
|
187
234
|
end
|
188
235
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
236
|
+
RSpec::Core::DSL.expose_example_group_alias(name)
|
237
|
+
end
|
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
|
+
|
271
|
+
# @private
|
272
|
+
# @macro [attach] define_nested_shared_group_method
|
273
|
+
# @!scope class
|
274
|
+
#
|
275
|
+
# @see SharedExampleGroup
|
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)
|
283
|
+
end
|
284
|
+
group.metadata[:shared_group_name] = name
|
285
|
+
group
|
205
286
|
end
|
206
287
|
end
|
207
288
|
|
289
|
+
# Generates a nested example group and includes the shared content
|
290
|
+
# mapped to `name` in the nested group.
|
291
|
+
define_nested_shared_group_method :it_behaves_like, "behaves like"
|
292
|
+
# Generates a nested example group and includes the shared content
|
293
|
+
# mapped to `name` in the nested group.
|
294
|
+
define_nested_shared_group_method :it_should_behave_like
|
295
|
+
|
208
296
|
# Includes shared content mapped to `name` directly in the group in which
|
209
297
|
# it is declared, as opposed to `it_behaves_like`, which creates a nested
|
210
298
|
# group. If given a block, that block is also eval'd in the current context.
|
@@ -225,110 +313,68 @@ module RSpec
|
|
225
313
|
|
226
314
|
# @private
|
227
315
|
def self.find_and_eval_shared(label, name, *args, &customization_block)
|
228
|
-
|
229
|
-
|
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
|
230
319
|
|
231
320
|
module_exec(*args, &shared_block)
|
232
|
-
|
321
|
+
module_exec(&customization_block) if customization_block
|
233
322
|
end
|
234
323
|
|
235
|
-
#
|
236
|
-
def self.examples
|
237
|
-
@examples ||= []
|
238
|
-
end
|
324
|
+
# @!endgroup
|
239
325
|
|
240
326
|
# @private
|
241
|
-
def self.
|
242
|
-
|
243
|
-
|
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
|
244
332
|
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
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)
|
249
338
|
|
250
|
-
|
251
|
-
# @see Metadata
|
252
|
-
def self.metadata
|
253
|
-
@metadata if defined?(@metadata)
|
339
|
+
subclass
|
254
340
|
end
|
255
341
|
|
256
342
|
# @private
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
#
|
267
|
-
# describe "something" do # << This describe method is defined in
|
268
|
-
# # << RSpec::Core::DSL, included in the
|
269
|
-
# # << global namespace (optional)
|
270
|
-
# before do
|
271
|
-
# do_something_before
|
272
|
-
# end
|
273
|
-
#
|
274
|
-
# let(:thing) { Thing.new }
|
275
|
-
#
|
276
|
-
# describe "attribute (of something)" do
|
277
|
-
# # examples in the group get the before hook
|
278
|
-
# # declared above, and can access `thing`
|
279
|
-
# end
|
280
|
-
# end
|
281
|
-
#
|
282
|
-
# @see DSL#describe
|
283
|
-
def self.example_group(*args, &example_group_block)
|
284
|
-
args << {} unless args.last.is_a?(Hash)
|
285
|
-
args.last.update(:example_group_block => example_group_block)
|
286
|
-
|
287
|
-
child = subclass(self, args, &example_group_block)
|
288
|
-
children << child
|
289
|
-
child
|
290
|
-
end
|
291
|
-
|
292
|
-
# An alias of `example_group`. Generally used when grouping
|
293
|
-
# examples by a thing you are describing (e.g. an object, class or method).
|
294
|
-
# @see example_group
|
295
|
-
alias_example_group_to :describe
|
296
|
-
|
297
|
-
# An alias of `example_group`. Generally used when grouping examples
|
298
|
-
# contextually.
|
299
|
-
# @see example_group
|
300
|
-
alias_example_group_to :context
|
301
|
-
|
302
|
-
# Shortcut to temporarily make an example group pending.
|
303
|
-
# @see example_group
|
304
|
-
alias_example_group_to :xdescribe, :skip => "Temporarily skipped with xdescribe"
|
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
|
305
352
|
|
306
|
-
|
307
|
-
|
308
|
-
|
353
|
+
description = args.shift
|
354
|
+
user_metadata = Metadata.build_hash_from(args)
|
355
|
+
args.unshift(description)
|
309
356
|
|
310
|
-
|
311
|
-
|
312
|
-
|
357
|
+
@metadata = Metadata::ExampleGroupHash.create(
|
358
|
+
superclass_metadata || {}, user_metadata, *args, &example_group_block
|
359
|
+
)
|
313
360
|
|
314
|
-
|
315
|
-
|
316
|
-
|
361
|
+
hooks.register_globals(self, RSpec.configuration.hooks)
|
362
|
+
RSpec.world.configure_group(self)
|
363
|
+
end
|
317
364
|
|
318
365
|
# @private
|
319
|
-
def self.
|
320
|
-
|
321
|
-
|
322
|
-
ExampleGroups.assign_const(subclass)
|
323
|
-
subclass.module_eval(&example_group_block) if example_group_block
|
366
|
+
def self.examples
|
367
|
+
@examples ||= []
|
368
|
+
end
|
324
369
|
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
MemoizedHelpers.define_helpers_on(subclass)
|
370
|
+
# @private
|
371
|
+
def self.filtered_examples
|
372
|
+
RSpec.world.filtered_examples[self]
|
373
|
+
end
|
330
374
|
|
331
|
-
|
375
|
+
# @private
|
376
|
+
def self.descendant_filtered_examples
|
377
|
+
@descendant_filtered_examples ||= filtered_examples + children.inject([]){|l,c| l + c.descendant_filtered_examples}
|
332
378
|
end
|
333
379
|
|
334
380
|
# @private
|
@@ -361,84 +407,64 @@ module RSpec
|
|
361
407
|
end
|
362
408
|
|
363
409
|
# @private
|
364
|
-
def self.
|
365
|
-
|
366
|
-
# SystemStackError if you include a module in a superclass after
|
367
|
-
# including it in a subclass: https://gist.github.com/845896
|
368
|
-
# To prevent this, we must include any modules in RSpec::Core::ExampleGroup
|
369
|
-
# before users create example groups and have a chance to include
|
370
|
-
# the same module in a subclass of RSpec::Core::ExampleGroup.
|
371
|
-
# So we need to configure example groups here.
|
372
|
-
ensure_example_groups_are_configured
|
373
|
-
|
374
|
-
symbol_description = args.shift if args.first.is_a?(Symbol)
|
375
|
-
args << Metadata.build_hash_from(args)
|
376
|
-
args.unshift(symbol_description) if symbol_description
|
377
|
-
@metadata = RSpec::Core::Metadata.new(superclass_metadata).process(*args)
|
378
|
-
@order = nil
|
379
|
-
hooks.register_globals(self, RSpec.configuration.hooks)
|
380
|
-
world.configure_group(self)
|
381
|
-
end
|
382
|
-
|
383
|
-
# @private
|
384
|
-
def self.before_all_ivars
|
385
|
-
@before_all_ivars ||= {}
|
410
|
+
def self.before_context_ivars
|
411
|
+
@before_context_ivars ||= {}
|
386
412
|
end
|
387
413
|
|
388
414
|
# @private
|
389
|
-
def self.
|
415
|
+
def self.store_before_context_ivars(example_group_instance)
|
390
416
|
return if example_group_instance.instance_variables.empty?
|
391
417
|
|
392
418
|
example_group_instance.instance_variables.each { |ivar|
|
393
|
-
|
419
|
+
before_context_ivars[ivar] = example_group_instance.instance_variable_get(ivar)
|
394
420
|
}
|
395
421
|
end
|
396
422
|
|
397
423
|
# @private
|
398
|
-
def self.
|
424
|
+
def self.run_before_context_hooks(example_group_instance)
|
399
425
|
return if descendant_filtered_examples.empty?
|
400
426
|
begin
|
401
|
-
set_ivars(example_group_instance, superclass.
|
427
|
+
set_ivars(example_group_instance, superclass.before_context_ivars)
|
402
428
|
|
403
|
-
|
404
|
-
hooks.run(:before, :
|
429
|
+
ContextHookMemoizedHash::Before.isolate_for_context_hook(example_group_instance) do
|
430
|
+
hooks.run(:before, :context, example_group_instance)
|
405
431
|
end
|
406
432
|
ensure
|
407
|
-
|
433
|
+
store_before_context_ivars(example_group_instance)
|
408
434
|
end
|
409
435
|
end
|
410
436
|
|
411
437
|
# @private
|
412
|
-
def self.
|
438
|
+
def self.run_after_context_hooks(example_group_instance)
|
413
439
|
return if descendant_filtered_examples.empty?
|
414
|
-
set_ivars(example_group_instance,
|
440
|
+
set_ivars(example_group_instance, before_context_ivars)
|
415
441
|
|
416
|
-
|
417
|
-
hooks.run(:after, :
|
442
|
+
ContextHookMemoizedHash::After.isolate_for_context_hook(example_group_instance) do
|
443
|
+
hooks.run(:after, :context, example_group_instance)
|
418
444
|
end
|
419
445
|
end
|
420
446
|
|
421
447
|
# Runs all the examples in this group
|
422
448
|
def self.run(reporter)
|
423
|
-
if RSpec.wants_to_quit
|
424
|
-
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?
|
425
451
|
return
|
426
452
|
end
|
427
453
|
reporter.example_group_started(self)
|
428
454
|
|
429
455
|
begin
|
430
|
-
|
456
|
+
run_before_context_hooks(new)
|
431
457
|
result_for_this_group = run_examples(reporter)
|
432
458
|
results_for_descendants = ordering_strategy.order(children).map { |child| child.run(reporter) }.all?
|
433
459
|
result_for_this_group && results_for_descendants
|
434
460
|
rescue Pending::SkipDeclaredInExample => ex
|
435
461
|
for_filtered_examples(reporter) {|example| example.skip_with_exception(reporter, ex) }
|
436
462
|
rescue Exception => ex
|
437
|
-
RSpec.wants_to_quit = true if fail_fast?
|
463
|
+
RSpec.world.wants_to_quit = true if fail_fast?
|
438
464
|
for_filtered_examples(reporter) {|example| example.fail_with_exception(reporter, ex) }
|
439
465
|
ensure
|
440
|
-
|
441
|
-
|
466
|
+
run_after_context_hooks(new)
|
467
|
+
before_context_ivars.clear
|
442
468
|
reporter.example_group_finished(self)
|
443
469
|
end
|
444
470
|
end
|
@@ -452,7 +478,7 @@ module RSpec
|
|
452
478
|
warn <<-WARNING.gsub(/^ +\|/, '')
|
453
479
|
|WARNING: Ignoring unknown ordering specified using `:order => #{order.inspect}` metadata.
|
454
480
|
| Falling back to configured global ordering.
|
455
|
-
| Unrecognized ordering specified at: #{
|
481
|
+
| Unrecognized ordering specified at: #{location}
|
456
482
|
WARNING
|
457
483
|
|
458
484
|
registry.fetch(:global)
|
@@ -462,11 +488,11 @@ module RSpec
|
|
462
488
|
# @private
|
463
489
|
def self.run_examples(reporter)
|
464
490
|
ordering_strategy.order(filtered_examples).map do |example|
|
465
|
-
next if RSpec.wants_to_quit
|
491
|
+
next if RSpec.world.wants_to_quit
|
466
492
|
instance = new
|
467
|
-
set_ivars(instance,
|
493
|
+
set_ivars(instance, before_context_ivars)
|
468
494
|
succeeded = example.run(instance, reporter)
|
469
|
-
RSpec.wants_to_quit = true if fail_fast? && !succeeded
|
495
|
+
RSpec.world.wants_to_quit = true if fail_fast? && !succeeded
|
470
496
|
succeeded
|
471
497
|
end.all?
|
472
498
|
end
|
@@ -490,17 +516,17 @@ module RSpec
|
|
490
516
|
|
491
517
|
# @private
|
492
518
|
def self.any_apply?(filters)
|
493
|
-
|
519
|
+
MetadataFilter.any_apply?(filters, metadata)
|
494
520
|
end
|
495
521
|
|
496
522
|
# @private
|
497
523
|
def self.all_apply?(filters)
|
498
|
-
|
524
|
+
MetadataFilter.all_apply?(filters, metadata)
|
499
525
|
end
|
500
526
|
|
501
527
|
# @private
|
502
528
|
def self.declaration_line_numbers
|
503
|
-
@declaration_line_numbers ||= [metadata[:
|
529
|
+
@declaration_line_numbers ||= [metadata[:line_number]] +
|
504
530
|
examples.collect {|e| e.metadata[:line_number]} +
|
505
531
|
children.inject([]) {|l,c| l + c.declaration_line_numbers}
|
506
532
|
end
|
@@ -515,37 +541,39 @@ module RSpec
|
|
515
541
|
ivars.each {|name, value| instance.instance_variable_set(name, value)}
|
516
542
|
end
|
517
543
|
|
518
|
-
# Returns the class or module passed to the `describe` method (or alias).
|
519
|
-
# Returns nil if the subject is not a class or module.
|
520
|
-
# @example
|
521
|
-
# describe Thing do
|
522
|
-
# it "does something" do
|
523
|
-
# described_class == Thing
|
524
|
-
# end
|
525
|
-
# end
|
526
|
-
#
|
527
|
-
#
|
528
|
-
def described_class
|
529
|
-
self.class.described_class
|
530
|
-
end
|
531
|
-
|
532
544
|
# @private
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
if RSpec.current_example
|
540
|
-
RSpec.current_example.set_exception(e, context)
|
541
|
-
else
|
542
|
-
raise
|
543
|
-
end
|
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
|
544
551
|
end
|
552
|
+
|
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)
|
556
|
+
|
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) }
|
561
|
+
|
562
|
+
return options, callback
|
563
|
+
end
|
564
|
+
end
|
565
|
+
|
566
|
+
# @private
|
567
|
+
# Unnamed example group used by `SuiteHookContext`.
|
568
|
+
class AnonymousExampleGroup < ExampleGroup
|
569
|
+
def self.metadata
|
570
|
+
{}
|
545
571
|
end
|
546
572
|
end
|
547
573
|
end
|
548
574
|
|
575
|
+
# @private
|
576
|
+
#
|
549
577
|
# Namespace for the example group subclasses generated by top-level `describe`.
|
550
578
|
module ExampleGroups
|
551
579
|
def self.assign_const(group)
|