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
data/lib/rspec/core/example.rb
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
module RSpec
|
|
2
2
|
module Core
|
|
3
3
|
# Wrapper for an instance of a subclass of {ExampleGroup}. An instance of
|
|
4
|
-
# `Example` is returned by
|
|
5
|
-
#
|
|
6
|
-
#
|
|
4
|
+
# `RSpec::Core::Example` is returned by example definition methods
|
|
5
|
+
# such as {ExampleGroup.it it} and is yielded to the {ExampleGroup.it it},
|
|
6
|
+
# {Hooks#before before}, {Hooks#after after}, {Hooks#around around},
|
|
7
|
+
# {MemoizedHelpers::ClassMethods#let let} and
|
|
8
|
+
# {MemoizedHelpers::ClassMethods#subject subject} blocks.
|
|
9
|
+
#
|
|
10
|
+
# This allows us to provide rich metadata about each individual
|
|
11
|
+
# example without adding tons of methods directly to the ExampleGroup
|
|
12
|
+
# that users may inadvertantly redefine.
|
|
7
13
|
#
|
|
8
14
|
# Useful for configuring logging and/or taking some action based
|
|
9
15
|
# on the state of an example's metadata.
|
|
@@ -11,17 +17,17 @@ module RSpec
|
|
|
11
17
|
# @example
|
|
12
18
|
#
|
|
13
19
|
# RSpec.configure do |config|
|
|
14
|
-
# config.before do
|
|
20
|
+
# config.before do |example|
|
|
15
21
|
# log example.description
|
|
16
22
|
# end
|
|
17
23
|
#
|
|
18
|
-
# config.after do
|
|
24
|
+
# config.after do |example|
|
|
19
25
|
# log example.description
|
|
20
26
|
# end
|
|
21
27
|
#
|
|
22
|
-
# config.around do |
|
|
28
|
+
# config.around do |example|
|
|
23
29
|
# log example.description
|
|
24
|
-
#
|
|
30
|
+
# example.run
|
|
25
31
|
# end
|
|
26
32
|
# end
|
|
27
33
|
#
|
|
@@ -33,15 +39,33 @@ module RSpec
|
|
|
33
39
|
# end
|
|
34
40
|
#
|
|
35
41
|
# @see ExampleGroup
|
|
42
|
+
# @note Example blocks are evaluated in the context of an instance
|
|
43
|
+
# of an `ExampleGroup`, not in the context of an instance of `Example`.
|
|
36
44
|
class Example
|
|
37
45
|
# @private
|
|
38
46
|
#
|
|
39
47
|
# Used to define methods that delegate to this example's metadata
|
|
40
|
-
def self.delegate_to_metadata(
|
|
41
|
-
|
|
48
|
+
def self.delegate_to_metadata(key)
|
|
49
|
+
define_method(key) { @metadata[key] }
|
|
42
50
|
end
|
|
43
51
|
|
|
44
|
-
|
|
52
|
+
# @return [ExecutionResult] represents the result of running this example.
|
|
53
|
+
delegate_to_metadata :execution_result
|
|
54
|
+
# @return [String] the relative path to the file where this example was defined.
|
|
55
|
+
delegate_to_metadata :file_path
|
|
56
|
+
# @return [String] the full description (including the docstrings of
|
|
57
|
+
# all parent example groups).
|
|
58
|
+
delegate_to_metadata :full_description
|
|
59
|
+
# @return [String] the exact source location of this example in a form
|
|
60
|
+
# like `./path/to/spec.rb:17`
|
|
61
|
+
delegate_to_metadata :location
|
|
62
|
+
# @return [Boolean] flag that indicates that the example is not expected to pass.
|
|
63
|
+
# It will be run and will either have a pending result (if a failure occurs)
|
|
64
|
+
# or a failed result (if no failure occurs).
|
|
65
|
+
delegate_to_metadata :pending
|
|
66
|
+
# @return [Boolean] flag that will cause the example to not run.
|
|
67
|
+
# The {ExecutionResult} status will be `:pending`.
|
|
68
|
+
delegate_to_metadata :skip
|
|
45
69
|
|
|
46
70
|
# Returns the string submitted to `example` or its aliases (e.g.
|
|
47
71
|
# `specify`, `it`, etc). If no string is submitted (e.g. `it { is_expected.to
|
|
@@ -49,7 +73,9 @@ module RSpec
|
|
|
49
73
|
# there is one, otherwise returns a message including the location of the
|
|
50
74
|
# example.
|
|
51
75
|
def description
|
|
52
|
-
description = metadata[:description].to_s.empty? ?
|
|
76
|
+
description = metadata[:description].to_s.empty? ?
|
|
77
|
+
"example at #{location}" :
|
|
78
|
+
metadata[:description]
|
|
53
79
|
RSpec.configuration.format_docstrings_block.call(description)
|
|
54
80
|
end
|
|
55
81
|
|
|
@@ -71,23 +97,26 @@ module RSpec
|
|
|
71
97
|
# running this example.
|
|
72
98
|
attr_reader :example_group_instance
|
|
73
99
|
|
|
100
|
+
# @attr
|
|
101
|
+
# @private
|
|
102
|
+
attr_accessor :clock
|
|
103
|
+
|
|
74
104
|
# Creates a new instance of Example.
|
|
75
|
-
# @param example_group_class the subclass of ExampleGroup in which this Example is declared
|
|
76
|
-
# @param description the String passed to the `it` method (or alias)
|
|
77
|
-
# @param
|
|
78
|
-
# @param example_block the block of code that represents the example
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
@
|
|
82
|
-
@
|
|
83
|
-
|
|
84
|
-
|
|
105
|
+
# @param example_group_class [Class] the subclass of ExampleGroup in which this Example is declared
|
|
106
|
+
# @param description [String] the String passed to the `it` method (or alias)
|
|
107
|
+
# @param user_metadata [Hash] additional args passed to `it` to be used as metadata
|
|
108
|
+
# @param example_block [Proc] the block of code that represents the example
|
|
109
|
+
# @api private
|
|
110
|
+
def initialize(example_group_class, description, user_metadata, example_block=nil)
|
|
111
|
+
@example_group_class = example_group_class
|
|
112
|
+
@example_block = example_block
|
|
113
|
+
|
|
114
|
+
@metadata = Metadata::ExampleHash.create(
|
|
115
|
+
@example_group_class.metadata, user_metadata, description, example_block
|
|
116
|
+
)
|
|
85
117
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
RSpec.deprecate("`RSpec::Core::Example#options`",
|
|
89
|
-
:replacement => "`RSpec::Core::Example#metadata`")
|
|
90
|
-
@options
|
|
118
|
+
@example_group_instance = @exception = nil
|
|
119
|
+
@clock = RSpec::Core::Time
|
|
91
120
|
end
|
|
92
121
|
|
|
93
122
|
# Returns the example group class that provides the context for running
|
|
@@ -97,9 +126,10 @@ module RSpec
|
|
|
97
126
|
end
|
|
98
127
|
|
|
99
128
|
alias_method :pending?, :pending
|
|
129
|
+
alias_method :skipped?, :skip
|
|
100
130
|
|
|
101
131
|
# @api private
|
|
102
|
-
#
|
|
132
|
+
# instance_execs the block passed to the constructor in the context of
|
|
103
133
|
# the instance of {ExampleGroup}.
|
|
104
134
|
# @param example_group_instance the instance of an ExampleGroup subclass
|
|
105
135
|
def run(example_group_instance, reporter)
|
|
@@ -109,17 +139,28 @@ module RSpec
|
|
|
109
139
|
start(reporter)
|
|
110
140
|
|
|
111
141
|
begin
|
|
112
|
-
|
|
113
|
-
|
|
142
|
+
if skipped?
|
|
143
|
+
Pending.mark_pending! self, skip
|
|
144
|
+
elsif !RSpec.configuration.dry_run?
|
|
145
|
+
with_around_example_hooks do
|
|
114
146
|
begin
|
|
115
|
-
|
|
116
|
-
@example_group_instance.
|
|
117
|
-
|
|
118
|
-
|
|
147
|
+
run_before_example
|
|
148
|
+
@example_group_instance.instance_exec(self, &@example_block)
|
|
149
|
+
|
|
150
|
+
if pending?
|
|
151
|
+
Pending.mark_fixed! self
|
|
152
|
+
|
|
153
|
+
raise Pending::PendingExampleFixedError,
|
|
154
|
+
'Expected example to fail since it is pending, but it passed.',
|
|
155
|
+
[location]
|
|
156
|
+
end
|
|
157
|
+
rescue Pending::SkipDeclaredInExample
|
|
158
|
+
# no-op, required metadata has already been set by the `skip`
|
|
159
|
+
# method.
|
|
119
160
|
rescue Exception => e
|
|
120
161
|
set_exception(e)
|
|
121
162
|
ensure
|
|
122
|
-
|
|
163
|
+
run_after_example
|
|
123
164
|
end
|
|
124
165
|
end
|
|
125
166
|
end
|
|
@@ -130,12 +171,6 @@ module RSpec
|
|
|
130
171
|
@example_group_instance.instance_variable_set(ivar, nil)
|
|
131
172
|
end
|
|
132
173
|
@example_group_instance = nil
|
|
133
|
-
|
|
134
|
-
begin
|
|
135
|
-
assign_generated_description
|
|
136
|
-
rescue Exception => e
|
|
137
|
-
set_exception(e, "while assigning the example description")
|
|
138
|
-
end
|
|
139
174
|
end
|
|
140
175
|
|
|
141
176
|
finish(reporter)
|
|
@@ -143,66 +178,61 @@ module RSpec
|
|
|
143
178
|
RSpec.current_example = nil
|
|
144
179
|
end
|
|
145
180
|
|
|
146
|
-
#
|
|
147
|
-
#
|
|
148
|
-
#
|
|
149
|
-
# `
|
|
150
|
-
def self.procsy(metadata, &proc)
|
|
151
|
-
proc.extend(Procsy).with(metadata)
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
# Used to extend a `Proc` with behavior that makes it look something like
|
|
155
|
-
# an {Example} in an {Hooks#around around} hook.
|
|
156
|
-
#
|
|
157
|
-
# @note Procsy, itself, is not a public API, but we're documenting it
|
|
158
|
-
# here to document how to interact with the object yielded to an
|
|
159
|
-
# `around` hook.
|
|
181
|
+
# Wraps both a `Proc` and an {Example} for use in {Hooks#around
|
|
182
|
+
# around} hooks. In around hooks we need to yield this special
|
|
183
|
+
# kind of object (rather than the raw {Example}) because when
|
|
184
|
+
# there are multiple `around` hooks we have to wrap them recursively.
|
|
160
185
|
#
|
|
161
186
|
# @example
|
|
162
187
|
#
|
|
163
188
|
# RSpec.configure do |c|
|
|
164
|
-
# c.around do |ex| #
|
|
189
|
+
# c.around do |ex| # Procsy which wraps the example
|
|
165
190
|
# if ex.metadata[:key] == :some_value && some_global_condition
|
|
166
191
|
# raise "some message"
|
|
167
192
|
# end
|
|
168
193
|
# ex.run # run delegates to ex.call
|
|
169
194
|
# end
|
|
170
195
|
# end
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
196
|
+
#
|
|
197
|
+
# @note This class also exposes the instance methods of {Example},
|
|
198
|
+
# proxying them through to the wrapped {Example} instance.
|
|
199
|
+
class Procsy
|
|
200
|
+
# The {Example} instance.
|
|
201
|
+
attr_reader :example
|
|
202
|
+
|
|
203
|
+
Example.public_instance_methods(false).each do |name|
|
|
204
|
+
define_method(name) { |*a, &b| @example.__send__(name, *a, &b) }
|
|
205
|
+
end
|
|
174
206
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
# Adds a `run` method to the extended Proc, allowing it to be invoked
|
|
178
|
-
# in an [around](../Hooks#around-instance_method) hook using either
|
|
179
|
-
# `run` or `call`.
|
|
180
|
-
def self.extended(proc)
|
|
181
|
-
# @api public
|
|
182
|
-
# Foo bar
|
|
183
|
-
def proc.run; call; end
|
|
207
|
+
Proc.public_instance_methods(false).each do |name|
|
|
208
|
+
define_method(name) { |*a, &b| @proc.__send__(name, *a, &b) }
|
|
184
209
|
end
|
|
210
|
+
alias run call
|
|
185
211
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
@
|
|
189
|
-
|
|
212
|
+
def initialize(example, &block)
|
|
213
|
+
@example = example
|
|
214
|
+
@proc = block
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
# @private
|
|
218
|
+
def wrap(&block)
|
|
219
|
+
self.class.new(example, &block)
|
|
190
220
|
end
|
|
191
221
|
end
|
|
192
222
|
|
|
193
223
|
# @private
|
|
194
224
|
def any_apply?(filters)
|
|
195
|
-
|
|
225
|
+
MetadataFilter.any_apply?(filters, metadata)
|
|
196
226
|
end
|
|
197
227
|
|
|
198
228
|
# @private
|
|
199
229
|
def all_apply?(filters)
|
|
200
|
-
|
|
230
|
+
MetadataFilter.all_apply?(filters, metadata) || @example_group_class.all_apply?(filters)
|
|
201
231
|
end
|
|
202
232
|
|
|
203
233
|
# @private
|
|
204
|
-
def
|
|
205
|
-
@
|
|
234
|
+
def around_example_hooks
|
|
235
|
+
@around_example_hooks ||= example_group.hooks.around_example_hooks_for(self)
|
|
206
236
|
end
|
|
207
237
|
|
|
208
238
|
# @private
|
|
@@ -210,26 +240,30 @@ module RSpec
|
|
|
210
240
|
# Used internally to set an exception in an after hook, which
|
|
211
241
|
# captures the exception but doesn't raise it.
|
|
212
242
|
def set_exception(exception, context=nil)
|
|
213
|
-
if
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
243
|
+
if pending? && !(Pending::PendingExampleFixedError === exception)
|
|
244
|
+
execution_result.pending_exception = exception
|
|
245
|
+
else
|
|
246
|
+
if @exception
|
|
247
|
+
# An error has already been set; we don't want to override it,
|
|
248
|
+
# but we also don't want silence the error, so let's print it.
|
|
249
|
+
msg = <<-EOS
|
|
217
250
|
|
|
218
|
-
An error occurred #{context}
|
|
219
|
-
|
|
220
|
-
|
|
251
|
+
An error occurred #{context}
|
|
252
|
+
#{exception.class}: #{exception.message}
|
|
253
|
+
occurred at #{exception.backtrace.first}
|
|
221
254
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
255
|
+
EOS
|
|
256
|
+
RSpec.configuration.reporter.message(msg)
|
|
257
|
+
end
|
|
225
258
|
|
|
226
|
-
|
|
259
|
+
@exception ||= exception
|
|
260
|
+
end
|
|
227
261
|
end
|
|
228
262
|
|
|
229
263
|
# @private
|
|
230
264
|
#
|
|
231
265
|
# Used internally to set an exception and fail without actually executing
|
|
232
|
-
# the example when an exception is raised in before(:
|
|
266
|
+
# the example when an exception is raised in before(:context).
|
|
233
267
|
def fail_with_exception(reporter, exception)
|
|
234
268
|
start(reporter)
|
|
235
269
|
set_exception(exception)
|
|
@@ -237,87 +271,201 @@ An error occurred #{context}
|
|
|
237
271
|
end
|
|
238
272
|
|
|
239
273
|
# @private
|
|
240
|
-
|
|
241
|
-
|
|
274
|
+
#
|
|
275
|
+
# Used internally to skip without actually executing the example when
|
|
276
|
+
# skip is used in before(:context)
|
|
277
|
+
def skip_with_exception(reporter, exception)
|
|
278
|
+
start(reporter)
|
|
279
|
+
Pending.mark_skipped! self, exception.argument
|
|
280
|
+
finish(reporter)
|
|
242
281
|
end
|
|
243
282
|
|
|
244
283
|
# @private
|
|
245
|
-
def
|
|
246
|
-
@example_group_instance.
|
|
284
|
+
def instance_exec_with_rescue(context, &block)
|
|
285
|
+
@example_group_instance.instance_exec(self, &block)
|
|
286
|
+
rescue Exception => e
|
|
287
|
+
set_exception(e, context)
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
# @private
|
|
291
|
+
def instance_exec(*args, &block)
|
|
292
|
+
@example_group_instance.instance_exec(*args, &block)
|
|
247
293
|
end
|
|
248
294
|
|
|
249
295
|
private
|
|
250
296
|
|
|
251
|
-
def
|
|
252
|
-
if
|
|
297
|
+
def with_around_example_hooks(&block)
|
|
298
|
+
if around_example_hooks.empty?
|
|
253
299
|
yield
|
|
254
300
|
else
|
|
255
|
-
@example_group_class.
|
|
301
|
+
@example_group_class.hooks.run(:around, :example, self, Procsy.new(self, &block))
|
|
256
302
|
end
|
|
257
303
|
rescue Exception => e
|
|
258
|
-
set_exception(e, "in an around(:
|
|
304
|
+
set_exception(e, "in an `around(:example)` hook")
|
|
259
305
|
end
|
|
260
306
|
|
|
261
307
|
def start(reporter)
|
|
262
308
|
reporter.example_started(self)
|
|
263
|
-
|
|
309
|
+
execution_result.started_at = clock.now
|
|
264
310
|
end
|
|
265
311
|
|
|
266
312
|
def finish(reporter)
|
|
313
|
+
pending_message = execution_result.pending_message
|
|
314
|
+
|
|
267
315
|
if @exception
|
|
268
|
-
record_finished
|
|
316
|
+
record_finished :failed
|
|
317
|
+
execution_result.exception = @exception
|
|
269
318
|
reporter.example_failed self
|
|
270
319
|
false
|
|
271
|
-
elsif
|
|
272
|
-
record_finished
|
|
273
|
-
|
|
274
|
-
true
|
|
275
|
-
elsif pending
|
|
276
|
-
record_finished 'pending', :pending_message => String === pending ? pending : Pending::NO_REASON_GIVEN
|
|
320
|
+
elsif pending_message
|
|
321
|
+
record_finished :pending
|
|
322
|
+
execution_result.pending_message = pending_message
|
|
277
323
|
reporter.example_pending self
|
|
278
324
|
true
|
|
279
325
|
else
|
|
280
|
-
record_finished
|
|
326
|
+
record_finished :passed
|
|
281
327
|
reporter.example_passed self
|
|
282
328
|
true
|
|
283
329
|
end
|
|
284
330
|
end
|
|
285
331
|
|
|
286
|
-
def record_finished(status
|
|
287
|
-
|
|
288
|
-
record results.merge(:status => status, :finished_at => finished_at, :run_time => (finished_at - execution_result[:started_at]).to_f)
|
|
332
|
+
def record_finished(status)
|
|
333
|
+
execution_result.record_finished(status, clock.now)
|
|
289
334
|
end
|
|
290
335
|
|
|
291
|
-
def
|
|
336
|
+
def run_before_example
|
|
292
337
|
@example_group_instance.setup_mocks_for_rspec
|
|
293
|
-
@example_group_class.
|
|
338
|
+
@example_group_class.hooks.run(:before, :example, self)
|
|
294
339
|
end
|
|
295
340
|
|
|
296
|
-
def
|
|
297
|
-
@example_group_class.
|
|
341
|
+
def run_after_example
|
|
342
|
+
@example_group_class.hooks.run(:after, :example, self)
|
|
298
343
|
verify_mocks
|
|
344
|
+
assign_generated_description if RSpec.configuration.expecting_with_rspec?
|
|
299
345
|
rescue Exception => e
|
|
300
|
-
set_exception(e, "in an after(:
|
|
346
|
+
set_exception(e, "in an `after(:example)` hook")
|
|
301
347
|
ensure
|
|
302
348
|
@example_group_instance.teardown_mocks_for_rspec
|
|
303
349
|
end
|
|
304
350
|
|
|
305
351
|
def verify_mocks
|
|
306
|
-
@example_group_instance.verify_mocks_for_rspec
|
|
352
|
+
@example_group_instance.verify_mocks_for_rspec if mocks_need_verification?
|
|
307
353
|
rescue Exception => e
|
|
308
|
-
|
|
354
|
+
if pending?
|
|
355
|
+
execution_result.pending_fixed = false
|
|
356
|
+
@exception = nil
|
|
357
|
+
else
|
|
358
|
+
set_exception(e)
|
|
359
|
+
end
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
def mocks_need_verification?
|
|
363
|
+
exception.nil? || execution_result.pending_fixed?
|
|
309
364
|
end
|
|
310
365
|
|
|
311
366
|
def assign_generated_description
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
metadata[:
|
|
367
|
+
if metadata[:description].empty? && (description = RSpec::Matchers.generated_description)
|
|
368
|
+
metadata[:description] = description
|
|
369
|
+
metadata[:full_description] << description
|
|
315
370
|
end
|
|
371
|
+
rescue Exception => e
|
|
372
|
+
set_exception(e, "while assigning the example description")
|
|
373
|
+
ensure
|
|
316
374
|
RSpec::Matchers.clear_generated_description
|
|
317
375
|
end
|
|
318
376
|
|
|
319
|
-
def
|
|
320
|
-
|
|
377
|
+
def skip_message
|
|
378
|
+
if String === skip
|
|
379
|
+
skip
|
|
380
|
+
else
|
|
381
|
+
Pending::NO_REASON_GIVEN
|
|
382
|
+
end
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
# Represents the result of executing an example.
|
|
386
|
+
# Behaves like a hash for backwards compatibility.
|
|
387
|
+
class ExecutionResult
|
|
388
|
+
include HashImitatable
|
|
389
|
+
|
|
390
|
+
# @return [Symbol] `:passed`, `:failed` or `:pending`.
|
|
391
|
+
attr_accessor :status
|
|
392
|
+
|
|
393
|
+
# @return [Exception, nil] The failure, if there was one.
|
|
394
|
+
attr_accessor :exception
|
|
395
|
+
|
|
396
|
+
# @return [Time] When the example started.
|
|
397
|
+
attr_accessor :started_at
|
|
398
|
+
|
|
399
|
+
# @return [Time] When the example finished.
|
|
400
|
+
attr_accessor :finished_at
|
|
401
|
+
|
|
402
|
+
# @return [Float] How long the example took in seconds.
|
|
403
|
+
attr_accessor :run_time
|
|
404
|
+
|
|
405
|
+
# @return [String, nil] The reason the example was pending,
|
|
406
|
+
# or nil if the example was not pending.
|
|
407
|
+
attr_accessor :pending_message
|
|
408
|
+
|
|
409
|
+
# @return [Exception, nil] The exception triggered while
|
|
410
|
+
# executing the pending example. If no exception was triggered
|
|
411
|
+
# it would no longer get a status of `:pending` unless it was
|
|
412
|
+
# tagged with `:skip`.
|
|
413
|
+
attr_accessor :pending_exception
|
|
414
|
+
|
|
415
|
+
# @return [Boolean] For examples tagged with `:pending`,
|
|
416
|
+
# this indicates whether or not it now passes.
|
|
417
|
+
attr_accessor :pending_fixed
|
|
418
|
+
|
|
419
|
+
alias pending_fixed? pending_fixed
|
|
420
|
+
|
|
421
|
+
# @api private
|
|
422
|
+
# Records the finished status of the example.
|
|
423
|
+
def record_finished(status, finished_at)
|
|
424
|
+
self.status = status
|
|
425
|
+
self.finished_at = finished_at
|
|
426
|
+
self.run_time = (finished_at - started_at).to_f
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
private
|
|
430
|
+
|
|
431
|
+
# For backwards compatibility we present `status` as a string
|
|
432
|
+
# when presenting the legacy hash interface.
|
|
433
|
+
def hash_for_delegation
|
|
434
|
+
super.tap do |hash|
|
|
435
|
+
hash[:status] &&= status.to_s
|
|
436
|
+
end
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
def set_value(name, value)
|
|
440
|
+
value &&= value.to_sym if name == :status
|
|
441
|
+
super(name, value)
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
def get_value(name)
|
|
445
|
+
if name == :status
|
|
446
|
+
status.to_s if status
|
|
447
|
+
else
|
|
448
|
+
super
|
|
449
|
+
end
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
def issue_deprecation(method_name, *args)
|
|
453
|
+
RSpec.deprecate("Treating `metadata[:execution_result]` as a hash",
|
|
454
|
+
:replacement => "the attributes methods to access the data")
|
|
455
|
+
end
|
|
456
|
+
end
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
# @private
|
|
460
|
+
# Provides an execution context for before/after :suite hooks.
|
|
461
|
+
class SuiteHookContext < Example
|
|
462
|
+
def initialize
|
|
463
|
+
super(AnonymousExampleGroup, "", {})
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
# To ensure we don't silence errors...
|
|
467
|
+
def set_exception(exception, context=nil)
|
|
468
|
+
raise exception
|
|
321
469
|
end
|
|
322
470
|
end
|
|
323
471
|
end
|