rspec-core 2.12.2 → 2.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. data/Changelog.md +31 -0
  2. data/README.md +11 -10
  3. data/features/command_line/example_name_option.feature +6 -10
  4. data/features/command_line/tag.feature +15 -8
  5. data/features/configuration/backtrace_clean_patterns.feature +102 -0
  6. data/features/configuration/failure_exit_code.feature +36 -0
  7. data/features/configuration/order_and_seed.feature +3 -0
  8. data/features/configuration/output_stream.feature +24 -0
  9. data/features/configuration/pattern.feature +30 -0
  10. data/features/configuration/profile.feature +163 -0
  11. data/features/configuration/run_all_when_everything_filtered.feature +60 -0
  12. data/features/configuration/show_failures_in_pending_blocks.feature +61 -0
  13. data/features/configuration/treat_symbols_as_metadata_keys_with_true_values.feature +52 -0
  14. data/features/filtering/exclusion_filters.feature +1 -2
  15. data/features/formatters/configurable_colors.feature +31 -0
  16. data/features/step_definitions/additional_cli_steps.rb +21 -0
  17. data/features/subject/explicit_subject.feature +19 -0
  18. data/lib/autotest/rspec2.rb +1 -1
  19. data/lib/rspec/core.rb +1 -2
  20. data/lib/rspec/core/configuration.rb +33 -3
  21. data/lib/rspec/core/configuration_options.rb +5 -5
  22. data/lib/rspec/core/deprecation.rb +1 -1
  23. data/lib/rspec/core/example.rb +2 -2
  24. data/lib/rspec/core/example_group.rb +1 -3
  25. data/lib/rspec/core/formatters/base_text_formatter.rb +93 -27
  26. data/lib/rspec/core/formatters/documentation_formatter.rb +3 -3
  27. data/lib/rspec/core/formatters/progress_formatter.rb +3 -3
  28. data/lib/rspec/core/memoized_helpers.rb +425 -0
  29. data/lib/rspec/core/metadata.rb +6 -2
  30. data/lib/rspec/core/option_parser.rb +8 -2
  31. data/lib/rspec/core/pending.rb +7 -0
  32. data/lib/rspec/core/shared_context.rb +1 -1
  33. data/lib/rspec/core/version.rb +1 -1
  34. data/spec/autotest/failed_results_re_spec.rb +4 -4
  35. data/spec/autotest/rspec_spec.rb +25 -20
  36. data/spec/command_line/order_spec.rb +21 -21
  37. data/spec/rspec/core/command_line_spec.rb +6 -6
  38. data/spec/rspec/core/configuration_options_spec.rb +86 -72
  39. data/spec/rspec/core/configuration_spec.rb +161 -156
  40. data/spec/rspec/core/deprecations_spec.rb +4 -4
  41. data/spec/rspec/core/drb_command_line_spec.rb +9 -9
  42. data/spec/rspec/core/drb_options_spec.rb +46 -33
  43. data/spec/rspec/core/dsl_spec.rb +3 -3
  44. data/spec/rspec/core/example_group_spec.rb +156 -124
  45. data/spec/rspec/core/example_spec.rb +68 -52
  46. data/spec/rspec/core/filter_manager_spec.rb +36 -36
  47. data/spec/rspec/core/formatters/base_formatter_spec.rb +9 -9
  48. data/spec/rspec/core/formatters/base_text_formatter_spec.rb +104 -42
  49. data/spec/rspec/core/formatters/documentation_formatter_spec.rb +4 -4
  50. data/spec/rspec/core/formatters/helpers_spec.rb +13 -13
  51. data/spec/rspec/core/formatters/html_formatted-1.8.7-jruby.html +5 -17
  52. data/spec/rspec/core/formatters/html_formatted-1.8.7-rbx.html +159 -44
  53. data/spec/rspec/core/formatters/html_formatted-1.8.7.html +14 -14
  54. data/spec/rspec/core/formatters/html_formatted-1.9.2.html +20 -20
  55. data/spec/rspec/core/formatters/html_formatted-1.9.3-jruby.html +5 -5
  56. data/spec/rspec/core/formatters/html_formatted-1.9.3-rbx.html +159 -44
  57. data/spec/rspec/core/formatters/html_formatted-1.9.3.html +20 -20
  58. data/spec/rspec/core/formatters/{html_formatted-1.9.2-jruby.html → html_formatted-2.0.0.html} +24 -18
  59. data/spec/rspec/core/formatters/html_formatter_spec.rb +9 -5
  60. data/spec/rspec/core/formatters/json_formatter_spec.rb +9 -9
  61. data/spec/rspec/core/formatters/progress_formatter_spec.rb +4 -4
  62. data/spec/rspec/core/formatters/snippet_extractor_spec.rb +3 -3
  63. data/spec/rspec/core/formatters/text_mate_formatted-1.8.7-jruby.html +5 -17
  64. data/spec/rspec/core/formatters/text_mate_formatted-1.8.7-rbx.html +159 -44
  65. data/spec/rspec/core/formatters/text_mate_formatted-1.8.7.html +16 -16
  66. data/spec/rspec/core/formatters/text_mate_formatted-1.9.2.html +23 -23
  67. data/spec/rspec/core/formatters/text_mate_formatted-1.9.3-jruby.html +5 -17
  68. data/spec/rspec/core/formatters/text_mate_formatted-1.9.3-rbx.html +159 -44
  69. data/spec/rspec/core/formatters/text_mate_formatted-1.9.3.html +23 -23
  70. data/spec/rspec/core/formatters/{text_mate_formatted-1.9.2-jruby.html → text_mate_formatted-2.0.0.html} +25 -19
  71. data/spec/rspec/core/formatters/text_mate_formatter_spec.rb +8 -4
  72. data/spec/rspec/core/hooks_filtering_spec.rb +16 -16
  73. data/spec/rspec/core/hooks_spec.rb +11 -11
  74. data/spec/rspec/core/kernel_extensions_spec.rb +1 -1
  75. data/spec/rspec/core/memoized_helpers_spec.rb +458 -0
  76. data/spec/rspec/core/metadata_spec.rb +74 -74
  77. data/spec/rspec/core/option_parser_spec.rb +27 -27
  78. data/spec/rspec/core/pending_example_spec.rb +32 -32
  79. data/spec/rspec/core/project_initializer_spec.rb +8 -8
  80. data/spec/rspec/core/rake_task_spec.rb +16 -16
  81. data/spec/rspec/core/reporter_spec.rb +3 -3
  82. data/spec/rspec/core/resources/formatter_specs.rb +4 -4
  83. data/spec/rspec/core/ruby_project_spec.rb +4 -2
  84. data/spec/rspec/core/shared_context_spec.rb +34 -7
  85. data/spec/rspec/core/shared_example_group_spec.rb +14 -14
  86. data/spec/rspec/core/world_spec.rb +9 -9
  87. data/spec/rspec/core_spec.rb +5 -5
  88. data/spec/spec_helper.rb +4 -0
  89. data/spec/support/shared_example_groups.rb +4 -4
  90. data/spec/support/spec_files.rb +2 -2
  91. metadata +158 -150
  92. data/lib/rspec/core/let.rb +0 -110
  93. data/lib/rspec/core/subject.rb +0 -223
  94. data/spec/rspec/core/let_spec.rb +0 -55
  95. data/spec/rspec/core/subject_spec.rb +0 -255
