rspec-core 3.0.0.beta2 → 3.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (201) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/.yardopts +1 -0
  5. data/Changelog.md +297 -57
  6. data/README.md +16 -13
  7. data/lib/rspec/core.rb +55 -84
  8. data/lib/rspec/core/backport_random.rb +35 -3
  9. data/lib/rspec/core/backtrace_formatter.rb +4 -13
  10. data/lib/rspec/core/configuration.rb +330 -114
  11. data/lib/rspec/core/configuration_options.rb +38 -22
  12. data/lib/rspec/core/drb.rb +111 -0
  13. data/lib/rspec/core/dsl.rb +8 -2
  14. data/lib/rspec/core/example.rb +203 -94
  15. data/lib/rspec/core/example_group.rb +344 -316
  16. data/lib/rspec/core/filter_manager.rb +135 -90
  17. data/lib/rspec/core/flat_map.rb +1 -0
  18. data/lib/rspec/core/formatters.rb +50 -14
  19. data/lib/rspec/core/formatters/base_formatter.rb +32 -138
  20. data/lib/rspec/core/formatters/base_text_formatter.rb +32 -253
  21. data/lib/rspec/core/formatters/console_codes.rb +65 -0
  22. data/lib/rspec/core/formatters/deprecation_formatter.rb +24 -15
  23. data/lib/rspec/core/formatters/documentation_formatter.rb +7 -10
  24. data/lib/rspec/core/formatters/helpers.rb +15 -9
  25. data/lib/rspec/core/formatters/html_formatter.rb +17 -16
  26. data/lib/rspec/core/formatters/html_printer.rb +1 -0
  27. data/lib/rspec/core/formatters/json_formatter.rb +18 -20
  28. data/lib/rspec/core/formatters/profile_formatter.rb +67 -0
  29. data/lib/rspec/core/formatters/progress_formatter.rb +6 -7
  30. data/lib/rspec/core/formatters/snippet_extractor.rb +8 -6
  31. data/lib/rspec/core/hooks.rb +131 -125
  32. data/lib/rspec/core/memoized_helpers.rb +31 -26
  33. data/lib/rspec/core/metadata.rb +277 -184
  34. data/lib/rspec/core/metadata_filter.rb +86 -0
  35. data/lib/rspec/core/minitest_assertions_adapter.rb +28 -0
  36. data/lib/rspec/core/mocking_adapters/flexmock.rb +1 -1
  37. data/lib/rspec/core/mocking_adapters/mocha.rb +1 -1
  38. data/lib/rspec/core/mocking_adapters/null.rb +1 -1
  39. data/lib/rspec/core/mocking_adapters/rr.rb +2 -1
  40. data/lib/rspec/core/mocking_adapters/rspec.rb +1 -1
  41. data/lib/rspec/core/notifications.rb +435 -24
  42. data/lib/rspec/core/option_parser.rb +16 -25
  43. data/lib/rspec/core/ordering.rb +3 -1
  44. data/lib/rspec/core/pending.rb +57 -33
  45. data/lib/rspec/core/project_initializer.rb +2 -0
  46. data/lib/rspec/core/project_initializer/spec_helper.rb +5 -4
  47. data/lib/rspec/core/rake_task.rb +45 -20
  48. data/lib/rspec/core/reporter.rb +50 -22
  49. data/lib/rspec/core/ruby_project.rb +1 -0
  50. data/lib/rspec/core/runner.rb +93 -39
  51. data/lib/rspec/core/shared_context.rb +7 -5
  52. data/lib/rspec/core/shared_example_group.rb +85 -77
  53. data/lib/rspec/core/test_unit_assertions_adapter.rb +30 -0
  54. data/lib/rspec/core/version.rb +3 -1
  55. data/lib/rspec/core/warnings.rb +35 -17
  56. data/lib/rspec/core/world.rb +57 -5
  57. metadata +56 -369
  58. metadata.gz.sig +3 -3
  59. data/features/README.md +0 -13
  60. data/features/Upgrade.md +0 -352
  61. data/features/command_line/README.md +0 -25
  62. data/features/command_line/dry_run.feature +0 -29
  63. data/features/command_line/example_name_option.feature +0 -97
  64. data/features/command_line/exit_status.feature +0 -82
  65. data/features/command_line/fail_fast.feature +0 -26
  66. data/features/command_line/format_option.feature +0 -75
  67. data/features/command_line/init.feature +0 -57
  68. data/features/command_line/line_number_appended_to_path.feature +0 -140
  69. data/features/command_line/line_number_option.feature +0 -58
  70. data/features/command_line/order.feature +0 -25
  71. data/features/command_line/pattern_option.feature +0 -49
  72. data/features/command_line/rake_task.feature +0 -122
  73. data/features/command_line/randomization.feature +0 -63
  74. data/features/command_line/require_option.feature +0 -43
  75. data/features/command_line/ruby.feature +0 -23
  76. data/features/command_line/tag.feature +0 -98
  77. data/features/command_line/warnings_option.feature +0 -29
  78. data/features/configuration/alias_example_to.feature +0 -39
  79. data/features/configuration/backtrace_exclusion_patterns.feature +0 -105
  80. data/features/configuration/custom_settings.feature +0 -84
  81. data/features/configuration/default_path.feature +0 -38
  82. data/features/configuration/deprecation_stream.feature +0 -58
  83. data/features/configuration/enable_global_dsl.feature +0 -54
  84. data/features/configuration/fail_fast.feature +0 -77
  85. data/features/configuration/failure_exit_code.feature +0 -36
  86. data/features/configuration/order_and_seed.feature +0 -3
  87. data/features/configuration/output_stream.feature +0 -24
  88. data/features/configuration/overriding_global_ordering.feature +0 -93
  89. data/features/configuration/pattern.feature +0 -38
  90. data/features/configuration/profile.feature +0 -220
  91. data/features/configuration/read_options_from_file.feature +0 -90
  92. data/features/configuration/run_all_when_everything_filtered.feature +0 -76
  93. data/features/example_groups/aliasing.feature +0 -48
  94. data/features/example_groups/basic_structure.feature +0 -55
  95. data/features/example_groups/shared_context.feature +0 -74
  96. data/features/example_groups/shared_examples.feature +0 -286
  97. data/features/expectation_framework_integration/configure_expectation_framework.feature +0 -102
  98. data/features/filtering/exclusion_filters.feature +0 -135
  99. data/features/filtering/if_and_unless.feature +0 -138
  100. data/features/filtering/inclusion_filters.feature +0 -101
  101. data/features/formatters/configurable_colors.feature +0 -31
  102. data/features/formatters/custom_formatter.feature +0 -68
  103. data/features/formatters/json_formatter.feature +0 -30
  104. data/features/formatters/regression_tests.feature +0 -95
  105. data/features/formatters/text_formatter.feature +0 -46
  106. data/features/helper_methods/arbitrary_methods.feature +0 -40
  107. data/features/helper_methods/let.feature +0 -50
  108. data/features/helper_methods/modules.feature +0 -146
  109. data/features/hooks/around_hooks.feature +0 -344
  110. data/features/hooks/before_and_after_hooks.feature +0 -427
  111. data/features/hooks/filtering.feature +0 -232
  112. data/features/metadata/current_example.feature +0 -56
  113. data/features/metadata/described_class.feature +0 -17
  114. data/features/metadata/user_defined.feature +0 -100
  115. data/features/mock_framework_integration/use_any_framework.feature +0 -106
  116. data/features/mock_framework_integration/use_flexmock.feature +0 -94
  117. data/features/mock_framework_integration/use_mocha.feature +0 -95
  118. data/features/mock_framework_integration/use_rr.feature +0 -96
  119. data/features/mock_framework_integration/use_rspec.feature +0 -95
  120. data/features/pending_and_skipped_examples/README.md +0 -3
  121. data/features/pending_and_skipped_examples/pending_examples.feature +0 -118
  122. data/features/pending_and_skipped_examples/skipped_examples.feature +0 -106
  123. data/features/spec_files/arbitrary_file_suffix.feature +0 -13
  124. data/features/step_definitions/additional_cli_steps.rb +0 -83
  125. data/features/subject/explicit_subject.feature +0 -101
  126. data/features/subject/implicit_subject.feature +0 -63
  127. data/features/subject/one_liner_syntax.feature +0 -71
  128. data/features/support/env.rb +0 -21
  129. data/features/support/require_expect_syntax_in_aruba_specs.rb +0 -16
  130. data/features/support/rubinius.rb +0 -6
  131. data/lib/rspec/core/command_line.rb +0 -35
  132. data/lib/rspec/core/drb_command_line.rb +0 -26
  133. data/lib/rspec/core/drb_options.rb +0 -87
  134. data/lib/rspec/core/formatters/legacy_formatter.rb +0 -227
  135. data/lib/rspec/core/shared_example_group/collection.rb +0 -27
  136. data/spec/command_line/order_spec.rb +0 -211
  137. data/spec/rspec/core/backtrace_formatter_spec.rb +0 -230
  138. data/spec/rspec/core/command_line_spec.rb +0 -112
  139. data/spec/rspec/core/command_line_spec_output.txt +0 -0
  140. data/spec/rspec/core/configuration_options_spec.rb +0 -409
  141. data/spec/rspec/core/configuration_spec.rb +0 -1479
  142. data/spec/rspec/core/drb_command_line_spec.rb +0 -102
  143. data/spec/rspec/core/drb_options_spec.rb +0 -193
  144. data/spec/rspec/core/dsl_spec.rb +0 -88
  145. data/spec/rspec/core/example_group_spec.rb +0 -1533
  146. data/spec/rspec/core/example_spec.rb +0 -642
  147. data/spec/rspec/core/filter_manager_spec.rb +0 -229
  148. data/spec/rspec/core/formatters/base_formatter_spec.rb +0 -64
  149. data/spec/rspec/core/formatters/base_text_formatter_spec.rb +0 -303
  150. data/spec/rspec/core/formatters/deprecation_formatter_spec.rb +0 -208
  151. data/spec/rspec/core/formatters/documentation_formatter_spec.rb +0 -75
  152. data/spec/rspec/core/formatters/helpers_spec.rb +0 -104
  153. data/spec/rspec/core/formatters/html_formatted-2.1.0.html +0 -392
  154. data/spec/rspec/core/formatters/html_formatted.html +0 -397
  155. data/spec/rspec/core/formatters/html_formatter_spec.rb +0 -122
  156. data/spec/rspec/core/formatters/json_formatter_spec.rb +0 -206
  157. data/spec/rspec/core/formatters/legacy_formatter_spec.rb +0 -137
  158. data/spec/rspec/core/formatters/progress_formatter_spec.rb +0 -43
  159. data/spec/rspec/core/formatters/snippet_extractor_spec.rb +0 -26
  160. data/spec/rspec/core/formatters_spec.rb +0 -120
  161. data/spec/rspec/core/hooks_filtering_spec.rb +0 -227
  162. data/spec/rspec/core/hooks_spec.rb +0 -294
  163. data/spec/rspec/core/memoized_helpers_spec.rb +0 -495
  164. data/spec/rspec/core/metadata_spec.rb +0 -491
  165. data/spec/rspec/core/option_parser_spec.rb +0 -262
  166. data/spec/rspec/core/ordering_spec.rb +0 -102
  167. data/spec/rspec/core/pending_example_spec.rb +0 -117
  168. data/spec/rspec/core/pending_spec.rb +0 -8
  169. data/spec/rspec/core/project_initializer_spec.rb +0 -73
  170. data/spec/rspec/core/rake_task_spec.rb +0 -146
  171. data/spec/rspec/core/random_spec.rb +0 -47
  172. data/spec/rspec/core/reporter_spec.rb +0 -155
  173. data/spec/rspec/core/resources/a_bar.rb +0 -0
  174. data/spec/rspec/core/resources/a_foo.rb +0 -0
  175. data/spec/rspec/core/resources/a_spec.rb +0 -1
  176. data/spec/rspec/core/resources/custom_example_group_runner.rb +0 -14
  177. data/spec/rspec/core/resources/formatter_specs.rb +0 -58
  178. data/spec/rspec/core/resources/utf8_encoded.rb +0 -8
  179. data/spec/rspec/core/rspec_matchers_spec.rb +0 -45
  180. data/spec/rspec/core/ruby_project_spec.rb +0 -26
  181. data/spec/rspec/core/runner_spec.rb +0 -151
  182. data/spec/rspec/core/shared_context_spec.rb +0 -102
  183. data/spec/rspec/core/shared_example_group/collection_spec.rb +0 -57
  184. data/spec/rspec/core/shared_example_group_spec.rb +0 -114
  185. data/spec/rspec/core/warnings_spec.rb +0 -29
  186. data/spec/rspec/core/world_spec.rb +0 -142
  187. data/spec/rspec/core_spec.rb +0 -91
  188. data/spec/spec_helper.rb +0 -160
  189. data/spec/support/config_options_helper.rb +0 -13
  190. data/spec/support/formatter_support.rb +0 -83
  191. data/spec/support/helper_methods.rb +0 -26
  192. data/spec/support/isolate_load_path_mutation.rb +0 -5
  193. data/spec/support/isolated_directory.rb +0 -10
  194. data/spec/support/isolated_home_directory.rb +0 -16
  195. data/spec/support/legacy_formatter_using_sub_classing_example.rb +0 -87
  196. data/spec/support/matchers.rb +0 -85
  197. data/spec/support/mathn_integration_support.rb +0 -12
  198. data/spec/support/old_style_formatter_example.rb +0 -69
  199. data/spec/support/shared_example_groups.rb +0 -13
  200. data/spec/support/spec_files.rb +0 -44
  201. data/spec/support/stderr_splitter.rb +0 -36
