gitlab_quality-test_tooling 0.8.2 → 0.8.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d201b5e75d11490d7b8a3f7b3abdc883442487d07d19f9c5c7cf02577a867116
4
- data.tar.gz: 0b50d503726912d587bb2b3d4bd1e1c2194b8f0773d2a37905afa0c66dfbbaee
3
+ metadata.gz: a3472eb65666a6691797e9e0f0332a1773bb6babe898245a375bd9976523866e
4
+ data.tar.gz: 6372e6df38afb56bbe300b39d25a65cb7cdd205765ded99cab3745f4fbe7d812
5
5
  SHA512:
6
- metadata.gz: e5b8c615d62f29710c55a3d39373efb71cf1b7895d3b7ca08d6a4e0077e47b7a0c109f111716d49d7d5adcac4b3ffc8668c20fcb95fc01bfb2244c38bfafba62
7
- data.tar.gz: 30b05b1eac9f9b6400e089b1de4e229fcd5769aae2a41066bc43e79e08f6a6c37db8e4b7cbbfd46933021eabafa098be601a546c5cc05d7a93fa4c01d5c14021
6
+ metadata.gz: 899483550e08f6f873d137d6a1bc90620ed58eff093827e76e5b4c92de8b7b1f95bba60181d2b726d79bf91b08b627cc93fb3817662dff73db8ba46e81557aad
7
+ data.tar.gz: 6b21fae0eb76efa44dd868113d22d36c30a9f5d06b5bb1b625dd42129a463a24ae77abf4edf6df05d06800b29261116492cb39aa892490aaa22cfca9ce442aa4
data/.tool-versions ADDED
@@ -0,0 +1 @@
1
+ ruby 3.0.5
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gitlab_quality-test_tooling (0.8.2)
4
+ gitlab_quality-test_tooling (0.8.3)
5
5
  activesupport (>= 6.1, < 7.1)
6
6
  gitlab (~> 4.19)
7
7
  http (~> 5.0)
data/README.md CHANGED
@@ -121,6 +121,18 @@ Usage: exe/update-screenshot-paths [options]
121
121
  -h, --help Show the usage
