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
@@ -12,199 +12,287 @@ module RSpec
12
12
  # The object returned by `it "does something"` is an instance of Example,
13
13
  # which serves as a wrapper for an instance of the ExampleGroup in which it
14
14
  # is declared.
15
+ #
16
+ # Example group bodies (e.g. `describe` or `context` blocks) are evaluated
17
+ # in the context of a new subclass of ExampleGroup. Individual examples are
18
+ # evalutaed in the context of an instance of the specific ExampleGroup subclass
19
+ # to which they belong.
20
+ #
21
+ # Besides the class methods defined here, there are other interesting macros
22
+ # defined in {Hooks}, {MemoizedHelpers::ClassMethods} and {SharedExampleGroup}.
23
+ # There are additional instance methods available to your examples defined in
24
+ # {MemoizedHelpers} and {Pending}.
15
25
  class ExampleGroup
16
26
  extend Hooks
17
27
 
18
28
  include MemoizedHelpers
29
+ extend MemoizedHelpers::ClassMethods
19
30
  include Pending
20
- extend SharedExampleGroup
31
+ extend SharedExampleGroup
21
32
 
22
- # @private
23
- def self.world
24
- RSpec.world
33
+ unless respond_to?(:define_singleton_method)
34
+ # @private
35
+ def self.define_singleton_method(*a, &b)
36
+ (class << self; self; end).__send__(:define_method, *a, &b)
37
+ end
38
+ end
39
+
40
+ # @!group Metadata
41
+
42
+ # The [Metadata](Metadata) object associated with this group.
43
+ # @see Metadata
44
+ def self.metadata
45
+ @metadata if defined?(@metadata)
25
46
  end
26
47
 
27
48
  # @private
28
- def self.register
29
- world.register(self)
49
+ # @return [Metadata] belonging to the parent of a nested {ExampleGroup}
50
+ def self.superclass_metadata
51
+ @superclass_metadata ||= self.superclass.respond_to?(:metadata) ? self.superclass.metadata : nil
30
52
  end
31
53
 
32
- class << self
33
- # @private
34
- def self.delegate_to_metadata(*names)
35
- names.each do |name|
36
- define_method name do
37
- metadata[:example_group][name]
38
- end
39
- end
54
+ # @private
55
+ def self.delegate_to_metadata(*names)
56
+ names.each do |name|
57
+ define_singleton_method(name) { metadata.fetch(name) }
40
58
  end
59
+ end
41
60
 
42
- def description
43
- description = metadata[:example_group][:description]
44
- RSpec.configuration.format_docstrings_block.call(description)
45
- end
61
+ delegate_to_metadata :described_class, :file_path, :location
46
62
 
47
- delegate_to_metadata :described_class, :file_path
48
- alias_method :display_name, :description
49
- # @private
50
- alias_method :describes, :described_class
63
+ # @return [String] the current example group description
64
+ def self.description
65
+ description = metadata[:description]
66
+ RSpec.configuration.format_docstrings_block.call(description)
67
+ end
51
68
 
52
- # @private
53
- # @macro [attach] define_example_method
54
- # @param [String] name
55
- # @param [Hash] extra_options
56
- # @param [Block] implementation
57
- # @yield [Example] the example object
58
- def self.define_example_method(name, extra_options={})
59
- define_method(name) do |*all_args, &block|
60
- desc, *args = *all_args
61
- options = Metadata.build_hash_from(args)
62
- options.update(:skip => RSpec::Core::Pending::NOT_YET_IMPLEMENTED) unless block
63
- options.update(extra_options)
64
-
65
- # Metadata inheritance normally happens in `Example#initialize`,
66
- # but for `:pending` specifically we need it earlier.
67
- pending_metadata = options[:pending] || metadata[:pending]
68
-
69
- if pending_metadata
70
- options, block = ExampleGroup.pending_metadata_and_block_for(
71
- options.merge(:pending => pending_metadata),
72
- block
73
- )
74
- end
69
+ # Returns the class or module passed to the `describe` method (or alias).
70
+ # Returns nil if the subject is not a class or module.
71
+ # @example
72
+ # describe Thing do
73
+ # it "does something" do
74
+ # described_class == Thing
75
+ # end
76
+ # end
77
+ #
78
+ #
79
+ def described_class
80
+ self.class.described_class
81
+ end
82
+
83
+ # @!endgroup
75
84
 
