gitlab_quality-test_tooling 3.2.1 → 3.4.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.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -3
- data/exe/test-coverage +7 -3
- data/lib/gitlab_quality/test_tooling/code_coverage/README.md +10 -0
- data/lib/gitlab_quality/test_tooling/code_coverage/click_house/category_owners_table.rb +0 -23
- data/lib/gitlab_quality/test_tooling/code_coverage/click_house/coverage_metrics_table.rb +0 -42
- data/lib/gitlab_quality/test_tooling/code_coverage/click_house/table.rb +17 -0
- data/lib/gitlab_quality/test_tooling/code_coverage/click_house/test_file_mappings_table.rb +48 -0
- data/lib/gitlab_quality/test_tooling/code_coverage/lcov_file.rb +11 -1
- data/lib/gitlab_quality/test_tooling/code_coverage/test_file_mapping_data.rb +33 -0
- data/lib/gitlab_quality/test_tooling/runtime/env.rb +4 -0
- data/lib/gitlab_quality/test_tooling/test_quarantine/quarantine_formatter.rb +38 -0
- data/lib/gitlab_quality/test_tooling/test_quarantine/quarantine_helper.rb +76 -0
- data/lib/gitlab_quality/test_tooling/version.rb +1 -1
- metadata +6 -16
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 870c9853d71d7274b721d9f7bf0b6e23466da21ca5dec47a66aae9d3ebc62ea0
|
|
4
|
+
data.tar.gz: 242a18c953ae4259bce53f875c110be58e79d1b2477b07f8871d78a64aa7c5c6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4469d2f5013331527e49b45356563d7f8f4de34c2a49eb9ea4860cfc87fdb96979d4d3d05152403264f5564a70febdb91cc46e4e93373d2cd6b16924641a400e
|
|
7
|
+
data.tar.gz: 585059565492ed297f43f60bc13ec7c747e6a5cacb1330e9a8f828735b6dd1e151c72cba938b251c9cff8bca4926d191d0b8b336da2deb069827b841d666989d
|
data/Gemfile.lock
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
gitlab_quality-test_tooling (3.
|
|
4
|
+
gitlab_quality-test_tooling (3.4.0)
|
|
5
5
|
activesupport (>= 7.0)
|
|
6
6
|
amatch (~> 0.4.1)
|
|
7
7
|
fog-google (~> 1.24, >= 1.24.1)
|
|
8
8
|
gitlab (>= 4.19, < 7.0)
|
|
9
9
|
http (~> 5.0)
|
|
10
|
-
influxdb-client (~> 3.1)
|
|
11
10
|
nokogiri (~> 1.10)
|
|
12
11
|
parallel (>= 1, < 2)
|
|
13
12
|
rainbow (>= 3, < 4)
|
|
@@ -200,7 +199,6 @@ GEM
|
|
|
200
199
|
httpclient (2.8.3)
|
|
201
200
|
i18n (1.14.6)
|
|
202
201
|
concurrent-ruby (~> 1.0)
|
|
203
|
-
influxdb-client (3.1.0)
|
|
204
202
|
jaro_winkler (1.6.0)
|
|
205
203
|
json (2.7.2)
|
|
206
204
|
jwt (2.9.3)
|
data/exe/test-coverage
CHANGED
|
@@ -10,11 +10,13 @@ require_relative "../lib/gitlab_quality/test_tooling"
|
|
|
10
10
|
require_relative '../lib/gitlab_quality/test_tooling/code_coverage/category_owners'
|
|
11
11
|
require_relative '../lib/gitlab_quality/test_tooling/code_coverage/click_house/category_owners_table'
|
|
12
12
|
require_relative '../lib/gitlab_quality/test_tooling/code_coverage/click_house/coverage_metrics_table'
|
|
13
|
+
require_relative '../lib/gitlab_quality/test_tooling/code_coverage/click_house/test_file_mappings_table'
|
|
13
14
|
require_relative '../lib/gitlab_quality/test_tooling/code_coverage/coverage_data'
|
|
14
15
|
require_relative '../lib/gitlab_quality/test_tooling/code_coverage/lcov_file'
|
|
15
16
|
require_relative '../lib/gitlab_quality/test_tooling/code_coverage/artifacts'
|
|
16
17
|
require_relative '../lib/gitlab_quality/test_tooling/code_coverage/test_report'
|
|
17
18
|
require_relative '../lib/gitlab_quality/test_tooling/code_coverage/test_map'
|
|
19
|
+
require_relative '../lib/gitlab_quality/test_tooling/code_coverage/test_file_mapping_data'
|
|
18
20
|
require_relative '../lib/gitlab_quality/test_tooling/code_coverage/source_file_classifier'
|
|
19
21
|
require_relative '../lib/gitlab_quality/test_tooling/code_coverage/responsibility_classifier'
|
|
20
22
|
require_relative '../lib/gitlab_quality/test_tooling/code_coverage/responsibility_patterns_config'
|
|
@@ -167,15 +169,17 @@ if params.any? && (required_params - params.keys).none?
|
|
|
167
169
|
category_owners_table = GitlabQuality::TestTooling::CodeCoverage::ClickHouse::CategoryOwnersTable.new(**clickhouse_data)
|
|
168
170
|
coverage_metrics_table = GitlabQuality::TestTooling::CodeCoverage::ClickHouse::CoverageMetricsTable.new(**clickhouse_data)
|
|
169
171
|
|
|
170
|
-
category_owners_table.create if ENV['CLICKHOUSE_CREATE_CATEGORY_OWNERS_TABLE'] == 'true'
|
|
171
|
-
coverage_metrics_table.create if ENV['CLICKHOUSE_CREATE_COVERAGE_METRICS_TABLE'] == 'true'
|
|
172
|
-
|
|
173
172
|
if ENV['CLICKHOUSE_PUSH_CATEGORY_DATA'] == 'true'
|
|
174
173
|
category_owners_table.truncate
|
|
175
174
|
category_owners_table.push(category_owners.as_db_table)
|
|
176
175
|
end
|
|
177
176
|
|
|
178
177
|
coverage_metrics_table.push(coverage_data.as_db_table)
|
|
178
|
+
|
|
179
|
+
# Export test-to-file mappings
|
|
180
|
+
test_file_mapping_data = GitlabQuality::TestTooling::CodeCoverage::TestFileMappingData.new(test_to_sources)
|
|
181
|
+
test_file_mappings_table = GitlabQuality::TestTooling::CodeCoverage::ClickHouse::TestFileMappingsTable.new(**clickhouse_data)
|
|
182
|
+
test_file_mappings_table.push(test_file_mapping_data.as_db_table)
|
|
179
183
|
else
|
|
180
184
|
puts "Missing argument(s). Required arguments are: #{required_params}\nPassed arguments are: #{params}\n"
|
|
181
185
|
puts options
|
|
@@ -4,6 +4,7 @@ Exports test coverage data to ClickHouse, enriched with:
|
|
|
4
4
|
|
|
5
5
|
- **Feature category ownership** - group, stage, and section for each covered file
|
|
6
6
|
- **Responsibility classification** - whether coverage comes from unit or integration tests
|
|
7
|
+
- **Test-to-file mappings** - which source files each test covers
|
|
7
8
|
|
|
8
9
|
## How It Works
|
|
9
10
|
|
|
@@ -134,6 +135,15 @@ dependent:
|
|
|
134
135
|
- "^spec/features/"
|
|
135
136
|
```
|
|
136
137
|
|
|
138
|
+
## Test-to-File Mappings
|
|
139
|
+
|
|
140
|
+
When a test map is provided, the module also exports test-to-source-file relationships
|
|
141
|
+
to a separate `test_file_mappings` table. This enables:
|
|
142
|
+
|
|
143
|
+
- **Coverage context for tests** - see which source files a specific test covers
|
|
144
|
+
- **Impact analysis** - understand which files would lose coverage if a test is quarantined
|
|
145
|
+
- **Flaky test triage** - correlate flaky tests with the source files they cover
|
|
146
|
+
|
|
137
147
|
## CLI
|
|
138
148
|
|
|
139
149
|
Example usage:
|
|
@@ -11,29 +11,6 @@ module GitlabQuality
|
|
|
11
11
|
|
|
12
12
|
MissingMappingError = Class.new(StandardError)
|
|
13
13
|
|
|
14
|
-
# Creates the ClickHouse table, if it doesn't exist already
|
|
15
|
-
# @return [nil]
|
|
16
|
-
def create
|
|
17
|
-
logger.debug("#{LOG_PREFIX} Creating category_owners table if it doesn't exist ...")
|
|
18
|
-
|
|
19
|
-
client.query(<<~SQL)
|
|
20
|
-
CREATE TABLE IF NOT EXISTS #{table_name} (
|
|
21
|
-
timestamp DateTime64(6, 'UTC') DEFAULT now64(),
|
|
22
|
-
category String,
|
|
23
|
-
group String,
|
|
24
|
-
stage String,
|
|
25
|
-
section String,
|
|
26
|
-
INDEX idx_group group TYPE set(360) GRANULARITY 1,
|
|
27
|
-
INDEX idx_stage stage TYPE set(360) GRANULARITY 1,
|
|
28
|
-
INDEX idx_section section TYPE set(360) GRANULARITY 1
|
|
29
|
-
) ENGINE = MergeTree()
|
|
30
|
-
ORDER BY (category, timestamp)
|
|
31
|
-
SETTINGS index_granularity = 8192;
|
|
32
|
-
SQL
|
|
33
|
-
|
|
34
|
-
logger.info("#{LOG_PREFIX} Category owners table created/verified successfully")
|
|
35
|
-
end
|
|
36
|
-
|
|
37
14
|
def truncate
|
|
38
15
|
logger.debug("#{LOG_PREFIX} Truncating table #{full_table_name} ...")
|
|
39
16
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'time'
|
|
4
3
|
require_relative 'table'
|
|
5
4
|
|
|
6
5
|
module GitlabQuality
|
|
@@ -10,39 +9,6 @@ module GitlabQuality
|
|
|
10
9
|
class CoverageMetricsTable < GitlabQuality::TestTooling::CodeCoverage::ClickHouse::Table
|
|
11
10
|
TABLE_NAME = "coverage_metrics"
|
|
12
11
|
|
|
13
|
-
# Creates the ClickHouse table, if it doesn't exist already
|
|
14
|
-
# @return [nil]
|
|
15
|
-
def create
|
|
16
|
-
logger.debug("#{LOG_PREFIX} Creating coverage_metrics table if it doesn't exist ...")
|
|
17
|
-
|
|
18
|
-
client.query(<<~SQL)
|
|
19
|
-
CREATE TABLE IF NOT EXISTS #{table_name} (
|
|
20
|
-
timestamp DateTime64(6, 'UTC'),
|
|
21
|
-
file String,
|
|
22
|
-
line_coverage Float64,
|
|
23
|
-
branch_coverage Nullable(Float64),
|
|
24
|
-
function_coverage Nullable(Float64),
|
|
25
|
-
source_file_type String,
|
|
26
|
-
is_responsible Nullable(Bool),
|
|
27
|
-
is_dependent Nullable(Bool),
|
|
28
|
-
category Nullable(String),
|
|
29
|
-
ci_project_id Nullable(UInt32),
|
|
30
|
-
ci_project_path Nullable(String),
|
|
31
|
-
ci_job_name Nullable(String),
|
|
32
|
-
ci_job_id Nullable(UInt64),
|
|
33
|
-
ci_pipeline_id Nullable(UInt64),
|
|
34
|
-
ci_merge_request_iid Nullable(UInt32),
|
|
35
|
-
ci_branch Nullable(String),
|
|
36
|
-
ci_target_branch Nullable(String)
|
|
37
|
-
) ENGINE = MergeTree()
|
|
38
|
-
PARTITION BY toYYYYMM(timestamp)
|
|
39
|
-
ORDER BY (ci_project_path, timestamp, file, ci_pipeline_id)
|
|
40
|
-
SETTINGS index_granularity = 8192, allow_nullable_key = 1;
|
|
41
|
-
SQL
|
|
42
|
-
|
|
43
|
-
logger.info("#{LOG_PREFIX} Coverage metrics table created/verified successfully")
|
|
44
|
-
end
|
|
45
|
-
|
|
46
12
|
private
|
|
47
13
|
|
|
48
14
|
# @return [Boolean] True if the record is valid, false otherwise
|
|
@@ -106,14 +72,6 @@ module GitlabQuality
|
|
|
106
72
|
}
|
|
107
73
|
end
|
|
108
74
|
|
|
109
|
-
# @return [Time] Common timestamp for all coverage records
|
|
110
|
-
def time
|
|
111
|
-
@time ||= begin
|
|
112
|
-
ci_created_at = ENV.fetch('CI_PIPELINE_CREATED_AT', nil)
|
|
113
|
-
ci_created_at ? Time.strptime(ci_created_at, '%Y-%m-%dT%H:%M:%S%z') : Time.now.utc
|
|
114
|
-
end
|
|
115
|
-
end
|
|
116
|
-
|
|
117
75
|
# @return [Hash] CI-related metadata
|
|
118
76
|
def ci_metadata
|
|
119
77
|
{
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'time'
|
|
4
|
+
|
|
3
5
|
module GitlabQuality
|
|
4
6
|
module TestTooling
|
|
5
7
|
module CodeCoverage
|
|
@@ -58,6 +60,21 @@ module GitlabQuality
|
|
|
58
60
|
raise NotImplementedError, "#{self.class}##{__method__} method must be implemented in a subclass"
|
|
59
61
|
end
|
|
60
62
|
|
|
63
|
+
# @return [Time] Common timestamp for all records, memoized
|
|
64
|
+
def time
|
|
65
|
+
@time ||= parse_ci_timestamp
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def parse_ci_timestamp
|
|
69
|
+
ci_created_at = ENV.fetch('CI_PIPELINE_CREATED_AT', nil)
|
|
70
|
+
return Time.now.utc unless ci_created_at
|
|
71
|
+
|
|
72
|
+
Time.strptime(ci_created_at, '%Y-%m-%dT%H:%M:%S%z')
|
|
73
|
+
rescue ArgumentError
|
|
74
|
+
logger.warn("#{LOG_PREFIX} Invalid CI_PIPELINE_CREATED_AT format: #{ci_created_at}, using current time")
|
|
75
|
+
Time.now.utc
|
|
76
|
+
end
|
|
77
|
+
|
|
61
78
|
# @return [GitlabQuality::TestTooling::ClickHouse::Client]
|
|
62
79
|
def client
|
|
63
80
|
@client ||= GitlabQuality::TestTooling::ClickHouse::Client.new(
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'table'
|
|
4
|
+
|
|
5
|
+
module GitlabQuality
|
|
6
|
+
module TestTooling
|
|
7
|
+
module CodeCoverage
|
|
8
|
+
module ClickHouse
|
|
9
|
+
class TestFileMappingsTable < GitlabQuality::TestTooling::CodeCoverage::ClickHouse::Table
|
|
10
|
+
TABLE_NAME = "test_file_mappings"
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
# @return [Boolean] True if the record is valid, false otherwise
|
|
15
|
+
def valid_record?(record)
|
|
16
|
+
valid_test_file?(record) && valid_source_file?(record)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# @return [Boolean] True if the test_file field is present
|
|
20
|
+
def valid_test_file?(record)
|
|
21
|
+
return true unless record[:test_file].blank?
|
|
22
|
+
|
|
23
|
+
logger.warn("#{LOG_PREFIX} Skipping record with nil/empty test_file: #{record}")
|
|
24
|
+
false
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# @return [Boolean] True if the source_file field is present
|
|
28
|
+
def valid_source_file?(record)
|
|
29
|
+
return true unless record[:source_file].blank?
|
|
30
|
+
|
|
31
|
+
logger.warn("#{LOG_PREFIX} Skipping record with nil/empty source_file: #{record}")
|
|
32
|
+
false
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# @return [Hash] Transformed mapping data including timestamp and CI metadata
|
|
36
|
+
def sanitized_data_record(record)
|
|
37
|
+
{
|
|
38
|
+
timestamp: time,
|
|
39
|
+
test_file: record[:test_file],
|
|
40
|
+
source_file: record[:source_file],
|
|
41
|
+
ci_project_path: ENV.fetch('CI_PROJECT_PATH', nil)
|
|
42
|
+
}
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -85,7 +85,7 @@ module GitlabQuality
|
|
|
85
85
|
end
|
|
86
86
|
|
|
87
87
|
def register_source_file(filename)
|
|
88
|
-
@current_file = filename
|
|
88
|
+
@current_file = normalize_path(filename)
|
|
89
89
|
@parsed_content[@current_file] = {
|
|
90
90
|
line_coverage: {},
|
|
91
91
|
branch_coverage: {},
|
|
@@ -94,6 +94,16 @@ module GitlabQuality
|
|
|
94
94
|
}
|
|
95
95
|
end
|
|
96
96
|
|
|
97
|
+
def normalize_path(filename)
|
|
98
|
+
# Remove leading ./ if present
|
|
99
|
+
path = filename.gsub(%r{^\./}, '')
|
|
100
|
+
|
|
101
|
+
# Handle GDK/CI paths like "../../../home/gdk/gitlab-development-kit/gitlab/app/..."
|
|
102
|
+
# Extract path starting from known root directories
|
|
103
|
+
match = path.match(%r{((?:ee/)?(?:app|lib|config|db|spec|scripts|tooling|workhorse|vendor)/.+)$})
|
|
104
|
+
match ? match[1] : path
|
|
105
|
+
end
|
|
106
|
+
|
|
97
107
|
def register_line_data(line_no, count)
|
|
98
108
|
return unless @current_file
|
|
99
109
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GitlabQuality
|
|
4
|
+
module TestTooling
|
|
5
|
+
module CodeCoverage
|
|
6
|
+
class TestFileMappingData
|
|
7
|
+
# @param [Hash<String, Array<String>>] test_to_sources Test files
|
|
8
|
+
# mapped to all source files they cover
|
|
9
|
+
def initialize(test_to_sources)
|
|
10
|
+
@test_to_sources = test_to_sources
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# @return [Array<Hash<Symbol, String>>] Mapping data formatted for database insertion
|
|
14
|
+
# @example Return value
|
|
15
|
+
# [
|
|
16
|
+
# { test_file: "spec/models/user_spec.rb", source_file: "app/models/user.rb" },
|
|
17
|
+
# { test_file: "spec/models/user_spec.rb", source_file: "lib/utils.rb" },
|
|
18
|
+
# ...
|
|
19
|
+
# ]
|
|
20
|
+
def as_db_table
|
|
21
|
+
@test_to_sources.flat_map do |test_file, source_files|
|
|
22
|
+
source_files.map do |source_file|
|
|
23
|
+
{
|
|
24
|
+
test_file: test_file,
|
|
25
|
+
source_file: source_file
|
|
26
|
+
}
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rspec/core/formatters/base_formatter"
|
|
4
|
+
|
|
5
|
+
module GitlabQuality
|
|
6
|
+
module TestTooling
|
|
7
|
+
module TestQuarantine
|
|
8
|
+
class QuarantineFormatter < ::RSpec::Core::Formatters::BaseFormatter
|
|
9
|
+
include QuarantineHelper
|
|
10
|
+
|
|
11
|
+
::RSpec::Core::Formatters.register(
|
|
12
|
+
self,
|
|
13
|
+
:example_group_started,
|
|
14
|
+
:example_started
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
# Starts example group
|
|
18
|
+
# @param [RSpec::Core::Notifications::GroupNotification] example_group_notification
|
|
19
|
+
# @return [void]
|
|
20
|
+
def example_group_started(example_group_notification)
|
|
21
|
+
group = example_group_notification.group
|
|
22
|
+
|
|
23
|
+
skip_or_run_quarantined_tests_or_contexts(group)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Starts example
|
|
27
|
+
# @param [RSpec::Core::Notifications::ExampleNotification] example_notification
|
|
28
|
+
# @return [void]
|
|
29
|
+
def example_started(example_notification)
|
|
30
|
+
example = example_notification.example
|
|
31
|
+
|
|
32
|
+
# if skip propagated from example_group, do not reset skip metadata
|
|
33
|
+
skip_or_run_quarantined_tests_or_contexts(example) unless example.metadata[:skip]
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rspec/core'
|
|
4
|
+
|
|
5
|
+
module GitlabQuality
|
|
6
|
+
module TestTooling
|
|
7
|
+
module TestQuarantine
|
|
8
|
+
module QuarantineHelper
|
|
9
|
+
include ::RSpec::Core::Pending
|
|
10
|
+
|
|
11
|
+
extend self
|
|
12
|
+
|
|
13
|
+
# Skip tests in quarantine unless we explicitly focus on them or quarantine disabled
|
|
14
|
+
def skip_or_run_quarantined_tests_or_contexts(example)
|
|
15
|
+
return if Runtime::Env.quarantine_disabled?
|
|
16
|
+
|
|
17
|
+
if filters.key?(:quarantine)
|
|
18
|
+
included_filters = filters_other_than_quarantine
|
|
19
|
+
|
|
20
|
+
# If :quarantine is focused, skip the test/context unless its metadata
|
|
21
|
+
# includes quarantine and any other filters
|
|
22
|
+
# E.g., Suppose a test is tagged :smoke and :quarantine, and another is tagged
|
|
23
|
+
# :ldap and :quarantine. If we wanted to run just quarantined smoke tests
|
|
24
|
+
# using `--tag quarantine --tag smoke`, without this check we'd end up
|
|
25
|
+
# running that ldap test as well because of the :quarantine metadata.
|
|
26
|
+
# We could use an exclusion filter, but this way the test report will list
|
|
27
|
+
# the quarantined tests when they're not run so that we're aware of them
|
|
28
|
+
if should_skip_when_focused?(example.metadata, included_filters)
|
|
29
|
+
example.metadata[:skip] = "Only running tests tagged with :quarantine and any of #{included_filters.keys}"
|
|
30
|
+
end
|
|
31
|
+
elsif example.metadata.key?(:quarantine)
|
|
32
|
+
quarantine_tag = example.metadata[:quarantine]
|
|
33
|
+
|
|
34
|
+
example.metadata[:skip] = quarantine_message(quarantine_tag)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def filters_other_than_quarantine
|
|
39
|
+
filters.except(:quarantine)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def quarantine_message(quarantine_tag)
|
|
43
|
+
quarantine_message = %w[In quarantine]
|
|
44
|
+
quarantine_message << case quarantine_tag
|
|
45
|
+
when String
|
|
46
|
+
": #{quarantine_tag}"
|
|
47
|
+
when Hash
|
|
48
|
+
quarantine_tag.key?(:issue) ? ": #{quarantine_tag[:issue]}" : ''
|
|
49
|
+
else
|
|
50
|
+
''
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
quarantine_message.join(' ').strip
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Checks if a test or context should be skipped.
|
|
57
|
+
#
|
|
58
|
+
# Returns true if
|
|
59
|
+
# - the metadata does not includes the :quarantine tag
|
|
60
|
+
# or if
|
|
61
|
+
# - the metadata includes the :quarantine tag
|
|
62
|
+
# - and the filter includes other tags that aren't in the metadata
|
|
63
|
+
def should_skip_when_focused?(metadata, included_filters)
|
|
64
|
+
return true unless metadata.key?(:quarantine)
|
|
65
|
+
return false if included_filters.empty?
|
|
66
|
+
|
|
67
|
+
!metadata.keys.intersect?(included_filters.keys)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def filters
|
|
71
|
+
@filters ||= ::RSpec.configuration.inclusion_filter.rules
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: gitlab_quality-test_tooling
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- GitLab Quality
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-01-13 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: climate_control
|
|
@@ -302,20 +302,6 @@ dependencies:
|
|
|
302
302
|
- - "~>"
|
|
303
303
|
- !ruby/object:Gem::Version
|
|
304
304
|
version: '5.0'
|
|
305
|
-
- !ruby/object:Gem::Dependency
|
|
306
|
-
name: influxdb-client
|
|
307
|
-
requirement: !ruby/object:Gem::Requirement
|
|
308
|
-
requirements:
|
|
309
|
-
- - "~>"
|
|
310
|
-
- !ruby/object:Gem::Version
|
|
311
|
-
version: '3.1'
|
|
312
|
-
type: :runtime
|
|
313
|
-
prerelease: false
|
|
314
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
315
|
-
requirements:
|
|
316
|
-
- - "~>"
|
|
317
|
-
- !ruby/object:Gem::Version
|
|
318
|
-
version: '3.1'
|
|
319
305
|
- !ruby/object:Gem::Dependency
|
|
320
306
|
name: nokogiri
|
|
321
307
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -490,12 +476,14 @@ files:
|
|
|
490
476
|
- lib/gitlab_quality/test_tooling/code_coverage/click_house/category_owners_table.rb
|
|
491
477
|
- lib/gitlab_quality/test_tooling/code_coverage/click_house/coverage_metrics_table.rb
|
|
492
478
|
- lib/gitlab_quality/test_tooling/code_coverage/click_house/table.rb
|
|
479
|
+
- lib/gitlab_quality/test_tooling/code_coverage/click_house/test_file_mappings_table.rb
|
|
493
480
|
- lib/gitlab_quality/test_tooling/code_coverage/coverage_data.rb
|
|
494
481
|
- lib/gitlab_quality/test_tooling/code_coverage/lcov_file.rb
|
|
495
482
|
- lib/gitlab_quality/test_tooling/code_coverage/responsibility_classifier.rb
|
|
496
483
|
- lib/gitlab_quality/test_tooling/code_coverage/responsibility_patterns_config.rb
|
|
497
484
|
- lib/gitlab_quality/test_tooling/code_coverage/rspec_report.rb
|
|
498
485
|
- lib/gitlab_quality/test_tooling/code_coverage/source_file_classifier.rb
|
|
486
|
+
- lib/gitlab_quality/test_tooling/code_coverage/test_file_mapping_data.rb
|
|
499
487
|
- lib/gitlab_quality/test_tooling/code_coverage/test_map.rb
|
|
500
488
|
- lib/gitlab_quality/test_tooling/code_coverage/test_report.rb
|
|
501
489
|
- lib/gitlab_quality/test_tooling/code_coverage/utils.rb
|
|
@@ -592,6 +580,8 @@ files:
|
|
|
592
580
|
- lib/gitlab_quality/test_tooling/test_metrics_exporter/formatter.rb
|
|
593
581
|
- lib/gitlab_quality/test_tooling/test_metrics_exporter/test_metrics.rb
|
|
594
582
|
- lib/gitlab_quality/test_tooling/test_metrics_exporter/utils.rb
|
|
583
|
+
- lib/gitlab_quality/test_tooling/test_quarantine/quarantine_formatter.rb
|
|
584
|
+
- lib/gitlab_quality/test_tooling/test_quarantine/quarantine_helper.rb
|
|
595
585
|
- lib/gitlab_quality/test_tooling/test_result/base_test_result.rb
|
|
596
586
|
- lib/gitlab_quality/test_tooling/test_result/j_unit_test_result.rb
|
|
597
587
|
- lib/gitlab_quality/test_tooling/test_result/json_test_result.rb
|