aboutsummaryrefslogtreecommitdiffstats
path: root/spec/bundler/support/sometimes.rb
blob: 6a50f5ff4c6907bf43a9e0b61cc26f8171fc7250 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# frozen_string_literal: true
module Sometimes
  def run_with_retries(example_to_run, retries)
    example = RSpec.current_example
    example.metadata[:retries] ||= retries

    retries.times do |t|
      example.metadata[:retried] = t + 1
      example.instance_variable_set(:@exception, nil)
      example_to_run.run
      break unless example.exception
    end

    if e = example.exception
      new_exception = e.exception(e.message + "[Retried #{retries} times]")
      new_exception.set_backtrace e.backtrace
      example.instance_variable_set(:@exception, new_exception)
    end
  end
end

RSpec.configure do |config|
  config.include Sometimes
  config.alias_example_to :sometimes, :sometimes => true
  config.add_setting :sometimes_retry_count, :default => 5

  config.around(:each, :sometimes => true) do |example|
    retries = example.metadata[:retries] || RSpec.configuration.sometimes_retry_count
    run_with_retries(example, retries)
  end

  config.after(:suite) do
    message = proc do |color, text|
      colored = RSpec::Core::Formatters::ConsoleCodes.wrap(text, color)
      notification = RSpec::Core::Notifications::MessageNotification.new(colored)
      formatter = RSpec.configuration.formatters.first
      formatter.message(notification) if formatter.respond_to?(:message)
    end

    retried_examples = RSpec.world.example_groups.map do |g|
      g.descendants.map do |d|
        d.filtered_examples.select do |e|
          e.metadata[:sometimes] && e.metadata.fetch(:retried, 1) > 1
        end
      end
    end.flatten

    message.call(retried_examples.empty? ? :green : :yellow, "\n\nRetried examples: #{retried_examples.count}")

    retried_examples.each do |e|
      message.call(:cyan, "  #{e.full_description}")
      path = RSpec::Core::Metadata.relative_path(e.location)
      message.call(:cyan, "  [#{e.metadata[:retried]}/#{e.metadata[:retries]}] " + path)
    end
  end
end