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/runner.rb
CHANGED
|
@@ -1,10 +1,23 @@
|
|
|
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?
|
|
15
|
+
RSpec.deprecate("Requiring `rspec/autorun` when running RSpec via the `rspec` command")
|
|
16
|
+
return
|
|
17
|
+
elsif installed_at_exit? || running_in_drb?
|
|
18
|
+
return
|
|
19
|
+
end
|
|
20
|
+
|
|
8
21
|
at_exit do
|
|
9
22
|
# Don't bother running any specs and just let the program terminate
|
|
10
23
|
# if we got here due to an unrescued exception (anything other than
|
|
@@ -14,73 +27,41 @@ module RSpec
|
|
|
14
27
|
# We got here because either the end of the program was reached or
|
|
15
28
|
# somebody called Kernel#exit. Run the specs and then override any
|
|
16
29
|
# existing exit status with RSpec's exit status if any specs failed.
|
|
17
|
-
|
|
18
|
-
exit status if status != 0
|
|
30
|
+
invoke
|
|
19
31
|
end
|
|
20
32
|
@installed_at_exit = true
|
|
21
33
|
end
|
|
22
|
-
AT_EXIT_HOOK_BACKTRACE_LINE = "#{__FILE__}:#{__LINE__ - 2}:in `autorun'"
|
|
23
34
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
@autorun_disabled ||= false
|
|
35
|
+
# Runs the suite of specs and exits the process with an appropriate exit code.
|
|
36
|
+
def self.invoke
|
|
37
|
+
disable_autorun!
|
|
38
|
+
status = run(ARGV, $stderr, $stdout).to_i
|
|
39
|
+
exit(status) if status != 0
|
|
30
40
|
end
|
|
31
41
|
|
|
32
|
-
|
|
33
|
-
@installed_at_exit ||= false
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def self.running_in_drb?
|
|
37
|
-
defined?(DRb) &&
|
|
38
|
-
(DRb.current_server rescue false) &&
|
|
39
|
-
DRb.current_server.uri =~ /druby\:\/\/127.0.0.1\:/
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def self.trap_interrupt
|
|
43
|
-
trap('INT') do
|
|
44
|
-
exit!(1) if RSpec.wants_to_quit
|
|
45
|
-
RSpec.wants_to_quit = true
|
|
46
|
-
STDERR.puts "\nExiting... Interrupt again to exit immediately."
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
# Run a suite of RSpec examples.
|
|
42
|
+
# Run a suite of RSpec examples. Does not exit.
|
|
51
43
|
#
|
|
52
44
|
# This is used internally by RSpec to run a suite, but is available
|
|
53
45
|
# for use by any other automation tool.
|
|
54
46
|
#
|
|
55
47
|
# If you want to run this multiple times in the same process, and you
|
|
56
|
-
# want files like spec_helper.rb to be reloaded, be sure to load `load`
|
|
48
|
+
# want files like `spec_helper.rb` to be reloaded, be sure to load `load`
|
|
57
49
|
# instead of `require`.
|
|
58
50
|
#
|
|
59
|
-
#
|
|
60
|
-
#
|
|
61
|
-
#
|
|
62
|
-
#
|
|
63
|
-
#
|
|
64
|
-
#
|
|
65
|
-
# * +Fixnum+ - exit status code (0/1)
|
|
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.
|
|
66
57
|
def self.run(args, err=$stderr, out=$stdout)
|
|
67
58
|
trap_interrupt
|
|
68
59
|
options = ConfigurationOptions.new(args)
|
|
69
|
-
options.parse_options
|
|
70
|
-
|
|
71
|
-
major, minor, point = RUBY_VERSION.split('.').map { |v| v.to_i }
|
|
72
|
-
|
|
73
|
-
if major == 1 && ( (minor == 9 && point < 2) || (minor == 8 && point < 7) )
|
|
74
|
-
RSpec.deprecate "RSpec support for Ruby #{RUBY_VERSION}",
|
|
75
|
-
:replacement => "1.8.7 or >= 1.9.2",
|
|
76
|
-
:call_site => nil
|
|
77
|
-
end
|
|
78
|
-
|
|
79
60
|
|
|
80
61
|
if options.options[:drb]
|
|
81
|
-
require 'rspec/core/
|
|
62
|
+
require 'rspec/core/drb'
|
|
82
63
|
begin
|
|
83
|
-
|
|
64
|
+
DRbRunner.new(options).run(err, out)
|
|
84
65
|
rescue DRb::DRbConnError
|
|
85
66
|
err.puts "No DRb server is running. Running in local process instead ..."
|
|
86
67
|
new(options).run(err, out)
|
|
@@ -88,8 +69,92 @@ module RSpec
|
|
|
88
69
|
else
|
|
89
70
|
new(options).run(err, out)
|
|
90
71
|
end
|
|
91
|
-
|
|
92
|
-
|
|
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
|
|
120
|
+
def self.disable_autorun!
|
|
121
|
+
@autorun_disabled = true
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# @private
|
|
125
|
+
def self.autorun_disabled?
|
|
126
|
+
@autorun_disabled ||= false
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# @private
|
|
130
|
+
def self.installed_at_exit?
|
|
131
|
+
@installed_at_exit ||= false
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# @private
|
|
135
|
+
def self.running_in_drb?
|
|
136
|
+
begin
|
|
137
|
+
if defined?(DRb) && DRb.current_server
|
|
138
|
+
require 'socket'
|
|
139
|
+
require 'uri'
|
|
140
|
+
|
|
141
|
+
local_ipv4 = IPSocket.getaddress(Socket.gethostname)
|
|
142
|
+
|
|
143
|
+
local_drb = ["127.0.0.1", "localhost", local_ipv4].any? { |addr| addr == URI(DRb.current_server.uri).host }
|
|
144
|
+
end
|
|
145
|
+
rescue DRb::DRbServerNotFound
|
|
146
|
+
ensure
|
|
147
|
+
return local_drb || false
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# @private
|
|
152
|
+
def self.trap_interrupt
|
|
153
|
+
trap('INT') do
|
|
154
|
+
exit!(1) if RSpec.world.wants_to_quit
|
|
155
|
+
RSpec.world.wants_to_quit = true
|
|
156
|
+
STDERR.puts "\nExiting... Interrupt again to exit immediately."
|
|
157
|
+
end
|
|
93
158
|
end
|
|
94
159
|
end
|
|
95
160
|
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,39 +17,39 @@ 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
|
-
|
|
43
|
-
|
|
44
|
-
end
|
|
45
|
-
EOS
|
|
42
|
+
define_method(meth) do |*args, &block|
|
|
43
|
+
__shared_context_recordings << Recording.new(meth, args, block)
|
|
44
|
+
end
|
|
46
45
|
end
|
|
47
46
|
end
|
|
48
47
|
|
|
48
|
+
# @private
|
|
49
49
|
record [:describe, :context] + Hooks.instance_methods(false) +
|
|
50
50
|
MemoizedHelpers::ClassMethods.instance_methods(false)
|
|
51
51
|
end
|
|
52
52
|
end
|
|
53
|
-
|
|
53
|
+
# @private
|
|
54
54
|
SharedContext = Core::SharedContext
|
|
55
55
|
end
|
|
@@ -1,163 +1,158 @@
|
|
|
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
|
-
|
|
38
|
-
def share_examples_for(*args, &block)
|
|
39
|
-
RSpec.deprecate("`share_examples_for`", :replacement => "`shared_examples` or `shared_examples_for`")
|
|
40
|
-
shared_examples(*args, &block)
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
# @deprecated
|
|
44
|
-
def share_as(name, &block)
|
|
45
|
-
RSpec.deprecate("Rspec::Core::SharedExampleGroup#share_as",
|
|
46
|
-
:replacement => "RSpec::SharedContext or shared_examples")
|
|
47
|
-
SharedExampleGroup.registry.add_const(self, name, &block)
|
|
48
|
-
end
|
|
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
|
|
49
57
|
|
|
50
|
-
|
|
51
|
-
SharedExampleGroup.registry.shared_example_groups_for('main', *ancestors[0..-1])
|
|
58
|
+
RSpec.world.shared_example_group_registry.add(self, name, *args, &block)
|
|
52
59
|
end
|
|
60
|
+
alias shared_context shared_examples
|
|
61
|
+
alias shared_examples_for shared_examples
|
|
53
62
|
|
|
63
|
+
# @api private
|
|
64
|
+
#
|
|
65
|
+
# Shared examples top level DSL
|
|
54
66
|
module TopLevelDSL
|
|
55
|
-
|
|
56
|
-
|
|
67
|
+
# @private
|
|
68
|
+
def self.definitions
|
|
69
|
+
proc do
|
|
70
|
+
def shared_examples(name, *args, &block)
|
|
71
|
+
RSpec.world.shared_example_group_registry.add(:main, name, *args, &block)
|
|
72
|
+
end
|
|
73
|
+
alias shared_context shared_examples
|
|
74
|
+
alias shared_examples_for shared_examples
|
|
75
|
+
end
|
|
57
76
|
end
|
|
58
77
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
def share_examples_for(*args, &block)
|
|
63
|
-
RSpec.deprecate("`share_examples_for`", :replacement => "`shared_examples` or `shared_examples_for`")
|
|
64
|
-
shared_examples(*args, &block)
|
|
78
|
+
# @private
|
|
79
|
+
def self.exposed_globally?
|
|
80
|
+
@exposed_globally ||= false
|
|
65
81
|
end
|
|
66
82
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
83
|
+
# @api private
|
|
84
|
+
#
|
|
85
|
+
# Adds the top level DSL methods to Module and the top level binding
|
|
86
|
+
def self.expose_globally!
|
|
87
|
+
return if exposed_globally?
|
|
88
|
+
Core::DSL.change_global_dsl(&definitions)
|
|
89
|
+
@exposed_globally = true
|
|
70
90
|
end
|
|
71
91
|
|
|
72
|
-
|
|
73
|
-
|
|
92
|
+
# @api private
|
|
93
|
+
#
|
|
94
|
+
# Removes the top level DSL methods to Module and the top level binding
|
|
95
|
+
def self.remove_globally!
|
|
96
|
+
return unless exposed_globally?
|
|
97
|
+
|
|
98
|
+
Core::DSL.change_global_dsl do
|
|
99
|
+
undef shared_examples
|
|
100
|
+
undef shared_context
|
|
101
|
+
undef shared_examples_for
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
@exposed_globally = false
|
|
74
105
|
end
|
|
75
|
-
end
|
|
76
106
|
|
|
77
|
-
def self.registry
|
|
78
|
-
@registry ||= Registry.new
|
|
79
107
|
end
|
|
80
108
|
|
|
81
109
|
# @private
|
|
82
|
-
#
|
|
83
|
-
# Used internally to manage the shared example groups and
|
|
84
|
-
# constants. We want to limit the number of methods we add
|
|
85
|
-
# to objects we don't own (main and Module) so this allows
|
|
86
|
-
# us to have helper methods that don't get added to those
|
|
87
|
-
# objects.
|
|
88
110
|
class Registry
|
|
89
|
-
def
|
|
90
|
-
ensure_block_has_source_location(block
|
|
91
|
-
|
|
92
|
-
if
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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
|
|
96
119
|
end
|
|
97
120
|
|
|
98
|
-
unless
|
|
121
|
+
unless metadata_args.empty?
|
|
99
122
|
mod = Module.new
|
|
100
|
-
(class << mod; self; end).
|
|
101
|
-
host.
|
|
123
|
+
(class << mod; self; end).__send__(:define_method, :included) do |host|
|
|
124
|
+
host.class_exec(&block)
|
|
102
125
|
end
|
|
103
|
-
RSpec.configuration.
|
|
126
|
+
RSpec.configuration.include mod, *metadata_args
|
|
104
127
|
end
|
|
105
128
|
end
|
|
106
129
|
|
|
107
|
-
def
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
130
|
+
def find(lookup_contexts, name)
|
|
131
|
+
lookup_contexts.each do |context|
|
|
132
|
+
found = shared_example_groups[context][name]
|
|
133
|
+
return found if found
|
|
111
134
|
end
|
|
112
135
|
|
|
113
|
-
|
|
114
|
-
@shared_block = block
|
|
115
|
-
@caller_line = caller.last
|
|
116
|
-
|
|
117
|
-
def self.created_from_caller(other_caller)
|
|
118
|
-
@caller_line == other_caller.last
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
def self.included(kls)
|
|
122
|
-
kls.describe(&@shared_block)
|
|
123
|
-
kls.children.first.metadata[:shared_group_name] = name
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
shared_const = Object.const_set(name, mod)
|
|
128
|
-
add_shared_example_group source, shared_const, block
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
def shared_example_groups_for(*sources)
|
|
132
|
-
Collection.new(sources, shared_example_groups)
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
def shared_example_groups
|
|
136
|
-
@shared_example_groups ||= Hash.new { |hash,key| hash[key] = Hash.new }
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
def clear
|
|
140
|
-
shared_example_groups.clear
|
|
136
|
+
shared_example_groups[:main][name]
|
|
141
137
|
end
|
|
142
138
|
|
|
143
139
|
private
|
|
144
140
|
|
|
145
|
-
def
|
|
146
|
-
shared_example_groups[
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
def key?(candidate)
|
|
150
|
-
[String, Symbol, Module].any? { |cls| cls === candidate }
|
|
141
|
+
def shared_example_groups
|
|
142
|
+
@shared_example_groups ||= Hash.new { |hash, context| hash[context] = {} }
|
|
151
143
|
end
|
|
152
144
|
|
|
153
|
-
def
|
|
154
|
-
|
|
145
|
+
def valid_name?(candidate)
|
|
146
|
+
case candidate
|
|
147
|
+
when String, Symbol, Module then true
|
|
148
|
+
else false
|
|
149
|
+
end
|
|
155
150
|
end
|
|
156
151
|
|
|
157
|
-
def warn_if_key_taken(
|
|
158
|
-
return unless existing_block =
|
|
152
|
+
def warn_if_key_taken(context, key, new_block)
|
|
153
|
+
return unless existing_block = shared_example_groups[context][key]
|
|
159
154
|
|
|
160
|
-
|
|
155
|
+
RSpec.warn_with <<-WARNING.gsub(/^ +\|/, ''), :call_site => nil
|
|
161
156
|
|WARNING: Shared example group '#{key}' has been previously defined at:
|
|
162
157
|
| #{formatted_location existing_block}
|
|
163
158
|
|...and you are now defining it at:
|
|
@@ -170,25 +165,17 @@ module RSpec
|
|
|
170
165
|
block.source_location.join ":"
|
|
171
166
|
end
|
|
172
167
|
|
|
173
|
-
def example_block_for(source, key)
|
|
174
|
-
shared_example_groups[source][key]
|
|
175
|
-
end
|
|
176
|
-
|
|
177
168
|
if Proc.method_defined?(:source_location)
|
|
178
|
-
def ensure_block_has_source_location(block
|
|
169
|
+
def ensure_block_has_source_location(block); end
|
|
179
170
|
else # for 1.8.7
|
|
180
|
-
def ensure_block_has_source_location(block
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
caller_line.split(':')
|
|
184
|
-
end
|
|
185
|
-
}
|
|
171
|
+
def ensure_block_has_source_location(block)
|
|
172
|
+
source_location = yield.split(':')
|
|
173
|
+
block.extend Module.new { define_method(:source_location) { source_location } }
|
|
186
174
|
end
|
|
187
175
|
end
|
|
188
176
|
end
|
|
189
177
|
end
|
|
190
178
|
end
|
|
191
|
-
end
|
|
192
179
|
|
|
193
|
-
|
|
194
|
-
|
|
180
|
+
instance_exec(&Core::SharedExampleGroup::TopLevelDSL.definitions)
|
|
181
|
+
end
|
data/lib/rspec/core/version.rb
CHANGED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require "rspec/support/warnings"
|
|
2
|
+
|
|
3
|
+
module RSpec
|
|
4
|
+
module Core
|
|
5
|
+
# @private
|
|
6
|
+
module Warnings
|
|
7
|
+
# @private
|
|
8
|
+
#
|
|
9
|
+
# Used internally to print deprecation warnings
|
|
10
|
+
def deprecate(deprecated, data = {})
|
|
11
|
+
RSpec.configuration.reporter.deprecation(
|
|
12
|
+
{
|
|
13
|
+
:deprecated => deprecated,
|
|
14
|
+
:call_site => CallerFilter.first_non_rspec_line
|
|
15
|
+
}.merge(data)
|
|
16
|
+
)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# @private
|
|
20
|
+
#
|
|
21
|
+
# Used internally to print deprecation warnings
|
|
22
|
+
def warn_deprecation(message, opts = {})
|
|
23
|
+
RSpec.configuration.reporter.deprecation opts.merge( :message => message )
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# @private
|
|
27
|
+
def warn_with(message, options = {})
|
|
28
|
+
if options[:use_spec_location_as_call_site]
|
|
29
|
+
message += "." unless message.end_with?(".")
|
|
30
|
+
|
|
31
|
+
if RSpec.current_example
|
|
32
|
+
message += " Warning generated from spec at `#{RSpec.current_example.location}`."
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
super(message, options)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|