76
- examples << RSpec::Core::Example.new(self, desc, options, block)
77
- examples.last
85
+ # @!group Defining Examples
86
+
87
+ # @private
88
+ # @macro [attach] define_example_method
89
+ # @!scope class
90
+ # @param name [String]
91
+ # @param extra_options [Hash]
92
+ # @param implementation [Block]
93
+ # @yield [Example] the example object
94
+ # @example
95
+ # $1 do
96
+ # end
97
+ #
98
+ # $1 "does something" do
99
+ # end
100
+ #
101
+ # $1 "does something", :with => 'additional metadata' do
102
+ # end
103
+ #
104
+ # $1 "does something" do |ex|
105
+ # # ex is the Example object that contains metadata about the example
106
+ # end
107
+ def self.define_example_method(name, extra_options={})
108
+ define_singleton_method(name) do |*all_args, &block|
109
+ desc, *args = *all_args
110
+ options = Metadata.build_hash_from(args)
111
+ options.update(:skip => RSpec::Core::Pending::NOT_YET_IMPLEMENTED) unless block
112
+ options.update(extra_options)
113
+
114
+ # Metadata inheritance normally happens in `Example#initialize`,
115
+ # but for `:pending` specifically we need it earlier.
116
+ pending_metadata = options[:pending] || metadata[:pending]
117
+
118
+ if pending_metadata
119
+ options, block = ExampleGroup.pending_metadata_and_block_for(
120
+ options.merge(:pending => pending_metadata),
121
+ block
122
+ )
78
123
  end
124
+
125
+ examples << RSpec::Core::Example.new(self, desc, options, block)
126
+ examples.last
79
127
  end
128
+ end
80
129
 
81
- def pending_metadata_and_block_for(options, block)
82
- if String === options[:pending]
83
- reason = options[:pending]
84
- else
85
- options[:pending] = true
86
- reason = RSpec::Core::Pending::NO_REASON_GIVEN
87
- end
130
+ # Defines an example within a group.
131
+ define_example_method :example
132
+ # Defines an example within a group.
133
+ # This is the primary API to define a code example.
134
+ define_example_method :it
135
+ # Defines an example within a group.
136
+ # Useful for when your docstring does not read well off of `it`.
137
+ # @example
138
+ # RSpec.describe MyClass do
139
+ # specify "#do_something is deprecated" do
140
+ # # ...
141
+ # end
142
+ # end
143
+ define_example_method :specify
144
+
145
+ # Shortcut to define an example with `:focus => true`
146
+ # @see example
147
+ define_example_method :focus, :focus => true
148
+ # Shortcut to define an example with `:focus => true`
149
+ # @see example
150
+ define_example_method :fexample, :focus => true
151
+ # Shortcut to define an example with `:focus => true`
152
+ # @see example
153
+ define_example_method :fit, :focus => true
154
+ # Shortcut to define an example with `:focus => true`
155
+ # @see example
156
+ define_example_method :fspecify, :focus => true
157
+ # Shortcut to define an example with `:skip => 'Temporarily skipped with xexample'`
158
+ # @see example
159
+ define_example_method :xexample, :skip => 'Temporarily skipped with xexample'
160
+ # Shortcut to define an example with `:skip => 'Temporarily skipped with xit'`
161
+ # @see example
162
+ define_example_method :xit, :skip => 'Temporarily skipped with xit'
163
+ # Shortcut to define an example with `:skip => 'Temporarily skipped with xspecify'`
164
+ # @see example
165
+ define_example_method :xspecify, :skip => 'Temporarily skipped with xspecify'
166
+ # Shortcut to define an example with `:skip => true`
167
+ # @see example
168
+ define_example_method :skip, :skip => true
169
+ # Shortcut to define an example with `:pending => true`
170
+ # @see example
171
+ define_example_method :pending, :pending => true
172
+
173
+ # @!endgroup
174
+
175
+ # @!group Defining Example Groups
88
176
 