@@ -38,7 +38,7 @@ module RSpec
38
38
  end
39
39
 
40
40
  def failure_output(example, exception)
41
- red("#{current_indentation}#{example.description.strip} (FAILED - #{next_failure_index})")
41
+ failure_color("#{current_indentation}#{example.description.strip} (FAILED - #{next_failure_index})")
42
42
  end
43
43
 
44
44
  def next_failure_index
@@ -47,11 +47,11 @@ module RSpec
47
47
  end
48
48
 
49
49
  def passed_output(example)
50
- green("#{current_indentation}#{example.description.strip}")
50
+ success_color("#{current_indentation}#{example.description.strip}")
51
51
  end
52
52
 
53
53
  def pending_output(example, message)
54
- yellow("#{current_indentation}#{example.description.strip} (PENDING: #{message})")
54
+ pending_color("#{current_indentation}#{example.description.strip} (PENDING: #{message})")
55
55
  end
56
56
 
57
57
  def current_indentation
@@ -7,17 +7,17 @@ module RSpec
7
7
 
8
8
  def example_passed(example)
9
9
  super(example)
10
- output.print green('.')
10
+ output.print success_color('.')
11
11
  end
12
12
 
13
13
  def example_pending(example)
14
14
  super(example)
15
- output.print yellow('*')
15
+ output.print pending_color('*')
16
16
  end
