rspec-core 3.0.0.beta2 → 3.0.0.rc1
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 +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
data/lib/rspec/core/runner.rb
CHANGED
@@ -1,8 +1,15 @@
|
|
1
1
|
module RSpec
|
2
2
|
module Core
|
3
|
+
# Provides the main entry point to run a suite of RSpec examples.
|
3
4
|
class Runner
|
4
5
|
|
5
|
-
# Register an at_exit hook that runs the suite.
|
6
|
+
# Register an `at_exit` hook that runs the suite when the process exits.
|
7
|
+
#
|
8
|
+
# @note This is not generally needed. The `rspec` command takes care
|
9
|
+
# of running examples for you without involving an `at_exit`
|
10
|
+
# hook. This is only needed if you are running specs using
|
11
|
+
# the `ruby` command, and even then, the normal way to invoke
|
12
|
+
# this is by requiring `rspec/autorun`.
|
6
13
|
def self.autorun
|
7
14
|
if autorun_disabled?
|
8
15
|
RSpec.deprecate("Requiring `rspec/autorun` when running RSpec via the `rspec` command")
|
@@ -24,26 +31,107 @@ module RSpec
|
|
24
31
|
end
|
25
32
|
@installed_at_exit = true
|
26
33
|
end
|
27
|
-
AT_EXIT_HOOK_BACKTRACE_LINE = "#{__FILE__}:#{__LINE__ - 2}:in `autorun'"
|
28
34
|
|
35
|
+
# Runs the suite of specs and exits the process with an appropriate exit code.
|
29
36
|
def self.invoke
|
30
37
|
disable_autorun!
|
31
38
|
status = run(ARGV, $stderr, $stdout).to_i
|
32
39
|
exit(status) if status != 0
|
33
40
|
end
|
34
41
|
|
42
|
+
# Run a suite of RSpec examples. Does not exit.
|
43
|
+
#
|
44
|
+
# This is used internally by RSpec to run a suite, but is available
|
45
|
+
# for use by any other automation tool.
|
46
|
+
#
|
47
|
+
# If you want to run this multiple times in the same process, and you
|
48
|
+
# want files like `spec_helper.rb` to be reloaded, be sure to load `load`
|
49
|
+
# instead of `require`.
|
50
|
+
#
|
51
|
+
# @param args [Array] command-line-supported arguments
|
52
|
+
# @param err [IO] error stream
|
53
|
+
# @param out [IO] output stream
|
54
|
+
# @return [Fixnum] exit status code. 0 if all specs passed,
|
55
|
+
# or the configured failure exit code (1 by default) if specs
|
56
|
+
# failed.
|
57
|
+
def self.run(args, err=$stderr, out=$stdout)
|
58
|
+
trap_interrupt
|
59
|
+
options = ConfigurationOptions.new(args)
|
60
|
+
|
61
|
+
if options.options[:drb]
|
62
|
+
require 'rspec/core/drb'
|
63
|
+
begin
|
64
|
+
DRbRunner.new(options).run(err, out)
|
65
|
+
rescue DRb::DRbConnError
|
66
|
+
err.puts "No DRb server is running. Running in local process instead ..."
|
67
|
+
new(options).run(err, out)
|
68
|
+
end
|
69
|
+
else
|
70
|
+
new(options).run(err, out)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def initialize(options, configuration=RSpec.configuration, world=RSpec.world)
|
75
|
+
@options = options
|
76
|
+
@configuration = configuration
|
77
|
+
@world = world
|
78
|
+
end
|
79
|
+
|
80
|
+
# Configures and runs a spec suite.
|
81
|
+
#
|
82
|
+
# @param err [IO] error stream
|
83
|
+
# @param out [IO] output stream
|
84
|
+
def run(err, out)
|
85
|
+
setup(err, out)
|
86
|
+
run_specs(@world.ordered_example_groups)
|
87
|
+
end
|
88
|
+
|
89
|
+
# Wires together the various configuration objects and state holders.
|
90
|
+
#
|
91
|
+
# @param err [IO] error stream
|
92
|
+
# @param out [IO] output stream
|
93
|
+
def setup(err, out)
|
94
|
+
@configuration.error_stream = err
|
95
|
+
@configuration.output_stream = out if @configuration.output_stream == $stdout
|
96
|
+
@options.configure(@configuration)
|
97
|
+
@configuration.load_spec_files
|
98
|
+
@world.announce_filters
|
99
|
+
end
|
100
|
+
|
101
|
+
# Runs the provided example groups.
|
102
|
+
#
|
103
|
+
# @param example_groups [Array<RSpec::Core::ExampleGroup>] groups to run
|
104
|
+
# @return [Fixnum] exit status code. 0 if all specs passed,
|
105
|
+
# or the configured failure exit code (1 by default) if specs
|
106
|
+
# failed.
|
107
|
+
def run_specs(example_groups)
|
108
|
+
@configuration.reporter.report(@world.example_count(example_groups)) do |reporter|
|
109
|
+
begin
|
110
|
+
hook_context = SuiteHookContext.new
|
111
|
+
@configuration.hooks.run(:before, :suite, hook_context)
|
112
|
+
example_groups.map { |g| g.run(reporter) }.all? ? 0 : @configuration.failure_exit_code
|
113
|
+
ensure
|
114
|
+
@configuration.hooks.run(:after, :suite, hook_context)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# @private
|
35
120
|
def self.disable_autorun!
|
36
121
|
@autorun_disabled = true
|
37
122
|
end
|
38
123
|
|
124
|
+
# @private
|
39
125
|
def self.autorun_disabled?
|
40
126
|
@autorun_disabled ||= false
|
41
127
|
end
|
42
128
|
|
129
|
+
# @private
|
43
130
|
def self.installed_at_exit?
|
44
131
|
@installed_at_exit ||= false
|
45
132
|
end
|
46
133
|
|
134
|
+
# @private
|
47
135
|
def self.running_in_drb?
|
48
136
|
begin
|
49
137
|
if defined?(DRb) && DRb.current_server
|
@@ -60,48 +148,14 @@ module RSpec
|
|
60
148
|
end
|
61
149
|
end
|
62
150
|
|
151
|
+
# @private
|
63
152
|
def self.trap_interrupt
|
64
153
|
trap('INT') do
|
65
|
-
exit!(1) if RSpec.wants_to_quit
|
66
|
-
RSpec.wants_to_quit = true
|
154
|
+
exit!(1) if RSpec.world.wants_to_quit
|
155
|
+
RSpec.world.wants_to_quit = true
|
67
156
|
STDERR.puts "\nExiting... Interrupt again to exit immediately."
|
68
157
|
end
|
69
158
|
end
|
70
|
-
|
71
|
-
# Run a suite of RSpec examples.
|
72
|
-
#
|
73
|
-
# This is used internally by RSpec to run a suite, but is available
|
74
|
-
# for use by any other automation tool.
|
75
|
-
#
|
76
|
-
# If you want to run this multiple times in the same process, and you
|
77
|
-
# want files like spec_helper.rb to be reloaded, be sure to load `load`
|
78
|
-
# instead of `require`.
|
79
|
-
#
|
80
|
-
# #### Parameters
|
81
|
-
# * +args+ - an array of command-line-supported arguments
|
82
|
-
# * +err+ - error stream (Default: $stderr)
|
83
|
-
# * +out+ - output stream (Default: $stdout)
|
84
|
-
#
|
85
|
-
# #### Returns
|
86
|
-
# * +Fixnum+ - exit status code (0/1)
|
87
|
-
def self.run(args, err=$stderr, out=$stdout)
|
88
|
-
trap_interrupt
|
89
|
-
options = ConfigurationOptions.new(args)
|
90
|
-
|
91
|
-
if options.options[:drb]
|
92
|
-
require 'rspec/core/drb_command_line'
|
93
|
-
begin
|
94
|
-
DRbCommandLine.new(options).run(err, out)
|
95
|
-
rescue DRb::DRbConnError
|
96
|
-
err.puts "No DRb server is running. Running in local process instead ..."
|
97
|
-
CommandLine.new(options).run(err, out)
|
98
|
-
end
|
99
|
-
else
|
100
|
-
CommandLine.new(options).run(err, out)
|
101
|
-
end
|
102
|
-
ensure
|
103
|
-
RSpec.reset
|
104
|
-
end
|
105
159
|
end
|
106
160
|
end
|
107
161
|
end
|
@@ -7,7 +7,7 @@ module RSpec
|
|
7
7
|
#
|
8
8
|
# module LoggedInAsAdmin
|
9
9
|
# extend RSpec::Core::SharedContext
|
10
|
-
# before(:
|
10
|
+
# before(:example) do
|
11
11
|
# log_in_as :admin
|
12
12
|
# end
|
13
13
|
# end
|
@@ -17,25 +17,26 @@ module RSpec
|
|
17
17
|
# # ...
|
18
18
|
# end
|
19
19
|
module SharedContext
|
20
|
-
# @
|
20
|
+
# @private
|
21
21
|
def included(group)
|
22
22
|
__shared_context_recordings.each do |recording|
|
23
23
|
recording.playback_onto(group)
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
# @
|
27
|
+
# @private
|
28
28
|
def __shared_context_recordings
|
29
29
|
@__shared_context_recordings ||= []
|
30
30
|
end
|
31
31
|
|
32
|
+
# @private
|
32
33
|
Recording = Struct.new(:method_name, :args, :block) do
|
33
34
|
def playback_onto(group)
|
34
35
|
group.__send__(method_name, *args, &block)
|
35
36
|
end
|
36
37
|
end
|
37
38
|
|
38
|
-
# @
|
39
|
+
# @private
|
39
40
|
def self.record(methods)
|
40
41
|
methods.each do |meth|
|
41
42
|
define_method(meth) do |*args, &block|
|
@@ -44,10 +45,11 @@ module RSpec
|
|
44
45
|
end
|
45
46
|
end
|
46
47
|
|
48
|
+
# @private
|
47
49
|
record [:describe, :context] + Hooks.instance_methods(false) +
|
48
50
|
MemoizedHelpers::ClassMethods.instance_methods(false)
|
49
51
|
end
|
50
52
|
end
|
51
|
-
|
53
|
+
# @private
|
52
54
|
SharedContext = Core::SharedContext
|
53
55
|
end
|
@@ -1,57 +1,77 @@
|
|
1
1
|
module RSpec
|
2
2
|
module Core
|
3
|
+
# Shared example groups let you define common context and/or common
|
4
|
+
# examples that you wish to use in multiple example groups.
|
5
|
+
#
|
6
|
+
# When defined, the shared group block is stored for later evaluation.
|
7
|
+
# It can later be included in an example group either explicitly
|
8
|
+
# (using `include_examples`, `include_context` or `it_behaves_like`)
|
9
|
+
# or implicitly (via matching metadata).
|
10
|
+
#
|
11
|
+
# Named shared example groups are scoped based on where they are
|
12
|
+
# defined. Shared groups defined in an example group are available
|
13
|
+
# for inclusion in that example group or any child example groups,
|
14
|
+
# but not in any parent or sibling example groups. Shared example
|
15
|
+
# groups defined at the top level can be included from any example group.
|
3
16
|
module SharedExampleGroup
|
4
17
|
# @overload shared_examples(name, &block)
|
5
|
-
#
|
18
|
+
# @param name [String, Symbol, Module] identifer to use when looking up this shared group
|
19
|
+
# @param block The block to be eval'd
|
20
|
+
# @overload shared_examples(name, metadata, &block)
|
21
|
+
# @param name [String, Symbol, Module] identifer to use when looking up this shared group
|
22
|
+
# @param metadata [Array<Symbol>, Hash] metadata to attach to this group; any example group
|
23
|
+
# with matching metadata will automatically include this shared example group.
|
24
|
+
# @param block The block to be eval'd
|
25
|
+
# @overload shared_examples(metadata, &block)
|
26
|
+
# @param metadata [Array<Symbol>, Hash] metadata to attach to this group; any example group
|
27
|
+
# with matching metadata will automatically include this shared example group.
|
28
|
+
# @param block The block to be eval'd
|
6
29
|
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
# `it_behaves_like`.
|
10
|
-
#
|
11
|
-
# @param [String] name to match when looking up this shared group
|
12
|
-
# @param block to be eval'd in a nested example group generated by `it_behaves_like`
|
30
|
+
# Stores the block for later use. The block will be evaluated
|
31
|
+
# in the context of an example group via `include_examples`,
|
32
|
+
# `include_context`, or `it_behaves_like`.
|
13
33
|
#
|
14
34
|
# @example
|
15
|
-
#
|
16
35
|
# shared_examples "auditable" do
|
17
36
|
# it "stores an audit record on save!" do
|
18
|
-
#
|
37
|
+
# expect { auditable.save! }.to change(Audit, :count).by(1)
|
19
38
|
# end
|
20
39
|
# end
|
21
40
|
#
|
22
|
-
#
|
41
|
+
# describe Account do
|
23
42
|
# it_behaves_like "auditable" do
|
24
|
-
#
|
43
|
+
# let(:auditable) { Account.new }
|
25
44
|
# end
|
26
45
|
# end
|
27
46
|
#
|
28
47
|
# @see ExampleGroup.it_behaves_like
|
29
48
|
# @see ExampleGroup.include_examples
|
30
49
|
# @see ExampleGroup.include_context
|
31
|
-
def shared_examples(*args, &block)
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
50
|
+
def shared_examples(name, *args, &block)
|
51
|
+
top_level = self == ExampleGroup
|
52
|
+
if top_level && RSpec.thread_local_metadata[:in_example_group]
|
53
|
+
raise "Creating isolated shared examples from within a context is " +
|
54
|
+
"not allowed. Remove `RSpec.` prefix or move this to a " +
|
55
|
+
"top-level scope."
|
56
|
+
end
|
38
57
|
|
39
|
-
|
40
|
-
SharedExampleGroup.registry.shared_example_groups_for('main', *ancestors[0..-1])
|
58
|
+
RSpec.world.shared_example_group_registry.add(self, name, *args, &block)
|
41
59
|
end
|
60
|
+
alias shared_context shared_examples
|
61
|
+
alias shared_examples_for shared_examples
|
42
62
|
|
63
|
+
# @api private
|
64
|
+
#
|
65
|
+
# Shared examples top level DSL
|
43
66
|
module TopLevelDSL
|
67
|
+
# @private
|
44
68
|
def self.definitions
|
45
69
|
proc do
|
46
|
-
def shared_examples(*args, &block)
|
47
|
-
|
48
|
-
end
|
49
|
-
alias :shared_context :shared_examples
|
50
|
-
alias :share_examples_for :shared_examples
|
51
|
-
alias :shared_examples_for :shared_examples
|
52
|
-
def shared_example_groups
|
53
|
-
SharedExampleGroup.registry.shared_example_groups_for('main')
|
70
|
+
def shared_examples(name, *args, &block)
|
71
|
+
RSpec.world.shared_example_group_registry.add(:main, name, *args, &block)
|
54
72
|
end
|
73
|
+
alias shared_context shared_examples
|
74
|
+
alias shared_examples_for shared_examples
|
55
75
|
end
|
56
76
|
end
|
57
77
|
|
@@ -60,21 +80,25 @@ module RSpec
|
|
60
80
|
@exposed_globally ||= false
|
61
81
|
end
|
62
82
|
|
83
|
+
# @api private
|
84
|
+
#
|
85
|
+
# Adds the top level DSL methods to Module and the top level binding
|
63
86
|
def self.expose_globally!
|
64
87
|
return if exposed_globally?
|
65
88
|
Core::DSL.change_global_dsl(&definitions)
|
66
89
|
@exposed_globally = true
|
67
90
|
end
|
68
91
|
|
92
|
+
# @api private
|
93
|
+
#
|
94
|
+
# Removes the top level DSL methods to Module and the top level binding
|
69
95
|
def self.remove_globally!
|
70
96
|
return unless exposed_globally?
|
71
97
|
|
72
98
|
Core::DSL.change_global_dsl do
|
73
99
|
undef shared_examples
|
74
100
|
undef shared_context
|
75
|
-
undef share_examples_for
|
76
101
|
undef shared_examples_for
|
77
|
-
undef shared_example_groups
|
78
102
|
end
|
79
103
|
|
80
104
|
@exposed_globally = false
|
@@ -82,60 +106,51 @@ module RSpec
|
|
82
106
|
|
83
107
|
end
|
84
108
|
|
85
|
-
def self.registry
|
86
|
-
@registry ||= Registry.new
|
87
|
-
end
|
88
|
-
|
89
109
|
# @private
|
90
|
-
#
|
91
|
-
# Used internally to manage the shared example groups and
|
92
|
-
# constants. We want to limit the number of methods we add
|
93
|
-
# to objects we don't own (main and Module) so this allows
|
94
|
-
# us to have helper methods that don't get added to those
|
95
|
-
# objects.
|
96
110
|
class Registry
|
97
|
-
def
|
98
|
-
ensure_block_has_source_location(block
|
99
|
-
|
100
|
-
if
|
101
|
-
|
102
|
-
|
103
|
-
|
111
|
+
def add(context, name, *metadata_args, &block)
|
112
|
+
ensure_block_has_source_location(block) { CallerFilter.first_non_rspec_line }
|
113
|
+
|
114
|
+
if valid_name?(name)
|
115
|
+
warn_if_key_taken context, name, block
|
116
|
+
shared_example_groups[context][name] = block
|
117
|
+
else
|
118
|
+
metadata_args.unshift name
|
104
119
|
end
|
105
120
|
|
106
|
-
unless
|
121
|
+
unless metadata_args.empty?
|
107
122
|
mod = Module.new
|
108
123
|
(class << mod; self; end).__send__(:define_method, :included) do |host|
|
109
|
-
host.
|
124
|
+
host.class_exec(&block)
|
110
125
|
end
|
111
|
-
RSpec.configuration.include mod, *
|
126
|
+
RSpec.configuration.include mod, *metadata_args
|
112
127
|
end
|
113
128
|
end
|
114
129
|
|
115
|
-
def
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
@shared_example_groups ||= Hash.new { |hash, key| hash[key] = Hash.new }
|
121
|
-
end
|
130
|
+
def find(lookup_contexts, name)
|
131
|
+
lookup_contexts.each do |context|
|
132
|
+
found = shared_example_groups[context][name]
|
133
|
+
return found if found
|
134
|
+
end
|
122
135
|
|
123
|
-
|
124
|
-
shared_example_groups.clear
|
136
|
+
shared_example_groups[:main][name]
|
125
137
|
end
|
126
138
|
|
127
139
|
private
|
128
140
|
|
129
|
-
def
|
130
|
-
shared_example_groups[
|
141
|
+
def shared_example_groups
|
142
|
+
@shared_example_groups ||= Hash.new { |hash, context| hash[context] = {} }
|
131
143
|
end
|
132
144
|
|
133
|
-
def
|
134
|
-
|
145
|
+
def valid_name?(candidate)
|
146
|
+
case candidate
|
147
|
+
when String, Symbol, Module then true
|
148
|
+
else false
|
149
|
+
end
|
135
150
|
end
|
136
151
|
|
137
|
-
def warn_if_key_taken(
|
138
|
-
return unless existing_block =
|
152
|
+
def warn_if_key_taken(context, key, new_block)
|
153
|
+
return unless existing_block = shared_example_groups[context][key]
|
139
154
|
|
140
155
|
RSpec.warn_with <<-WARNING.gsub(/^ +\|/, ''), :call_site => nil
|
141
156
|
|WARNING: Shared example group '#{key}' has been previously defined at:
|
@@ -150,24 +165,17 @@ module RSpec
|
|
150
165
|
block.source_location.join ":"
|
151
166
|
end
|
152
167
|
|
153
|
-
def example_block_for(source, key)
|
154
|
-
shared_example_groups[source][key]
|
155
|
-
end
|
156
|
-
|
157
168
|
if Proc.method_defined?(:source_location)
|
158
|
-
def ensure_block_has_source_location(block
|
169
|
+
def ensure_block_has_source_location(block); end
|
159
170
|
else # for 1.8.7
|
160
|
-
def ensure_block_has_source_location(block
|
161
|
-
|
162
|
-
|
163
|
-
caller_line.split(':')
|
164
|
-
end
|
165
|
-
}
|
171
|
+
def ensure_block_has_source_location(block)
|
172
|
+
source_location = yield.split(':')
|
173
|
+
block.extend Module.new { define_method(:source_location) { source_location } }
|
166
174
|
end
|
167
175
|
end
|
168
176
|
end
|
169
177
|
end
|
170
178
|
end
|
171
179
|
|
172
|
-
|
180
|
+
instance_exec(&Core::SharedExampleGroup::TopLevelDSL.definitions)
|
173
181
|
end
|