89
- # This will fail if no block is provided, which is effectively the
90
- # same as failing the example so it will be marked correctly as
91
- # pending.
92
- callback = Proc.new { pending(reason); instance_exec(&block) }
177
+ # @private
178
+ # @macro [attach] alias_example_group_to
179
+ # @!scope class
180
+ # @param name [String] The example group doc string
181
+ # @param metadata [Hash] Additional metadata to attach to the example group
182
+ # @yield The example group definition
183
+ #
184
+ # Generates a subclass of this example group which inherits
185
+ # everything except the examples themselves.
186
+ #
187
+ # @example
188
+ #
189
+ # RSpec.describe "something" do # << This describe method is defined in
190
+ # # << RSpec::Core::DSL, included in the
191
+ # # << global namespace (optional)
192
+ # before do
193
+ # do_something_before
194
+ # end
195
+ #
196
+ # let(:thing) { Thing.new }
197
+ #
198
+ # $1 "attribute (of something)" do
199
+ # # examples in the group get the before hook
200
+ # # declared above, and can access `thing`
201
+ # end
202
+ # end
203
+ #
204
+ # @see DSL#describe
205
+ def self.define_example_group_method(name, metadata={})
206
+ define_singleton_method(name) do |*args, &example_group_block|
207
+ thread_data = RSpec.thread_local_metadata
208
+ top_level = self == ExampleGroup
209
+
210
+ if top_level
211
+ if thread_data[:in_example_group]
212
+ raise "Creating an isolated context from within a context is " +
213
+ "not allowed. Change `RSpec.#{name}` to `#{name}` or " +
214
+ "move this to a top-level scope."
215
+ end
93
216
 
94
- return options, callback
95
- end
217
+ thread_data[:in_example_group] = true
218
+ end
96
219
 
97
- # Defines an example within a group.
98
- # @example
99
- # example do
100
- # end
101
- #
102
- # example "does something" do
103
- # end
104
- #
105
- # example "does something", :with => 'additional metadata' do
106
- # end
107
- #
108
- # example "does something" do |ex|
109
- # # ex is the Example object that evals this block
110
- # end
111
- define_example_method :example
112
- # Defines an example within a group.
113
- # @example
114
- define_example_method :it
115
- # Defines an example within a group.
116
- # This is here primarily for backward compatibility with early versions
117
- # of RSpec which used `context` and `specify` instead of `describe` and
118
- # `it`.
119
- define_example_method :specify
120
-
121
- # Shortcut to define an example with `:focus` => true
122
- # @see example
123
- define_example_method :focus, :focused => true, :focus => true
124
- # Shortcut to define an example with `:focus` => true
125
- # @see example
126
- define_example_method :focused, :focused => true, :focus => true
127
- # Shortcut to define an example with `:focus` => true
128
- # @see example
129
- define_example_method :fit, :focused => true, :focus => true
130
-
131
- # Shortcut to define an example with :skip => 'Temporarily skipped with xexample'
132
- # @see example
133
- define_example_method :xexample, :skip => 'Temporarily skipped with xexample'
134
- # Shortcut to define an example with :skip => 'Temporarily skipped with xit'
135
- # @see example
136
- define_example_method :xit, :skip => 'Temporarily skipped with xit'
137
- # Shortcut to define an example with :skip => 'Temporarily skipped with xspecify'
138
- # @see example
139
- define_example_method :xspecify, :skip => 'Temporarily skipped with xspecify'
140
- # Shortcut to define an example with :skip => true
141
- # @see example
142
- define_example_method :skip, :skip => true
143
- # Shortcut to define an example with :pending => true
144
- # @see example
145
- define_example_method :pending, :pending => true
146
-
147
- # Works like `alias_method :name, :example` with the added benefit of
148
- # assigning default metadata to the generated example.
149
- #
150
- # @note Use with caution. This extends the language used in your
151
- # specs, but does not add any additional documentation. We use this
152
- # in rspec to define methods like `focus` and `xit`, but we also add
153
- # docs for those methods.
154
- def alias_example_to name, extra={}
155
- (class << self; self; end).define_example_method name, extra
156
- end
220
+ begin
157
221
 
