rspec-core 3.7.0 → 3.9.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 (45) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/Changelog.md +80 -2
  5. data/README.md +16 -16
  6. data/lib/rspec/core.rb +1 -0
  7. data/lib/rspec/core/bisect/coordinator.rb +26 -30
  8. data/lib/rspec/core/bisect/example_minimizer.rb +12 -8
  9. data/lib/rspec/core/bisect/fork_runner.rb +134 -0
  10. data/lib/rspec/core/bisect/server.rb +5 -14
  11. data/lib/rspec/core/bisect/{runner.rb → shell_command.rb} +27 -70
  12. data/lib/rspec/core/bisect/shell_runner.rb +73 -0
  13. data/lib/rspec/core/bisect/utilities.rb +58 -0
  14. data/lib/rspec/core/configuration.rb +219 -62
  15. data/lib/rspec/core/configuration_options.rb +41 -4
  16. data/lib/rspec/core/did_you_mean.rb +46 -0
  17. data/lib/rspec/core/example.rb +8 -5
  18. data/lib/rspec/core/example_group.rb +8 -3
  19. data/lib/rspec/core/formatters.rb +13 -6
  20. data/lib/rspec/core/formatters/base_bisect_formatter.rb +45 -0
  21. data/lib/rspec/core/formatters/bisect_drb_formatter.rb +29 -0
  22. data/lib/rspec/core/formatters/bisect_progress_formatter.rb +29 -16
  23. data/lib/rspec/core/formatters/deprecation_formatter.rb +3 -1
  24. data/lib/rspec/core/formatters/documentation_formatter.rb +35 -3
  25. data/lib/rspec/core/formatters/exception_presenter.rb +13 -1
  26. data/lib/rspec/core/formatters/failure_list_formatter.rb +23 -0
  27. data/lib/rspec/core/formatters/html_printer.rb +0 -2
  28. data/lib/rspec/core/formatters/protocol.rb +17 -17
  29. data/lib/rspec/core/formatters/syntax_highlighter.rb +19 -19
  30. data/lib/rspec/core/hooks.rb +15 -9
  31. data/lib/rspec/core/invocations.rb +8 -6
  32. data/lib/rspec/core/memoized_helpers.rb +33 -14
  33. data/lib/rspec/core/metadata.rb +2 -3
  34. data/lib/rspec/core/option_parser.rb +8 -0
  35. data/lib/rspec/core/profiler.rb +3 -1
  36. data/lib/rspec/core/rake_task.rb +21 -1
  37. data/lib/rspec/core/reporter.rb +11 -6
  38. data/lib/rspec/core/runner.rb +25 -14
  39. data/lib/rspec/core/shared_example_group.rb +2 -4
  40. data/lib/rspec/core/shell_escape.rb +2 -2
  41. data/lib/rspec/core/version.rb +1 -1
  42. data/lib/rspec/core/world.rb +11 -0
  43. metadata +22 -13
  44. metadata.gz.sig +0 -0
  45. data/lib/rspec/core/formatters/bisect_formatter.rb +0 -69
@@ -81,7 +81,7 @@ module RSpec
81
81
 
82
82
  def fully_formatted_lines(failure_number, colorizer)