@@ -6,6 +6,7 @@ require 'pathname'
6
6
 
7
7
  module RSpec
8
8
  module Core
9
+ # @private
9
10
  module RubyProject
10
11
  def add_to_load_path(*dirs)
11
12
  dirs.map {|dir| add_dir_to_load_path(File.join(root, dir))}
@@ -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(:each) do
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
- # @api private
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
- # @api private
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
- # @api private
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
- # @overload shared_examples(name, tags, &block)
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
- # Wraps the `block` in a module which can then be included in example
8
- # groups using `include_examples`, `include_context`, or
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
- # lambda { auditable.save! }.should change(Audit, :count).by(1)
37
+ # expect { auditable.save! }.to change(Audit, :count).by(1)
19
38
  # end
20
39
  # end
21
40
  #
22
- # class Account do
41
+ # describe Account do
23
42
  # it_behaves_like "auditable" do
24
- # def auditable; Account.new; end
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
- SharedExampleGroup.registry.add_group(self, *args, &block)
33
- end
34
-
35
- alias_method :shared_context, :shared_examples
36
- alias_method :share_examples_for, :shared_examples
37
- alias_method :shared_examples_for, :shared_examples
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
- def shared_example_groups
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
- SharedExampleGroup.registry.add_group('main', *args, &block)
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 add_group(source, *args, &block)
98
- ensure_block_has_source_location(block, CallerFilter.first_non_rspec_line)
99
-
100
- if key? args.first
101
- key = args.shift
102
- warn_if_key_taken source, key, block
103
- add_shared_example_group source, key, block
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 args.empty?
121
+ unless metadata_args.empty?
107
122
  mod = Module.new