158
- # @private
159
- # @macro [attach] alias_example_group_to
160
- # @scope class
161
- # @param [String] docstring The example group doc string
162
- # @param [Hash] metadata Additional metadata to attach to the example group
163
- # @yield The example group definition
164
- def alias_example_group_to(name, metadata={})
165
- (class << self; self; end).__send__(:define_method, name) do |*args, &block|
222
+ description = args.shift
166
223
  combined_metadata = metadata.dup
167
224
  combined_metadata.merge!(args.pop) if args.last.is_a? Hash
168
225
  args << combined_metadata
169
- example_group(*args, &block)
170
- end
171
-
172
- RSpec::Core::DSL.expose_example_group_alias(name)
173
- end
174
226
 
175
- # @private
176
- # @macro [attach] define_nested_shared_group_method
177
- #
178
- # @see SharedExampleGroup
179
- def self.define_nested_shared_group_method(new_name, report_label="it should behave like")
180
- define_method(new_name) do |name, *args, &customization_block|
181
- group = example_group("#{report_label} #{name}") do
182
- find_and_eval_shared("examples", name, *args, &customization_block)
227
+ subclass(self, description, args, &example_group_block).tap do |child|
228
+ children << child
183
229
  end
184
- group.metadata[:shared_group_name] = name
185
- group
230
+
231
+ ensure
232
+ thread_data.delete(:in_example_group) if top_level
186
233
  end
187
234
  end
188
235
 
189
- # Generates a nested example group and includes the shared content
190
- # mapped to `name` in the nested group.
191
- define_nested_shared_group_method :it_behaves_like, "behaves like"
192
- # Generates a nested example group and includes the shared content
193
- # mapped to `name` in the nested group.
194
- define_nested_shared_group_method :it_should_behave_like
195
-
196
- # Works like `alias_method :name, :it_behaves_like` with the added
197
- # benefit of assigning default metadata to the generated example.
198
- #
199
- # @note Use with caution. This extends the language used in your
200
- # specs, but does not add any additional documentation. We use this
201
- # in rspec to define `it_should_behave_like` (for backward
202
- # compatibility), but we also add docs for that method.
203
- def alias_it_behaves_like_to name, *args, &block
204
- (class << self; self; end).define_nested_shared_group_method name, *args, &block
236
+ RSpec::Core::DSL.expose_example_group_alias(name)
237
+ end
238
+
239
+ define_example_group_method :example_group
240
+
241
+ # An alias of `example_group`. Generally used when grouping
242
+ # examples by a thing you are describing (e.g. an object, class or method).
243
+ # @see example_group
244
+ define_example_group_method :describe
245
+
246
+ # An alias of `example_group`. Generally used when grouping examples
247
+ # contextually (e.g. "with xyz", "when xyz" or "if xyz").
248
+ # @see example_group
249
+ define_example_group_method :context
250
+
251
+ # Shortcut to temporarily make an example group skipped.
252
+ # @see example_group
253
+ define_example_group_method :xdescribe, :skip => "Temporarily skipped with xdescribe"
254
+
255
+ # Shortcut to temporarily make an example group skipped.
256
+ # @see example_group
257
+ define_example_group_method :xcontext, :skip => "Temporarily skipped with xcontext"
258
+
259
+ # Shortcut to define an example group with `:focus => true`.
260
+ # @see example_group
261
+ define_example_group_method :fdescribe, :focus => true
262
+
263
+ # Shortcut to define an example group with `:focus => true`.
264
+ # @see example_group
265
+ define_example_group_method :fcontext, :focus => true
266
+
267
+ # @!endgroup
268
+
269
+ # @!group Including Shared Example Groups
270
+
271
+ # @private
272
+ # @macro [attach] define_nested_shared_group_method
273
+ # @!scope class
274
+ #
275
+ # @see SharedExampleGroup
276
+ def self.define_nested_shared_group_method(new_name, report_label="it should behave like")
277
+ define_singleton_method(new_name) do |name, *args, &customization_block|
278
+ # Pass :caller so the :location metadata is set properly...
279
+ # otherwise, it'll be set to the next line because that's
280
+ # the block's source_location.
281
+ group = example_group("#{report_label} #{name}", :caller => caller) do
282
+ find_and_eval_shared("examples", name, *args, &customization_block)
283
+ end
284
+ group.metadata[:shared_group_name] = name
285
+ group
205
286
  end