83
83
  lines = [
84
- description,
84
+ encoded_description(description),
85
85
  detail_formatter.call(example, colorizer),
86
86
  formatted_message_and_backtrace(colorizer),
87
87
  extra_detail_formatter.call(failure_number, colorizer),
@@ -244,6 +244,17 @@ module RSpec
244
244
  end
245
245
  end
246
246
 
247
+ if String.method_defined?(:encoding)
248
+ def encoded_description(description)
249
+ return if description.nil?
250
+ encoded_string(description)
251
+ end
252
+ else # for 1.8.7
253
+ def encoded_description(description)
254
+ description
255
+ end
256
+ end
257
+
247
258
  def exception_backtrace
248
259
  exception.backtrace || []
249
260
  end
@@ -379,6 +390,7 @@ module RSpec
379
390
  parent_bt[index] != child_bt[index]
380
391
  end
381
392
 
393
+ return child if index_before_first_common_frame.nil?
382
394
  return child if index_before_first_common_frame == -1
383
395
 
384
396
  child = child.dup
@@ -0,0 +1,23 @@
1
+ RSpec::Support.require_rspec_core "formatters/base_formatter"
2
+
3
+ module RSpec
4
+ module Core
5
+ module Formatters
6
+ # @private
7
+ class FailureListFormatter < BaseFormatter
8
+ Formatters.register self, :example_failed, :dump_profile, :message
9
+
10
+ def example_failed(failure)
11
+ output.puts "#{failure.example.location}:#{failure.example.description}"
12
+ end
13
+
14
+ # Discard profile and messages
15
+ #
16
+ # These outputs are not really relevant in the context of this failure
17
+ # list formatter.
18
+ def dump_profile(_profile); end
19
+ def message(_message); end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -115,7 +115,6 @@ module RSpec
115
115
  "style=\"margin-left: #{(number_of_parents - 1) * 15}px;\""
116
116
  end
117
117
 
118
- # rubocop:disable LineLength
119
118
  REPORT_HEADER = <<-EOF
120
119
  <div class="rspec-report">
121
120
 
@@ -139,7 +138,6 @@ module RSpec
139
138
 
140
139
  <div class="results">
141
140
  EOF
142
- # rubocop:enable LineLength
143
141
 
144
142
  GLOBAL_SCRIPTS = <<-EOF
145
143
 
@@ -17,12 +17,12 @@ module RSpec
17
17
  # @see RSpec::Core::Formatters::BaseTextFormatter
18
18
  # @see RSpec::Core::Reporter
19
19
  class Protocol
20
- # @method initialize
20
+ # @method initialize(output)
21
21
  # @api public
22
22
  #
23
23
  # @param output [IO] the formatter output
24
24
 
25
- # @method start
25
+ # @method start(notification)
26
26
  # @api public
27
27
  # @group Suite Notifications
28
28
  #
@@ -35,7 +35,7 @@ module RSpec
35
35
  #
36
36
  # @param notification [Notifications::StartNotification]
37
37
 
38
- # @method example_group_started
38
+ # @method example_group_started(notification)
39
39
  # @api public
40
40
  # @group Group Notifications
41
41
  #
@@ -48,7 +48,7 @@ module RSpec
48
48
  # @param notification [Notifications::GroupNotification] containing example_group
49
49
  # subclass of {ExampleGroup}
50
50
 
51
- # @method example_group_finished
51
+ # @method example_group_finished(notification)
52
52
  # @api public
53
53
  # @group Group Notifications
54
54
  #
@@ -57,7 +57,7 @@ module RSpec
57
57
  # @param notification [Notifications::GroupNotification] containing example_group
58
58
  # subclass of {ExampleGroup}
59
59
 
60
- # @method example_started
60
+ # @method example_started(notification)
61
61
  # @api public
62
62
  # @group Example Notifications
63
63
  #
@@ -66,7 +66,7 @@ module RSpec
66
66
  # @param notification [Notifications::ExampleNotification] containing example subclass
67
67
  # of {Example}
68
68
 
69
- # @method example_finished
69
+ # @method example_finished(notification)
70
70
  # @api public
71
71
  # @group Example Notifications
72
72
  #
@@ -75,7 +75,7 @@ module RSpec
75
75
  # @param notification [Notifications::ExampleNotification] containing example subclass
76
76
  # of {Example}
77
77
 
78
- # @method example_passed
78
+ # @method example_passed(notification)
79
79
  # @api public
80
80
  # @group Example Notifications
81
81
  #
@@ -84,7 +84,7 @@ module RSpec
84
84
  # @param notification [Notifications::ExampleNotification] containing example subclass
85
85
  # of {Example}
86
86
 
87
- # @method example_pending
87
+ # @method example_pending(notification)
88
88
  # @api public
89
89
  # @group Example Notifications
90
90
  #
@@ -93,7 +93,7 @@ module RSpec
93
93
  # @param notification [Notifications::ExampleNotification] containing example subclass
94
94
  # of {Example}
95
95
 
96
- # @method example_failed
96
+ # @method example_failed(notification)
97
97
  # @api public
98
98
  # @group Example Notifications
99
99
  #
@@ -102,7 +102,7 @@ module RSpec
102
102
  # @param notification [Notifications::ExampleNotification] containing example subclass
103
103
  # of {Example}
104
104
 
105
- # @method message
105
+ # @method message(notification)
106
106
  # @api public
107
107
  # @group Suite Notifications
108
108
  #
@@ -110,7 +110,7 @@ module RSpec
110
110
  #
111
111
  # @param notification [Notifications::MessageNotification] containing message
112
112
 
113
- # @method stop
113
+ # @method stop(notification)
114
114
  # @api public
115
115
  # @group Suite Notifications
116
116
  #
@@ -119,7 +119,7 @@ module RSpec
119
119
  #
120
120
  # @param notification [Notifications::NullNotification]
121
121
 
122
- # @method start_dump
122
+ # @method start_dump(notification)
123
123
  # @api public
124
124
  # @group Suite Notifications
125
125
  #
@@ -130,7 +130,7 @@ module RSpec
130
130
  #
131
131
  # @param notification [Notifications::NullNotification]
132
132
 
133
- # @method dump_failures
133
+ # @method dump_failures(notification)
134
134
  # @api public
135
135
  # @group Suite Notifications
136
136
  #
@@ -138,7 +138,7 @@ module RSpec
138
138
  #
139
139
  # @param notification [Notifications::NullNotification]
140
140
 
141
- # @method dump_summary
141
+ # @method dump_summary(summary)
142
142
  # @api public
143
143
  # @group Suite Notifications
144
144
  #
@@ -148,7 +148,7 @@ module RSpec
148
148
  # @param summary [Notifications::SummaryNotification] containing duration,
149
149
  # example_count, failure_count and pending_count
150
150
 
151
- # @method dump_profile
151
+ # @method dump_profile(profile)
152
152
  # @api public
153
153
  # @group Suite Notifications
154
154
  #
@@ -158,7 +158,7 @@ module RSpec
158
158
  # @param profile [Notifications::ProfileNotification] containing duration,
159
159
  # slowest_examples and slowest_example_groups
160
160
 
161
- # @method dump_pending
161
+ # @method dump_pending(notification)
162
162
  # @api public
163
163
  # @group Suite Notifications
164
164
  #
@@ -167,7 +167,7 @@ module RSpec
167
167
  #
168
168
  # @param notification [Notifications::NullNotification]
169
169
 
170
- # @method close
170
+ # @method close(notification)
171
171
  # @api public
172
172
  # @group Suite Notifications
173
173
  #
@@ -13,6 +13,25 @@ module RSpec
13
13
  implementation.highlight_syntax(lines)
14
14
  end
15
15
 
16
+ # rubocop:disable Lint/RescueException
17
+ # rubocop:disable Lint/HandleExceptions
18
+ def self.attempt_to_add_rspec_terms_to_coderay_keywords
19
+ CodeRay::Scanners::Ruby::Patterns::IDENT_KIND.add(%w[
20
+ describe context
21
+ it specify
22
+ before after around
23
+ let subject
24
+ expect allow
25
+ ], :keyword)
26
+ rescue Exception
27
+ # Mutating CodeRay's contants like this is not a public API
28
+ # and might not always work. If we cannot add our keywords
29
+ # to CodeRay it is not a big deal and not worth raising an
30
+ # error over, so we ignore it.
31
+ end
32
+ # rubocop:enable Lint/HandleExceptions
33
+ # rubocop:enable Lint/RescueException
34
+
16
35
  private
17
36
 
18
37
  if RSpec::Support::OS.windows?
@@ -38,25 +57,6 @@ module RSpec
38
57
  end
39
58
  end
40
59
 
41
- # rubocop:disable Lint/RescueException
42
- # rubocop:disable Lint/HandleExceptions
43
- def self.attempt_to_add_rspec_terms_to_coderay_keywords
44
- CodeRay::Scanners::Ruby::Patterns::IDENT_KIND.add(%w[
45
- describe context
46
- it specify
47
- before after around
48
- let subject
49
- expect allow
50
- ], :keyword)
51
- rescue Exception
52
- # Mutating CodeRay's contants like this is not a public API
53
- # and might not always work. If we cannot add our keywords
54
- # to CodeRay it is not a big deal and not worth raising an
55
- # error over, so we ignore it.
56
- end
57
- # rubocop:enable Lint/HandleExceptions
58
- # rubocop:enable Lint/RescueException
59
-
60
60
  # @private
61
61
  module CodeRayImplementation
62
62
  RESET_CODE = "\e[0m"
@@ -60,7 +60,8 @@ module RSpec
60
60
  # before(:example) # Declared in the current group.
61
61
  #
62
62
  # If more than one `before` is declared within any one scope, they are run
63
- # in the order in which they are declared.
63
+ # in the order in which they are declared. Any `around` hooks will execute
64
+ # later than any `before` hook regardless of scope.
64
65
  #
65
66
  # ### Conditions
66
67
  #
@@ -74,11 +75,11 @@ module RSpec
74
75
  # end
75
76
  # end
76
77
  #
77
- # describe Something, :authorized => true do
78
+ # RSpec.describe Something, :authorized => true do
78
79
  # # The before hook will run in before each example in this group.
79
80
  # end
80
81
  #
81
- # describe SomethingElse do
82
+ # RSpec.describe SomethingElse do
82
83
  # it "does something", :authorized => true do
83
84
  # # The before hook will run before this example.
84
85
  # end
@@ -159,7 +160,7 @@ module RSpec
159
160
  #
160
161
  # @example before(:example) declared in an {ExampleGroup}
161
162
  #
162
- # describe Thing do
163
+ # RSpec.describe Thing do
163
164
  # before(:example) do
164
165
  # @thing = Thing.new
165
166
  # end
@@ -171,7 +172,7 @@ module RSpec
171
172
  #
172
173
  # @example before(:context) declared in an {ExampleGroup}
173
174
  #
174
- # describe Parser do
175
+ # RSpec.describe Parser do
175
176
  # before(:context) do
176
177
  # File.open(file_to_parse, 'w') do |f|
177
178
  # f.write <<-CONTENT
@@ -261,7 +262,8 @@ module RSpec
261
262
  #
262
263
  # This is the reverse of the order in which `before` hooks are run.
263
264
  # Similarly, if more than one `after` is declared within any one scope,
264
- # they are run in reverse order of that in which they are declared.
265
+ # they are run in reverse order of that in which they are declared. Also
266
+ # `around` hooks will all have run before any after hooks are invoked.
265
267
  #
266
268
  # @note The `:example` and `:context` scopes are also available as
267
269
  # `:each` and `:all`, respectively. Use whichever you prefer.
@@ -322,13 +324,19 @@ module RSpec
322
324
  # end
323
325
  #
324
326
  # The yielded example aliases `run` with `call`, which lets you treat it
325
- # like a `Proc`. This is especially handy when working with libaries
327
+ # like a `Proc`. This is especially handy when working with libraries
326
328
  # that manage their own setup and teardown using a block or proc syntax,
327
329
  # e.g.
328
330
  #
329
331
  # around(:example) {|ex| Database.transaction(&ex)}
330
332
  # around(:example) {|ex| FakeFS(&ex)}
331
333
  #
334
+ # ### Order
335
+ #
336
+ # All `around` hooks execute immediately surrounding an example, this means
337
+ # that all `before` hooks will have run and no `after` hooks will have run yet.
338
+ #
339
+ # They are not a synonym for `before`/`after`.
332
340
  def around(*args, &block)
333
341
  hooks.register :prepend, :around, *args, &block
334
342
  end
@@ -339,8 +347,6 @@ module RSpec
339
347
  @hooks ||= HookCollections.new(self, FilterableItemRepository::UpdateOptimized)
340
348
  end
341
349
 
342
- private
343
-
344
350
  # @private
345
351
  Hook = Struct.new(:block, :options)
346
352
 
@@ -26,21 +26,23 @@ module RSpec
26
26
 
27
27
  # @private
28
28
  class Bisect
29
- def call(options, _err, _out)
29
+ def call(options, err, out)
30
30
  RSpec::Support.require_rspec_core "bisect/coordinator"
31
+ runner = Runner.new(options).tap { |r| r.configure(err, out) }
32
+ formatter = bisect_formatter_klass_for(options.options[:bisect]).new(
33
+ out, runner.configuration.bisect_runner
34
+ )
31
35
 
32
36
  success = RSpec::Core::Bisect::Coordinator.bisect_with(
33
- options.args,
34
- RSpec.configuration,
35
- bisect_formatter_for(options.options[:bisect])
37
+ runner, options.args, formatter
36
38
  )
37
39
 
38
40
  success ? 0 : 1
39
41
  end
40
42
 
41
- private
43
+ private
42
44
 
43
- def bisect_formatter_for(argument)
45
+ def bisect_formatter_klass_for(argument)
44
46
  return Formatters::BisectDebugFormatter if argument == "verbose"
45
47
  Formatters::BisectProgressFormatter
46
48
  end
@@ -10,7 +10,7 @@ module RSpec
10
10
  # @note `subject` was contributed by Joe Ferris to support the one-liner
11
11
  # syntax embraced by shoulda matchers:
12
12
  #
13
- # describe Widget do
13
+ # RSpec.describe Widget do
14
14
  # it { is_expected.to validate_presence_of(:name) }
15
15
  # # or
16
16
  # it { should validate_presence_of(:name) }
@@ -23,7 +23,7 @@ module RSpec
23
23
  # @example
24
24
  #
25
25
  # # Explicit declaration of subject.
26
- # describe Person do
26
+ # RSpec.describe Person do
27
27
  # subject { Person.new(:birthdate => 19.years.ago) }
28
28
  # it "should be eligible to vote" do
29
29
  # subject.should be_eligible_to_vote
@@ -32,7 +32,7 @@ module RSpec
32
32
  # end
33
33
  #
34
34
  # # Implicit subject => { Person.new }.
35
- # describe Person do
35
+ # RSpec.describe Person do
36
36
  # it "should be eligible to vote" do
37
37
  # subject.should be_eligible_to_vote
38
38
  # # ^ ^ explicit reference to subject not recommended
@@ -40,7 +40,7 @@ module RSpec
40
40
  # end
41
41
  #
42
42
  # # One-liner syntax - expectation is set on the subject.
43
- # describe Person do
43
+ # RSpec.describe Person do
44
44
  # it { is_expected.to be_eligible_to_vote }
45
45
  # # or
46
46
  # it { should be_eligible_to_vote }
@@ -67,7 +67,7 @@ module RSpec
67
67
  #
68
68
  # @example
69
69
  #
70
- # describe Person do
70
+ # RSpec.describe Person do
71
71
  # it { should be_eligible_to_vote }
72
72
  # end
73
73
  #
@@ -86,7 +86,7 @@ module RSpec
86
86
  #
87
87
  # @example
88
88
  #
89
- # describe Person do
89
+ # RSpec.describe Person do
90
90
  # it { should_not be_eligible_to_vote }
91
91
  # end
92
92
  #
@@ -270,7 +270,7 @@ EOS
270
270
  #
271
271
  # @example
272
272
  #
273
- # describe Thing do
273
+ # RSpec.describe Thing do
274
274
  # let(:thing) { Thing.new }
275
275
  #
276
276
  # it "does something" do
@@ -288,7 +288,26 @@ EOS
288
288
  raise(
289
289
  "#let or #subject called with a reserved name #initialize"
290
290
  ) if :initialize == name
291
- MemoizedHelpers.module_for(self).__send__(:define_method, name, &block)
291
+ our_module = MemoizedHelpers.module_for(self)
292
+
293
+ # If we have a module clash in our helper module
294
+ # then we need to remove it to prevent a warning.
295
+ #
296
+ # Note we do not check ancestor modules (see: `instance_methods(false)`)
297
+ # as we can override them.
298
+ if our_module.instance_methods(false).include?(name)
299
+ our_module.__send__(:remove_method, name)
300
+ end
301
+ our_module.__send__(:define_method, name, &block)
302
+
303
+ # If we have a module clash in the example module
304
+ # then we need to remove it to prevent a warning.
305
+ #
306
+ # Note we do not check ancestor modules (see: `instance_methods(false)`)
307
+ # as we can override them.
308
+ if instance_methods(false).include?(name)
309
+ remove_method(name)
310
+ end
292
311
 
293
312
  # Apply the memoization. The method has been defined in an ancestor
294
313
  # module so we can use `super` here to get the value.
@@ -323,7 +342,7 @@ EOS
323
342
  # end
324
343
  # end
325
344
  #
326
- # describe Thing do
345
+ # RSpec.describe Thing do
327
346
  # after(:example) { Thing.reset_count }
328
347
  #
329
348
  # context "using let" do
@@ -379,13 +398,13 @@ EOS
379
398
  #
380
399
  # @example
381
400
  #
382
- # describe CheckingAccount, "with $50" do
401
+ # RSpec.describe CheckingAccount, "with $50" do
383
402
  # subject { CheckingAccount.new(Money.new(50, :USD)) }
384
403
  # it { is_expected.to have_a_balance_of(Money.new(50, :USD)) }
385
404
  # it { is_expected.not_to be_overdrawn }
386
405
  # end
387
406
  #
388
- # describe CheckingAccount, "with a non-zero starting balance" do
407
+ # RSpec.describe CheckingAccount, "with a non-zero starting balance" do
389
408
  # subject(:account) { CheckingAccount.new(Money.new(50, :USD)) }
390
409
  # it { is_expected.not_to be_overdrawn }
391
410
  # it "has a balance equal to the starting balance" do
@@ -433,7 +452,7 @@ EOS
433
452
  # end
434
453
  # end
435
454
  #
436
- # describe Thing do
455
+ # RSpec.describe Thing do
437
456
  # after(:example) { Thing.reset_count }
438
457
  #
439
458
  # context "using subject" do
@@ -483,9 +502,9 @@ EOS
483
502
  def self.module_for(example_group)
484
503
  get_constant_or_yield(example_group, :LetDefinitions) do
485
504
  mod = Module.new do
486
- include Module.new {
505
+ include(Module.new {
487
506
  example_group.const_set(:NamedSubjectPreventSuper, self)
488
- }
507
+ })
489
508
  end
490
509
 
491
510
  example_group.const_set(:LetDefinitions, mod)