rspec-core 2.12.2 → 2.13.0

Sign up to get free protection for your applications and to get access to all the features.
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