206
287
  end
207
288
 
289
+ # Generates a nested example group and includes the shared content
290
+ # mapped to `name` in the nested group.
291
+ define_nested_shared_group_method :it_behaves_like, "behaves like"
292
+ # Generates a nested example group and includes the shared content
293
+ # mapped to `name` in the nested group.
294
+ define_nested_shared_group_method :it_should_behave_like
295
+
208
296
  # Includes shared content mapped to `name` directly in the group in which
209
297
  # it is declared, as opposed to `it_behaves_like`, which creates a nested
210
298
  # group. If given a block, that block is also eval'd in the current context.
@@ -225,110 +313,68 @@ module RSpec
225
313
 
226
314
  # @private
227
315
  def self.find_and_eval_shared(label, name, *args, &customization_block)
228
- raise ArgumentError, "Could not find shared #{label} #{name.inspect}" unless
229
- shared_block = shared_example_groups[name]
316
+ unless shared_block = RSpec.world.shared_example_group_registry.find(parent_groups, name)
317
+ raise ArgumentError, "Could not find shared #{label} #{name.inspect}"
318
+ end
230
319
 
231
320
  module_exec(*args, &shared_block)
232
- module_eval(&customization_block) if customization_block
321
+ module_exec(&customization_block) if customization_block
233
322
  end
234
323
 
235
- # @private
236
- def self.examples
237
- @examples ||= []
238
- end
324
+ # @!endgroup
239
325
 
240
326
  # @private
241
- def self.filtered_examples
242
- world.filtered_examples[self]
243
- end
327
+ def self.subclass(parent, description, args, &example_group_block)
328
+ subclass = Class.new(parent)
329
+ subclass.set_it_up(description, *args, &example_group_block)
330
+ ExampleGroups.assign_const(subclass)
331
+ subclass.module_exec(&example_group_block) if example_group_block
244
332
 
245
- # @private
246
- def self.descendant_filtered_examples
247
- @descendant_filtered_examples ||= filtered_examples + children.inject([]){|l,c| l + c.descendant_filtered_examples}
248
- end
333
+ # The LetDefinitions module must be included _after_ other modules
334
+ # to ensure that it takes precedence when there are name collisions.
335
+ # Thus, we delay including it until after the example group block
336
+ # has been eval'd.
337
+ MemoizedHelpers.define_helpers_on(subclass)
249
338
 
250
- # The [Metadata](Metadata) object associated with this group.
251
- # @see Metadata
252
- def self.metadata
253
- @metadata if defined?(@metadata)
339
+ subclass
254
340
  end
255
341
 
256
342
  # @private
