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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
# frozen_string_literal: true
require 'rspec/core'
module QA
module Specs
module Helpers
module Quarantine
include RSpec::Core::Pending
extend self
def configure_rspec
RSpec.configure do |config|
config.before(:context, :quarantine) do
Quarantine.skip_or_run_quarantined_contexts(config.inclusion_filter.rules, self.class)
end
config.before do |example|
Quarantine.skip_or_run_quarantined_tests_or_contexts(config.inclusion_filter.rules, example)
if example.metadata.key?(:only)
skip('Test is not compatible with this environment or pipeline') unless Runtime::Env.context_matches?(example.metadata[:only])
end
end
end
end
# Skip the entire context if a context is quarantined. This avoids running
# before blocks unnecessarily.
def skip_or_run_quarantined_contexts(filters, example)
return unless example.metadata.key?(:quarantine)
skip_or_run_quarantined_tests_or_contexts(filters, example)
end
# Skip tests in quarantine unless we explicitly focus on them.
def skip_or_run_quarantined_tests_or_contexts(filters, example)
if filters.key?(:quarantine)
included_filters = filters_other_than_quarantine(filters)
# If :quarantine is focused, skip the test/context unless its metadata
# includes quarantine and any other filters
# E.g., Suppose 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 because of the :quarantine metadata.
# 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
skip("Only running tests tagged with :quarantine and any of #{included_filters.keys}") if should_skip_when_focused?(example.metadata, included_filters)
else
if example.metadata.key?(:quarantine)
quarantine_tag = example.metadata[:quarantine]
if quarantine_tag&.is_a?(Hash) && quarantine_tag&.key?(:only)
# If the :quarantine hash contains :only, we respect that.
# For instance `quarantine: { only: { subdomain: :staging } }` will only quarantine the test when it runs against staging.
return unless Runtime::Env.context_matches?(quarantine_tag[:only])
end
skip(quarantine_message(quarantine_tag))
end
end
end
def filters_other_than_quarantine(filter)
filter.reject { |key, _| key == :quarantine }
end
def quarantine_message(quarantine_tag)
quarantine_message = %w(In quarantine)
quarantine_message << case quarantine_tag
when String
": #{quarantine_tag}"
when Hash
quarantine_tag.key?(:issue) ? ": #{quarantine_tag[:issue]}" : ''
else
''
end
quarantine_message.join(' ').strip
end
# Checks if a test or context should be skipped.
#
# Returns true if
# - the metadata does not includes the :quarantine tag
# or if
# - the metadata includes the :quarantine tag
# - and the filter includes other tags that aren't in the metadata
def should_skip_when_focused?(metadata, included_filters)
return true unless metadata.key?(:quarantine)
return false if included_filters.empty?
(metadata.keys & included_filters.keys).empty?
end
end
end
end
end
|