rspec-core 3.0.0.beta2 → 3.0.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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)