257
- # @return [Metadata] belonging to the parent of a nested {ExampleGroup}
258
- def self.superclass_metadata
259
- @superclass_metadata ||= self.superclass.respond_to?(:metadata) ? self.superclass.metadata : nil
260
- end
261
-
262
- # Generates a subclass of this example group which inherits
263
- # everything except the examples themselves.
264
- #
265
- # ## Examples
266
- #
267
- # describe "something" do # << This describe method is defined in
268
- # # << RSpec::Core::DSL, included in the
269
- # # << global namespace (optional)
270
- # before do
271
- # do_something_before
272
- # end
273
- #
274
- # let(:thing) { Thing.new }
275
- #
276
- # describe "attribute (of something)" do
277
- # # examples in the group get the before hook
278
- # # declared above, and can access `thing`
279
- # end
280
- # end
281
- #
282
- # @see DSL#describe
283
- def self.example_group(*args, &example_group_block)
284
- args << {} unless args.last.is_a?(Hash)
285
- args.last.update(:example_group_block => example_group_block)
286
-
287
- child = subclass(self, args, &example_group_block)
288
- children << child
289
- child
290
- end
291
-
292
- # An alias of `example_group`. Generally used when grouping
293
- # examples by a thing you are describing (e.g. an object, class or method).
294
- # @see example_group
295
- alias_example_group_to :describe
296
-
297
- # An alias of `example_group`. Generally used when grouping examples
298
- # contextually.
299
- # @see example_group
300
- alias_example_group_to :context
301
-
302
- # Shortcut to temporarily make an example group pending.
303
- # @see example_group
304
- alias_example_group_to :xdescribe, :skip => "Temporarily skipped with xdescribe"
343
+ def self.set_it_up(*args, &example_group_block)
344
+ # Ruby 1.9 has a bug that can lead to infinite recursion and a
345
+ # SystemStackError if you include a module in a superclass after
346
+ # including it in a subclass: https://gist.github.com/845896
347
+ # To prevent this, we must include any modules in RSpec::Core::ExampleGroup
348
+ # before users create example groups and have a chance to include
349
+ # the same module in a subclass of RSpec::Core::ExampleGroup.
350
+ # So we need to configure example groups here.
351
+ ensure_example_groups_are_configured
305
352
 
306
- # Shortcut to temporarily make an example group pending.
307
- # @see example_group
308
- alias_example_group_to :xcontext, :skip => "Temporarily skipped with xcontext"
353
+ description = args.shift
354
+ user_metadata = Metadata.build_hash_from(args)
355
+ args.unshift(description)
309
356
 
310
- # Shortcut to define an example group with `:focus` => true
311
- # @see example_group
312
- alias_example_group_to :fdescribe, :focus => true, :focused => true
357
+ @metadata = Metadata::ExampleGroupHash.create(
358
+ superclass_metadata || {}, user_metadata, *args, &example_group_block
359
+ )
313
360
 
314
- # Shortcut to define an example group with `:focus` => true
315
- # @see example_group
316
- alias_example_group_to :fcontext, :focus => true, :focused => true
361
+ hooks.register_globals(self, RSpec.configuration.hooks)
362
+ RSpec.world.configure_group(self)
363
+ end
317
364
 
318
365
  # @private
319
- def self.subclass(parent, args, &example_group_block)
320
- subclass = Class.new(parent)
321
- subclass.set_it_up(*args)
322
- ExampleGroups.assign_const(subclass)
323
- subclass.module_eval(&example_group_block) if example_group_block
366
+ def self.examples
367
+ @examples ||= []
368
+ end
324
369
 
325
- # The LetDefinitions module must be included _after_ other modules
326
- # to ensure that it takes precendence when there are name collisions.
327
- # Thus, we delay including it until after the example group block
328
- # has been eval'd.
329
- MemoizedHelpers.define_helpers_on(subclass)
370
+ # @private
371
+ def self.filtered_examples
372
+ RSpec.world.filtered_examples[self]
373
+ end
330
374
 
331
- subclass
375
+ # @private
376
+ def self.descendant_filtered_examples
377
+ @descendant_filtered_examples ||= filtered_examples + children.inject([]){|l,c| l + c.descendant_filtered_examples}
332
378
  end
333
379
 
334
380
  # @private
@@ -361,84 +407,64 @@ module RSpec
361
407
  end
362
408
 
363
409
  # @private
364
- def self.set_it_up(*args)
365
- # Ruby 1.9 has a bug that can lead to infinite recursion and a
366
- # SystemStackError if you include a module in a superclass after
367
- # including it in a subclass: https://gist.github.com/845896
368
- # To prevent this, we must include any modules in RSpec::Core::ExampleGroup
369
- # before users create example groups and have a chance to include
370
- # the same module in a subclass of RSpec::Core::ExampleGroup.
371
- # So we need to configure example groups here.
372
- ensure_example_groups_are_configured
373
-
374
- symbol_description = args.shift if args.first.is_a?(Symbol)
375
- args << Metadata.build_hash_from(args)
376
- args.unshift(symbol_description) if symbol_description
377
- @metadata = RSpec::Core::Metadata.new(superclass_metadata).process(*args)
378
- @order = nil
379
- hooks.register_globals(self, RSpec.configuration.hooks)
380
- world.configure_group(self)
381
- end
382
-
383
- # @private
384
- def self.before_all_ivars
385
- @before_all_ivars ||= {}
410
+ def self.before_context_ivars
411
+ @before_context_ivars ||= {}
386
412
  end