108
123
  (class << mod; self; end).__send__(:define_method, :included) do |host|
109
- host.class_eval(&block)
124
+ host.class_exec(&block)
110
125
  end
111
- RSpec.configuration.include mod, *args
126
+ RSpec.configuration.include mod, *metadata_args
112
127
  end
113
128
  end
114
129
 
115
- def shared_example_groups_for(*sources)
116
- Collection.new(sources, shared_example_groups)
117
- end
118
-
119
- def shared_example_groups
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
- def clear
124
- shared_example_groups.clear
136
+ shared_example_groups[:main][name]
125
137
  end
126
138
 
127
139
  private
128
140
 
129
- def add_shared_example_group(source, key, block)
130
- shared_example_groups[source][key] = block
141
+ def shared_example_groups
142
+ @shared_example_groups ||= Hash.new { |hash, context| hash[context] = {} }
131
143
  end
132
144
 
133
- def key?(candidate)
134
- [String, Symbol, Module].any? { |cls| cls === candidate }
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(source, key, new_block)
138
- return unless existing_block = example_block_for(source, key)
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, caller_line); end
169
+ def ensure_block_has_source_location(block); end
159
170
  else # for 1.8.7
160
- def ensure_block_has_source_location(block, caller_line)
161
- block.extend Module.new {
162
- define_method :source_location do
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
- instance_eval(&Core::SharedExampleGroup::TopLevelDSL.definitions)
180
+ instance_exec(&Core::SharedExampleGroup::TopLevelDSL.definitions)
173
181
  end