17
17
 
18
18
  def example_failed(example)
19
19
  super(example)
20
- output.print red('F')
20
+ output.print failure_color('F')
21
21
  end
22
22
 
23
23
  def start_dump
@@ -0,0 +1,425 @@
1
+ module RSpec
2
+ module Core
3
+ module MemoizedHelpers
4
+ # @note `subject` was contributed by Joe Ferris to support the one-liner
5
+ # syntax embraced by shoulda matchers:
6
+ #
7
+ # describe Widget do
8
+ # it { should validate_presence_of(:name) }
9
+ # end
10
+ #
11
+ # While the examples below demonstrate how to use `subject`
12
+ # explicitly in examples, we recommend that you define a method with
13
+ # an intention revealing name instead.
14
+ #
15
+ # @example
16
+ #
17
+ # # explicit declaration of subject
18
+ # describe Person do
19
+ # subject { Person.new(:birthdate => 19.years.ago) }
20
+ # it "should be eligible to vote" do
21
+ # subject.should be_eligible_to_vote
22
+ # # ^ ^ explicit reference to subject not recommended
23
+ # end
24
+ # end
25
+ #
26
+ # # implicit subject => { Person.new }
27
+ # describe Person do
28
+ # it "should be eligible to vote" do
29
+ # subject.should be_eligible_to_vote
30
+ # # ^ ^ explicit reference to subject not recommended
31
+ # end
32
+ # end
33
+ #
34
+ # # one-liner syntax - should is invoked on subject
35
+ # describe Person do
36
+ # it { should be_eligible_to_vote }
37
+ # end
38
+ #
39
+ # @see #should
40
+ def subject
41
+ raise NotImplementedError, 'This definition is here for documentation purposes only'
42
+ ' - it is overriden anyway below when this module gets included.'
43
+ end
44
+
45
+ # When `should` is called with no explicit receiver, the call is
46
+ # delegated to the object returned by `subject`. Combined with an
47
+ # implicit subject this supports very concise expressions.
48
+ #
49
+ # @example
50
+ #
51
+ # describe Person do
52
+ # it { should be_eligible_to_vote }
53
+ # end
54
+ #
55
+ # @see #subject
56
+ def should(matcher=nil, message=nil)
57
+ RSpec::Expectations::PositiveExpectationHandler.handle_matcher(subject, matcher, message)
58
+ end
59
+
60
+ # Just like `should`, `should_not` delegates to the subject (implicit or
61
+ # explicit) of the example group.
62
+ #
63
+ # @example
64
+ #
65
+ # describe Person do
66
+ # it { should_not be_eligible_to_vote }
67
+ # end
68
+ #
69
+ # @see #subject
70
+ def should_not(matcher=nil, message=nil)
71
+ RSpec::Expectations::NegativeExpectationHandler.handle_matcher(subject, matcher, message)
72
+ end
73
+
74
+ private
75
+
76
+ # @private
77
+ def __memoized
78
+ @__memoized ||= {}
79
+ end
80
+
81
+ def self.included(mod)
82
+ mod.extend(ClassMethods)
83
+
84
+ # This logic defines an implicit subject
85
+ mod.subject do
86
+ described = described_class || self.class.description
87
+ Class === described ? described.new : described
88
+ end
89
+ end
90
+
91
+ module ClassMethods
92
+ # Generates a method whose return value is memoized after the first
93
+ # call. Useful for reducing duplication between examples that assign
94
+ # values to the same local variable.
95
+ #
96
+ # @note `let` _can_ enhance readability when used sparingly (1,2, or
97
+ # maybe 3 declarations) in any given example group, but that can
98
+ # quickly degrade with overuse. YMMV.
99
+ #
100
+ # @note `let` uses an `||=` conditional that has the potential to
101
+ # behave in surprising ways in examples that spawn separate threads,
102
+ # though we have yet to see this in practice. You've been warned.
103
+ #
104
+ # @example
105
+ #
106
+ # describe Thing do
107
+ # let(:thing) { Thing.new }
108
+ #
109
+ # it "does something" do
110
+ # # first invocation, executes block, memoizes and returns result
111
+ # thing.do_something
112
+ #
113
+ # # second invocation, returns the memoized value
114
+ # thing.should be_something
115
+ # end
116
+ # end
117
+ def let(name, &block)
118
+ # We have to pass the block directly to `define_method` to
119
+ # allow it to use method constructs like `super` and `return`.
120
+ ::RSpec::Core::MemoizedHelpers.module_for(self).define_method(name, &block)
121
+
122
+ # Apply the memoization. The method has been defined in an ancestor
123
+ # module so we can use `super` here to get the value.
124
+ define_method(name) do
125
+ __memoized.fetch(name) { |k| __memoized[k] = super() }
126
+ end
127
+ end
128
+
129
+ # Just like `let`, except the block is invoked by an implicit `before`
130
+ # hook. This serves a dual purpose of setting up state and providing a
131
+ # memoized reference to that state.
132
+ #
133
+ # @example
134
+ #
135
+ # class Thing
136
+ # def self.count
137
+ # @count ||= 0
138
+ # end
139
+ #
140
+ # def self.count=(val)
141
+ # @count += val
142
+ # end
143
+ #
144
+ # def self.reset_count
145
+ # @count = 0
146
+ # end
147
+ #
148
+ # def initialize
149
+ # self.class.count += 1
150
+ # end
151
+ # end
152
+ #
153
+ # describe Thing do
154
+ # after(:each) { Thing.reset_count }
155
+ #
156
+ # context "using let" do
157
+ # let(:thing) { Thing.new }
158
+ #
159
+ # it "is not invoked implicitly" do
160
+ # Thing.count.should eq(0)
161
+ # end
162
+ #
163
+ # it "can be invoked explicitly" do
164
+ # thing
165
+ # Thing.count.should eq(1)
166
+ # end
167
+ # end
168
+ #
169
+ # context "using let!" do
170
+ # let!(:thing) { Thing.new }
171
+ #
172
+ # it "is invoked implicitly" do
173
+ # Thing.count.should eq(1)
174
+ # end
175
+ #
176
+ # it "returns memoized version on first invocation" do
177
+ # thing
178
+ # Thing.count.should eq(1)
179
+ # end
180
+ # end
181
+ # end
182
+ def let!(name, &block)
183
+ let(name, &block)
184
+ before { __send__(name) }
185
+ end
186
+
187
+ # Declares a `subject` for an example group which can then be the
188
+ # implicit receiver (through delegation) of calls to `should`.
189
+ #
190
+ # Given a `name`, defines a method with that name which returns the
191
+ # `subject`. This lets you declare the subject once and access it
192
+ # implicitly in one-liners and explicitly using an intention revealing
193
+ # name.
194
+ #
195
+ # @param [String,Symbol] name used to define an accessor with an
196
+ # intention revealing name
197
+ # @param block defines the value to be returned by `subject` in examples
198
+ #
199
+ # @example
200
+ #
201
+ # describe CheckingAccount, "with $50" do
202
+ # subject { CheckingAccount.new(Money.new(50, :USD)) }
203
+ # it { should have_a_balance_of(Money.new(50, :USD)) }
204
+ # it { should_not be_overdrawn }
205
+ # end
206
+ #
207
+ # describe CheckingAccount, "with a non-zero starting balance" do
208
+ # subject(:account) { CheckingAccount.new(Money.new(50, :USD)) }
209
+ # it { should_not be_overdrawn }
210
+ # it "has a balance equal to the starting balance" do
211
+ # account.balance.should eq(Money.new(50, :USD))
212
+ # end
213
+ # end
214
+ #
215
+ # @see MemoizedHelpers#should
216
+ def subject(name=nil, &block)
217
+ let(:subject, &block)
218
+ alias_method name, :subject if name
219
+ end
220
+
221
+ # Just like `subject`, except the block is invoked by an implicit `before`
222
+ # hook. This serves a dual purpose of setting up state and providing a
223
+ # memoized reference to that state.
224
+ #
225
+ # @example
226
+ #
227
+ # class Thing
228
+ # def self.count
229
+ # @count ||= 0
230
+ # end
231
+ #
232
+ # def self.count=(val)
233
+ # @count += val
234
+ # end
235
+ #
236
+ # def self.reset_count
237
+ # @count = 0
238
+ # end
239
+ #
240
+ # def initialize
241
+ # self.class.count += 1
242
+ # end
243
+ # end
244
+ #
245
+ # describe Thing do
246
+ # after(:each) { Thing.reset_count }
247
+ #
248
+ # context "using subject" do
249
+ # subject { Thing.new }
250
+ #
251
+ # it "is not invoked implicitly" do
252
+ # Thing.count.should eq(0)
253
+ # end
254
+ #
255
+ # it "can be invoked explicitly" do
256
+ # subject
257
+ # Thing.count.should eq(1)
258
+ # end
259
+ # end
260
+ #
261
+ # context "using subject!" do
262
+ # subject!(:thing) { Thing.new }
263
+ #
264
+ # it "is invoked implicitly" do
265
+ # Thing.count.should eq(1)
266
+ # end
267
+ #
268
+ # it "returns memoized version on first invocation" do
269
+ # subject
270
+ # Thing.count.should eq(1)
271
+ # end
272
+ # end
273
+ # end
274
+ def subject!(name=nil, &block)
275
+ subject(name, &block)
276
+ before { subject }
277
+ end
278
+
279
+ # Creates a nested example group named by the submitted `attribute`,
280
+ # and then generates an example using the submitted block.
281
+ #
282
+ # @example
283
+ #
284
+ # # This ...
285
+ # describe Array do
286
+ # its(:size) { should eq(0) }
287
+ # end
288
+ #
289
+ # # ... generates the same runtime structure as this:
290
+ # describe Array do
291
+ # describe "size" do
292
+ # it "should eq(0)" do
293
+ # subject.size.should eq(0)
294
+ # end
295
+ # end
296
+ # end
297
+ #
298
+ # The attribute can be a `Symbol` or a `String`. Given a `String`
299
+ # with dots, the result is as though you concatenated that `String`
300
+ # onto the subject in an expression.
301
+ #
302
+ # @example
303
+ #
304
+ # describe Person do
305
+ # subject do
306
+ # Person.new.tap do |person|
307
+ # person.phone_numbers << "555-1212"
308
+ # end
309
+ # end
310
+ #
311
+ # its("phone_numbers.first") { should eq("555-1212") }
312
+ # end
313
+ #
314
+ # When the subject is a `Hash`, you can refer to the Hash keys by
315
+ # specifying a `Symbol` or `String` in an array.
316
+ #
317
+ # @example
318
+ #
319
+ # describe "a configuration Hash" do
320
+ # subject do
321
+ # { :max_users => 3,
322
+ # 'admin' => :all_permissions }
323
+ # end
324
+ #
325
+ # its([:max_users]) { should eq(3) }
326
+ # its(['admin']) { should eq(:all_permissions) }
327
+ #
328
+ # # You can still access to its regular methods this way:
329
+ # its(:keys) { should include(:max_users) }
330
+ # its(:count) { should eq(2) }
331
+ # end
332
+ #
333
+ # Note that this method does not modify `subject` in any way, so if you
334
+ # refer to `subject` in `let` or `before` blocks, you're still
335
+ # referring to the outer subject.
336
+ #
337
+ # @example
338
+ #
339
+ # describe Person do
340
+ # subject { Person.new }
341
+ # before { subject.age = 25 }
342
+ # its(:age) { should eq(25) }
343
+ # end
344
+ def its(attribute, &block)
345
+ describe(attribute) do
346
+ if Array === attribute
347
+ let(:__its_subject) { subject[*attribute] }
348
+ else
349
+ let(:__its_subject) do
350
+ attribute_chain = attribute.to_s.split('.')
351
+ attribute_chain.inject(subject) do |inner_subject, attr|
352
+ inner_subject.send(attr)
353
+ end
354
+ end
355
+ end
356
+
357
+ def should(matcher=nil, message=nil)
358
+ RSpec::Expectations::PositiveExpectationHandler.handle_matcher(__its_subject, matcher, message)
359
+ end
360
+
361
+ def should_not(matcher=nil, message=nil)
362
+ RSpec::Expectations::NegativeExpectationHandler.handle_matcher(__its_subject, matcher, message)
363
+ end
364
+
365
+ example(&block)
366
+ end
367
+ end
368
+ end
369
+
370
+ # @api private
371
+ #
372
+ # Gets the LetDefinitions module. The module is mixed into
373
+ # the example group and is used to hold all let definitions.
374
+ # This is done so that the block passed to `let` can be
375
+ # forwarded directly on to `define_method`, so that all method
376
+ # constructs (including `super` and `return`) can be used in
377
+ # a `let` block.
378
+ #
379
+ # The memoization is provided by a method definition on the
380
+ # example group that supers to the LetDefinitions definition
381
+ # in order to get the value to memoize.
382
+ def self.module_for(example_group)
383
+ get_constant_or_yield(example_group, :LetDefinitions) do
384
+ # Expose `define_method` as a public method, so we can
385
+ # easily use it below.
386
+ mod = Module.new { public_class_method :define_method }
387
+ example_group.__send__(:include, mod)
388
+ example_group.const_set(:LetDefinitions, mod)
389
+ mod
390
+ end
391
+ end
392
+
393
+ if Module.method(:const_defined?).arity == 1 # for 1.8
394
+ # @api private
395
+ #
396
+ # Gets the named constant or yields.
397
+ # On 1.8, const_defined? / const_get do not take into
398
+ # account the inheritance hierarchy.
399
+ def self.get_constant_or_yield(example_group, name)
400
+ if example_group.const_defined?(name)
401
+ example_group.const_get(name)
402
+ else
403
+ yield
404
+ end
405
+ end
406
+ else
407
+ # @api private
408
+ #
409
+ # Gets the named constant or yields.
410
+ # On 1.9, const_defined? / const_get take into account the
411
+ # the inheritance by default, and accept an argument to
412
+ # disable this behavior. It's important that we don't
413
+ # consider inheritance here; each example group level that
414
+ # uses a `let` should get its own `LetDefinitions` module.
415
+ def self.get_constant_or_yield(example_group, name)
416
+ if example_group.const_defined?(name, (check_ancestors = false))
417
+ example_group.const_get(name, check_ancestors)
418
+ else
419
+ yield
420
+ end
421
+ end
422
+ end
423
+ end
424
+ end
425
+ end