387
413
 
388
414
  # @private
389
- def self.store_before_all_ivars(example_group_instance)
415
+ def self.store_before_context_ivars(example_group_instance)
390
416
  return if example_group_instance.instance_variables.empty?
391
417
 
392
418
  example_group_instance.instance_variables.each { |ivar|
393
- before_all_ivars[ivar] = example_group_instance.instance_variable_get(ivar)
419
+ before_context_ivars[ivar] = example_group_instance.instance_variable_get(ivar)
394
420
  }
395
421
  end
396
422
 
397
423
  # @private
398
- def self.run_before_all_hooks(example_group_instance)
424
+ def self.run_before_context_hooks(example_group_instance)
399
425
  return if descendant_filtered_examples.empty?
400
426
  begin
401
- set_ivars(example_group_instance, superclass.before_all_ivars)
427
+ set_ivars(example_group_instance, superclass.before_context_ivars)
402
428
 
403
- AllHookMemoizedHash::Before.isolate_for_all_hook(example_group_instance) do
404
- hooks.run(:before, :all, example_group_instance)
429
+ ContextHookMemoizedHash::Before.isolate_for_context_hook(example_group_instance) do
430
+ hooks.run(:before, :context, example_group_instance)
405
431
  end
406
432
  ensure
407
- store_before_all_ivars(example_group_instance)
433
+ store_before_context_ivars(example_group_instance)
408
434
  end
409
435
  end
410
436
 
411
437
  # @private
412
- def self.run_after_all_hooks(example_group_instance)
438
+ def self.run_after_context_hooks(example_group_instance)
413
439
  return if descendant_filtered_examples.empty?
414
- set_ivars(example_group_instance, before_all_ivars)
440
+ set_ivars(example_group_instance, before_context_ivars)
415
441
 
416
- AllHookMemoizedHash::After.isolate_for_all_hook(example_group_instance) do
417
- hooks.run(:after, :all, example_group_instance)
442
+ ContextHookMemoizedHash::After.isolate_for_context_hook(example_group_instance) do
443
+ hooks.run(:after, :context, example_group_instance)
418
444
  end
419
445
  end
420
446
 
421
447
  # Runs all the examples in this group
422
448
  def self.run(reporter)
423
- if RSpec.wants_to_quit
424
- RSpec.clear_remaining_example_groups if top_level?
449
+ if RSpec.world.wants_to_quit
450
+ RSpec.world.clear_remaining_example_groups if top_level?
425
451
  return
426
452
  end
427
453
  reporter.example_group_started(self)
428
454
 
429
455
  begin
430
- run_before_all_hooks(new)
456
+ run_before_context_hooks(new)
431
457
  result_for_this_group = run_examples(reporter)
432
458
  results_for_descendants = ordering_strategy.order(children).map { |child| child.run(reporter) }.all?
433
459
  result_for_this_group && results_for_descendants
434
460
  rescue Pending::SkipDeclaredInExample => ex
435
461
  for_filtered_examples(reporter) {|example| example.skip_with_exception(reporter, ex) }
436
462
  rescue Exception => ex
437
- RSpec.wants_to_quit = true if fail_fast?
463
+ RSpec.world.wants_to_quit = true if fail_fast?
438
464
  for_filtered_examples(reporter) {|example| example.fail_with_exception(reporter, ex) }
439
465
  ensure
440
- run_after_all_hooks(new)
441
- before_all_ivars.clear
466
+ run_after_context_hooks(new)
467
+ before_context_ivars.clear
442
468
  reporter.example_group_finished(self)
443
469
  end
444
470
  end
@@ -452,7 +478,7 @@ module RSpec
452
478
  warn <<-WARNING.gsub(/^ +\|/, '')