122
122
  ```
123
123
 
124
+ ### `slow-test-issues`
125
+
126
+ ```shell
127
+ Purpose: Create slow test issues from JSON RSpec report files
128
+ Usage: exe/slow-test-issue [options]
129
+ -i, --input-files INPUT_FILES JSON RSpec report files JSON
130
+ -p, --project PROJECT Can be an integer or a group/project string
131
+ -t, --token TOKEN A valid access token with `api` scope and Maintainer permission in PROJECT
132
+ --dry-run Perform a dry-run (don't create issues)
133
+ -v, --version Show the version
134
+ -h, --help Show the usage
135
+ ```
124
136
  ## Development
125
137
 
126
138
  ### Initial setup
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "optparse"
6
+
7
+ require_relative "../lib/gitlab_quality/test_tooling"
8
+
9
+ params = {}
10
+
11
+ options = OptionParser.new do |opts|
12
+ opts.banner = "Usage: #{$PROGRAM_NAME} [options]"
13
+
14
+ opts.on('-i', '--input-files INPUT_FILES', String, 'JSON RSpec report files JSON') do |input_files|
15
+ params[:input_files] = input_files
16
+ end
17
+
18
+ opts.on('-p', '--project PROJECT', String, 'Can be an integer or a group/project string') do |project|
19
+ params[:project] = project
20
+ end
21
+
22
+ opts.on('-t', '--token TOKEN', String, 'A valid access token with `api` scope and Maintainer permission in PROJECT') do |token|
23
+ params[:token] = token
24
+ end
25
+
26
+ opts.on('--dry-run', "Perform a dry-run (don't create issues)") do
27
+ params[:dry_run] = true
28
+ end
29
+
30
+ opts.on_tail('-v', '--version', 'Show the version') do
31
+ require_relative "../lib/gitlab_quality/test_tooling/version"
32
+ puts "#{$PROGRAM_NAME} : #{GitlabQuality::TestTooling::VERSION}"
33
+ exit
34
+ end
35
+
36
+ opts.on_tail('-h', '--help', 'Show the usage') do
37
+ puts "Purpose: Create slow test issues from JSON RSpec report files"
38
+ puts opts
39
+ exit
40
+ end
41
+
42
+ opts.parse(ARGV)
43
+ end
44
+
45
+ if params.any?
46
+ GitlabQuality::TestTooling::Report::SlowTestIssue.new(**params).invoke!
47
+ else
48
+ puts options
49
+ exit 1
50
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GitlabQuality
4
+ module TestTooling
5
+ module Report
6
+ module Concerns
7
+ module GroupAndCategoryLabels
8
+ def labels_inference
9
+ @labels_inference ||= GitlabQuality::TestTooling::LabelsInference.new
10
+ end
11
+
12
+ def new_issue_labels(test)
13
+ puts " => [DEBUG] product_group: #{test.product_group}; feature_category: #{test.feature_category}"
14
+
15
+ new_labels = self.class::NEW_ISSUE_LABELS +
16
+ labels_inference.infer_labels_from_product_group(test.product_group) +
17
+ labels_inference.infer_labels_from_feature_category(test.feature_category)
18
+ up_to_date_labels(test: test, new_labels: new_labels)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -16,6 +16,7 @@ module GitlabQuality
16
16
  # - Add the failed job to the issue description, and update labels
17
17
  class RelateFailureIssue < ReportAsIssue
18
18
  include Concerns::FindSetDri
19
+ include Concerns::GroupAndCategoryLabels
19
20
 
20
21
  DEFAULT_MAX_DIFF_RATIO_FOR_DETECTION = 0.15
21
22
  SYSTEMIC_EXCEPTIONS_THRESHOLD = 10
@@ -313,18 +314,6 @@ module GitlabQuality
313
314
  "1. #{Time.new.utc.strftime('%F')}: #{test.ci_job_url} (#{ENV.fetch('CI_PIPELINE_URL', 'pipeline url is missing')})"
314
315
  end
315
316
 
316
- def labels_inference
317
- @labels_inference ||= GitlabQuality::TestTooling::LabelsInference.new
318
- end
319
-
320
- def new_issue_labels(test)
321
- puts " => [DEBUG] product_group: #{test.product_group}; feature_category: #{test.feature_category}"
322
- new_labels = NEW_ISSUE_LABELS +
323
- labels_inference.infer_labels_from_product_group(test.product_group) +
324
- labels_inference.infer_labels_from_feature_category(test.feature_category)
325
- up_to_date_labels(test: test, new_labels: new_labels)
326
- end
327
-
328
317
  def up_to_date_labels(test:, issue: nil, new_labels: Set.new)
329
318
  (Set.new(base_issue_labels) + (super << pipeline_name_label)).to_a
330
319
  end
@@ -30,7 +30,7 @@ module GitlabQuality
30
30
  raise NotImplementedError
31
31
  end
32
32
 
33
- def failed_test_hash(test)
33
+ def test_hash(test)
34
34
  OpenSSL::Digest::SHA256.hexdigest(test.file + test.name)
35
35
  end
36
36
 
@@ -42,7 +42,7 @@ module GitlabQuality
42
42
  | ------ | ------ |
43
43
  | File | #{test_file_link(test)} |
44
44
  | Description | `#{test.name}` |
45
- | Hash | `#{failed_test_hash(test)}` |
45
+ | Hash | `#{test_hash(test)}` |
46
46
  #{"| Test case | #{test.testcase} |" if test.testcase}
47
47
  DESCRIPTION
48
48
  end
@@ -50,7 +50,7 @@ module GitlabQuality
50
50
  def test_file_link(test)
51
51
  path_prefix = test.file.start_with?('qa/') ? 'qa/' : ''
52
52
 
53
- "[`#{path_prefix}#{test.file}`](#{FILE_BASE_URL}#{path_prefix}#{test.file})"
53
+ "[`#{path_prefix}#{test.file}`](#{FILE_BASE_URL}#{path_prefix}#{test.file}##{test.line_number})"
54
54
  end
55
55
 
56
56
  def new_issue_labels(_test)
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GitlabQuality
4
+ module TestTooling
5
+ module Report
6
+ # Uses the API to create GitLab issues for slow tests
7
+ #
8
+ # - Takes the JSON test reports like rspec-*.json`
9
+ # - Takes a project where slow issues should be created
10
+ # - Find issue by title (with test description or test file)
11
+ # - Add test metadata, duration to the issue with group and category labels
12
+ class SlowTestIssue < ReportAsIssue
13
+ include Concerns::FindSetDri
14
+ include Concerns::GroupAndCategoryLabels
15
+
16
+ NEW_ISSUE_LABELS = Set.new(%w[test type::maintenance maintenance::performance priority::3 severity::3]).freeze
17
+ SEARCH_LABELS = %w[test maintenance::performance].freeze
18
+
19
+ MultipleIssuesFound = Class.new(StandardError)
20
+
21
+ TestLevelSpecification = Struct.new(:regex, :max_duration)
22
+
23
+ OTHER_TESTS_MAX_DURATION = 45.40 # seconds
24
+
25
+ TEST_LEVEL_SPECIFICATIONS = [
26
+ TestLevelSpecification.new(%r{/features/}, 50.13),
27
+ TestLevelSpecification.new(%r{/controllers|requests/}, 19.20),
28
+ TestLevelSpecification.new(%r{/lib/}, 27.12)
29
+ ].freeze
30
+
31
+ private
32
+
33
+ def run!
34
+ puts "Reporting slow tests in `#{files.join(',')}` as issues in project `#{project}` via the API at `#{Runtime::Env.gitlab_api_base}`."
35
+
36
+ TestResults::Builder.new(files).test_results_per_file do |test_results|
37
+ puts "=> Reporting #{test_results.count} tests in #{test_results.path}"
38
+
39
+ test_results.each do |test|
40
+ create_slow_issue(test) if should_create_slow_issue?(test)
41
+ end
42
+ end
43
+ end
44
+
45
+ def new_issue_title(test)
46
+ "Slow test in #{super}"
47
+ end
48
+
49
+ def new_issue_description(test)
50
+ super + [
51
+ "\n### Slow test",
52
+ "Slow tests detected, see guides for more details and how to improve them:",
53
+ "- [Top slow tests](https://docs.gitlab.com/ee/development/testing_guide/best_practices.html#top-slow-tests)",
54
+ "- [Test speed](https://docs.gitlab.com/ee/development/testing_guide/best_practices.html#test-speed)",
55
+ "**Duration**: #{test.run_time} seconds"
56
+ ].compact.join("\n\n")
57
+ end
58
+
59
+ def create_slow_issue(test)
60
+ puts " => Finding existing issues for slow test '#{test.name}' (run time: #{test.run_time} seconds)..."
61
+
62
+ issue = find_issue(test)
63
+
64
+ puts " => Existing issue link #{issue['web_url']}" if issue.present?
65
+
66
+ create_issue(test) unless issue.present?
67
+ rescue MultipleIssuesFound => e
68
+ warn(e.message)
69
+ end
70
+
71
+ def find_issue(test)
72
+ search_labels = SEARCH_LABELS
73
+
74
+ gitlab.find_issues(options: { state: 'opened', labels: search_labels.to_a }).find do |issue|
75
+ issue_title = issue.title.strip
76
+ issue_title.include?(test.name) || issue_title.include?(partial_file_path(test.file))
77
+ end
78
+ end
79
+
80
+ def should_create_slow_issue?(test)
81
+ test.run_time > max_duration_for_test(test)
82
+ end
83
+
84
+ def max_duration_for_test(test)
85
+ test_level_specification = TEST_LEVEL_SPECIFICATIONS.find do |test_level_specification|
86
+ test.example_id =~ test_level_specification.regex
87
+ end
88
+ return OTHER_TESTS_MAX_DURATION unless test_level_specification
89
+
90
+ test_level_specification.max_duration
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -115,6 +115,18 @@ module GitlabQuality
115
115
  report['feature_category']
116
116
  end
117
117
 
118
+ def run_time
119
+ report['run_time'].to_f.round(2)
120
+ end
121
+
122
+ def example_id
123
+ report['id']
124
+ end
125
+
126
+ def line_number
127
+ report['line_number']
128
+ end
129
+
118
130
  private
119
131
 
120
132
  # rubocop:disable Metrics/AbcSize
@@ -2,6 +2,6 @@
2
2
 
3
3
  module GitlabQuality
4
4
  module TestTooling
5
- VERSION = "0.8.2"
5
+ VERSION = "0.8.3"
6
6
  end
7
7
  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: 0.8.2
4
+ version: 0.8.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitLab Quality
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-06-19 00:00:00.000000000 Z
11
+ date: 2023-06-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: climate_control
@@ -323,6 +323,7 @@ executables:
323
323
  - prepare-stage-reports
324
324
  - relate-failure-issue
325
325
  - report-results
326
+ - slow-test-issues
326
327
  - update-screenshot-paths
327
328
  extensions: []
328
329
  extra_rdoc_files: []
@@ -331,6 +332,7 @@ files:
331
332
  - ".rubocop.yml"
332
333
  - ".rubocop_todo.yml"
333
334
  - ".ruby-version"
335
+ - ".tool-versions"
334
336
  - CODE_OF_CONDUCT.md
335
337
  - CONTRIBUTING.md
336
338
  - Dangerfile
@@ -345,6 +347,7 @@ files:
345
347
  - exe/prepare-stage-reports
346
348
  - exe/relate-failure-issue
347
349
  - exe/report-results
350
+ - exe/slow-test-issues
348
351
  - exe/update-screenshot-paths
349
352
  - lefthook.yml
350
353
  - lib/gitlab_quality/test_tooling.rb
@@ -352,6 +355,7 @@ files:
352
355
  - lib/gitlab_quality/test_tooling/gitlab_issue_dry_client.rb
353
356
  - lib/gitlab_quality/test_tooling/labels_inference.rb
354
357
  - lib/gitlab_quality/test_tooling/report/concerns/find_set_dri.rb
358
+ - lib/gitlab_quality/test_tooling/report/concerns/group_and_category_labels.rb
355
359
  - lib/gitlab_quality/test_tooling/report/concerns/results_reporter.rb
356
360
  - lib/gitlab_quality/test_tooling/report/concerns/utils.rb
357
361
  - lib/gitlab_quality/test_tooling/report/generate_test_session.rb
@@ -361,6 +365,7 @@ files:
361
365
  - lib/gitlab_quality/test_tooling/report/report_results.rb
362
366
  - lib/gitlab_quality/test_tooling/report/results_in_issues.rb
363
367
  - lib/gitlab_quality/test_tooling/report/results_in_test_cases.rb
368
+ - lib/gitlab_quality/test_tooling/report/slow_test_issue.rb
364
369
  - lib/gitlab_quality/test_tooling/report/update_screenshot_path.rb
365
370
  - lib/gitlab_quality/test_tooling/runtime/env.rb
366
371
  - lib/gitlab_quality/test_tooling/runtime/logger.rb