summaryrefslogtreecommitdiff
path: root/qa/spec/spec_helper.rb
blob: cbdd6e881b11dd913b0f5197480c90bb10bc5c66 (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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
require_relative '../qa'
require 'rspec/retry'

%w[helpers shared_examples].each do |d|
  Dir[::File.join(__dir__, d, '**', '*.rb')].each { |f| require f }
end

RSpec.configure do |config|
  config.before(:context) do
    if self.class.metadata.keys.include?(:quarantine)
      skip_or_run_quarantined_tests(self.class.metadata.keys, config.inclusion_filter.rules.keys)
    end
  end

  config.before do |example|
    QA::Runtime::Logger.debug("Starting test: #{example.full_description}") if QA::Runtime::Env.debug?

    skip_or_run_quarantined_tests(example.metadata.keys, config.inclusion_filter.rules.keys)
  end

  config.expect_with :rspec do |expectations|
    expectations.include_chain_clauses_in_custom_matcher_descriptions = true
  end

  config.mock_with :rspec do |mocks|
    mocks.verify_partial_doubles = true
  end

  config.shared_context_metadata_behavior = :apply_to_host_groups
  config.disable_monkey_patching!
  config.expose_dsl_globally = true
  config.profile_examples = 10
  config.order = :random
  Kernel.srand config.seed

  # show retry status in spec process
  config.verbose_retry = true

  # show exception that triggers a retry if verbose_retry is set to true
  config.display_try_failure_messages = true

  config.around do |example|
    retry_times = example.metadata.keys.include?(:quarantine) ? 1 : 3
    example.run_with_retry retry: retry_times
  end
end

# Skip tests in quarantine unless we explicitly focus on them.
# Skip the entire context if a context is tagged. This avoids running before
# blocks unnecessarily.
# If quarantine is focussed, skip tests/contexts that have other metadata
# unless they're also focussed. This lets us run quarantined tests in a
# particular category without running tests in other categories.
# E.g., if a test is tagged 'smoke' and 'quarantine', and another is tagged
# 'ldap' and 'quarantine', if we wanted to run just quarantined smoke tests
# using `--tag quarantine --tag smoke`, without this check we'd end up
# running that ldap test as well.
# We could use an exclusion filter, but this way the test report will list
# the quarantined tests when they're not run so that we're aware of them
def skip_or_run_quarantined_tests(metadata_keys, filter_keys)
  included_filters = filters_other_than_quarantine(filter_keys)

  if filter_keys.include?(:quarantine)
    skip("Only running tests tagged with :quarantine and any of #{included_filters}") unless quarantine_and_optional_other_tag?(metadata_keys, included_filters)
  else
    skip('In quarantine') if metadata_keys.include?(:quarantine)
  end
end

def filters_other_than_quarantine(filter_keys)
  filter_keys.reject { |key| key == :quarantine }
end

# Checks if a test has the 'quarantine' tag and other tags in the inclusion filter.
#
# Returns true if
# - the metadata includes the quarantine tag
#   - and the metadata and inclusion filter both have any other tag
#   - or no other tags are in the inclusion filter
def quarantine_and_optional_other_tag?(metadata_keys, included_filters)
  return false unless metadata_keys.include? :quarantine
  return true if included_filters.empty?

  included_filters.any? { |key| metadata_keys.include? key }
end