453
479
  |WARNING: Ignoring unknown ordering specified using `:order => #{order.inspect}` metadata.
454
480
  | Falling back to configured global ordering.
455
- | Unrecognized ordering specified at: #{metadata[:example_group][:location]}
481
+ | Unrecognized ordering specified at: #{location}
456
482
  WARNING
457
483
 
458
484
  registry.fetch(:global)
@@ -462,11 +488,11 @@ module RSpec
462
488
  # @private
463
489
  def self.run_examples(reporter)
464
490
  ordering_strategy.order(filtered_examples).map do |example|
465
- next if RSpec.wants_to_quit
491
+ next if RSpec.world.wants_to_quit
466
492
  instance = new
467
- set_ivars(instance, before_all_ivars)
493
+ set_ivars(instance, before_context_ivars)
468
494
  succeeded = example.run(instance, reporter)
469
- RSpec.wants_to_quit = true if fail_fast? && !succeeded
495
+ RSpec.world.wants_to_quit = true if fail_fast? && !succeeded
470
496
  succeeded
471
497
  end.all?
472
498
  end
@@ -490,17 +516,17 @@ module RSpec
490
516
 
491
517
  # @private
492
518
  def self.any_apply?(filters)
493
- metadata.any_apply?(filters)
519
+ MetadataFilter.any_apply?(filters, metadata)
494
520
  end
495
521
 
496
522
  # @private
497
523
  def self.all_apply?(filters)
498
- metadata.all_apply?(filters)
524
+ MetadataFilter.all_apply?(filters, metadata)
499
525
  end
500
526
 
501
527
  # @private
502
528
  def self.declaration_line_numbers
503
- @declaration_line_numbers ||= [metadata[:example_group][:line_number]] +
529
+ @declaration_line_numbers ||= [metadata[:line_number]] +
504
530
  examples.collect {|e| e.metadata[:line_number]} +
505
531
  children.inject([]) {|l,c| l + c.declaration_line_numbers}
506
532
  end
@@ -515,37 +541,39 @@ module RSpec
515
541
  ivars.each {|name, value| instance.instance_variable_set(name, value)}
516
542
  end
517
543
 
518
- # Returns the class or module passed to the `describe` method (or alias).
519
- # Returns nil if the subject is not a class or module.
520
- # @example
521
- # describe Thing do
522
- # it "does something" do
523
- # described_class == Thing
524
- # end
525
- # end
526
- #
527
- #
528
- def described_class
529
- self.class.described_class
530
- end
531
-
532
544
  # @private
533
- # instance_evals the block, capturing and reporting an exception if
534
- # raised
535
- def instance_exec_with_rescue(example, context = nil, &hook)
536
- begin
537
- instance_exec(example, &hook)
538
- rescue Exception => e
539
- if RSpec.current_example
540
- RSpec.current_example.set_exception(e, context)
541
- else
542
- raise
543
- end
545
+ def self.pending_metadata_and_block_for(options, block)
546
+ if String === options[:pending]
547
+ reason = options[:pending]
548
+ else
549
+ options[:pending] = true
550
+ reason = RSpec::Core::Pending::NO_REASON_GIVEN
544
551
  end
552
+
553
+ # Assign :caller so that the callback's source_location isn't used
554
+ # as the example location.
555
+ options[:caller] ||= Metadata.backtrace_from(block)
556
+
557
+ # This will fail if no block is provided, which is effectively the
558
+ # same as failing the example so it will be marked correctly as
559
+ # pending.
560
+ callback = Proc.new { pending(reason); instance_exec(&block) }
561
+
562
+ return options, callback
563
+ end
564
+ end
565
+
566
+ # @private
567
+ # Unnamed example group used by `SuiteHookContext`.
568
+ class AnonymousExampleGroup < ExampleGroup
569
+ def self.metadata
570
+ {}
545
571
  end
546
572
  end
547
573
  end
548
574
 
575
+ # @private
576
+ #
549
577
  # Namespace for the example group subclasses generated by top-level `describe`.
550
578
  module ExampleGroups
551
579
  def self.assign_const(group)