knapsack_pro 7.10.0 → 7.11.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 173300dc2ec82a1b5a15005c91ac3ceb942c40acbb14fd2ba57e64d2a32b67d8
4
- data.tar.gz: c0c856044ce6773dce0968ebd620f4c49e1fea170c30d880af90ace2e1fb66c1
3
+ metadata.gz: a1ef8aab90f4a3bec0602ae96afb11f6c74d7b8b045bfb7bb649be8a6a5df61c
4
+ data.tar.gz: f86cbe57dab02bab4b7f93096b94e73d7948f740a017beee8d44b7cf1b274a88
5
5
  SHA512:
6
- metadata.gz: e078dce53b72374ef499087c9675eea34272769a46154997e55dc06ab23e4da7fa016206297eed8b3cc660c5238a99b16177abb6f45c191e3bd38dc60c9cee6f
7
- data.tar.gz: 5a80b8cbc3dc3273e297693263a9223fab250d1ee6adbd2c6c909f904d35430f3403a1f9da92dc2709adc3f30f8311b8d05d34b6292e8952e1aae42c88f8f977
6
+ metadata.gz: 4b56ad88170012a6d956a097bfef88ccfe63a24db56e06432babbbac530ef24f0a20f43e30ddf62a604f05e80eafed1ba718b6a06733c3208d5c36dda16670c7
7
+ data.tar.gz: 2ce859941cd08128e364f4cab359dd5bc17d5d7b480bd709c38ef44762becc569cc126aac0d86258e86cb9c3172d623cd8341df7167004df5948469f9670c8cc
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ### 7.11.0
4
+
5
+ * fix(RSpec split by examples): Properly determine slow test files when test example execution times and full test file execution time are both known
6
+
7
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/281
8
+
9
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v7.10.0...v7.11.0
10
+
3
11
  ### 7.10.0
4
12
 
5
13
  * Improve the RSpec split by examples feature. Use test file execution times for existing test files on the disk to determine slow test files. This fixes issue with detecting slow test files when API token is shared between multiple test suites.
data/knapsack_pro.gemspec CHANGED
@@ -39,4 +39,5 @@ Gem::Specification.new do |spec|
39
39
  spec.add_development_dependency 'vcr', '>= 6.0'
40
40
  spec.add_development_dependency 'webmock', '>= 3.13'
41
41
  spec.add_development_dependency 'timecop', '>= 0.9.9'
42
+ spec.add_development_dependency 'ostruct', '>= 0.6.0'
42
43
  end
@@ -4,17 +4,27 @@ module KnapsackPro
4
4
  module TestCaseMergers
5
5
  class RSpecMerger < BaseMerger
6
6
  def call
7
- merged_test_files_hash = {}
7
+ all_test_files_hash = {}
8
+ merged_test_file_examples_hash = {}
9
+
8
10
  test_files.each do |test_file|
9
- test_file_path = extract_test_file_path(test_file.fetch('path'))
11
+ path = test_file.fetch('path')
12
+ test_file_path = extract_test_file_path(path)
13
+
14
+ if rspec_id_path?(path)
15
+ merged_test_file_examples_hash[test_file_path] ||= 0.0
16
+ merged_test_file_examples_hash[test_file_path] += test_file.fetch('time_execution')
17
+ else
18
+ all_test_files_hash[test_file_path] = test_file.fetch('time_execution')
19
+ end
20
+ end
10
21
 
11
- # must be float (default type for time execution from API)
12
- merged_test_files_hash[test_file_path] ||= 0.0
13
- merged_test_files_hash[test_file_path] += test_file.fetch('time_execution')
22
+ merged_test_file_examples_hash.each do |path, time_execution|
23
+ all_test_files_hash[path] = [time_execution, all_test_files_hash[path]].compact.max
14
24
  end
15
25
 
16
26
  merged_test_files = []
17
- merged_test_files_hash.each do |path, time_execution|
27
+ all_test_files_hash.each do |path, time_execution|
18
28
  merged_test_files << {
19
29
  'path' => path,
20
30
  'time_execution' => time_execution
@@ -31,6 +41,12 @@ module KnapsackPro
31
41
  def extract_test_file_path(path)
32
42
  path.gsub(/\.rb\[.+\]$/, '.rb')
33
43
  end
44
+
45
+ def rspec_id_path?(path)
46
+ path_with_id_regex = /.+_spec\.rb\[.+\]$/
47
+
48
+ path&.match?(path_with_id_regex)
49
+ end
34
50
  end
35
51
  end
36
52
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module KnapsackPro
4
- VERSION = '7.10.0'
4
+ VERSION = '7.11.0'
5
5
  end
@@ -1,6 +1,7 @@
1
1
  require 'open3'
2
2
  require 'json'
3
3
  require 'nokogiri'
4
+ require 'ostruct'
4
5
 
5
6
  describe "#{KnapsackPro::Runners::Queue::RSpecRunner} - Integration tests", :clear_tmp do
6
7
  SPEC_DIRECTORY = 'spec_integration'
@@ -1061,7 +1062,7 @@ describe "#{KnapsackPro::Runners::Queue::RSpecRunner} - Integration tests", :cle
1061
1062
  expect(actual.stdout).to_not include('C1 test example')
1062
1063
 
1063
1064
  expect(actual.stdout).to include('An error occurred while loading ./spec_integration/failing_spec.rb')
1064
- expect(actual.stdout).to match(/undefined local variable or method `a_fake_method' for.* RSpec::ExampleGroups::BDescribe/)
1065
+ expect(actual.stdout).to match(/undefined local variable or method .a_fake_method. for.* RSpec::ExampleGroups::BDescribe/)
1065
1066
  expect(actual.stdout).to include('WARN -- : [knapsack_pro] RSpec wants to quit')
1066
1067
  expect(actual.stdout).to include('1 example, 0 failures, 1 error occurred outside of examples')
1067
1068
 
@@ -1104,7 +1105,7 @@ describe "#{KnapsackPro::Runners::Queue::RSpecRunner} - Integration tests", :cle
1104
1105
  actual = subject
1105
1106
 
1106
1107
  expect(actual.stdout).to include('An error occurred while loading spec_helper.')
1107
- expect(actual.stdout).to include("undefined local variable or method `a_fake_method' for main")
1108
+ expect(actual.stdout).to match(/undefined local variable or method .a_fake_method. for main/)
1108
1109
  expect(actual.stdout).to include('0 examples, 0 failures, 1 error occurred outside of examples')
1109
1110
 
1110
1111
  expect(actual.exit_code).to eq 1
@@ -1407,9 +1408,9 @@ describe "#{KnapsackPro::Runners::Queue::RSpecRunner} - Integration tests", :cle
1407
1408
 
1408
1409
  expect(actual.stdout).to include('Use the following backtrace(s) to find the line of code that got stuck if the CI node hung and terminated your tests.')
1409
1410
  expect(actual.stdout).to include('Main thread backtrace:')
1410
- expect(actual.stdout).to include("spec_integration/b_spec.rb:7:in `kill'")
1411
+ expect(actual.stdout).to match(/spec_integration\/b_spec\.rb:7:in .*kill/)
1411
1412
  expect(actual.stdout).to include('Non-main thread backtrace:')
1412
- expect(actual.stdout).to include("spec_integration/a_spec.rb:6:in `sleep'")
1413
+ expect(actual.stdout).to match(/spec_integration\/a_spec\.rb:6:in .*sleep/)
1413
1414
 
1414
1415
 
1415
1416
  expect(actual.exit_code).to eq 1
@@ -2019,7 +2020,7 @@ describe "#{KnapsackPro::Runners::Queue::RSpecRunner} - Integration tests", :cle
2019
2020
 
2020
2021
  actual = subject
2021
2022
 
2022
- expect(actual.stdout).to include('DEBUG -- : [knapsack_pro] Detected 1 slow test files: [{"path"=>"spec_integration/a_spec.rb"}]')
2023
+ expect(actual.stdout).to match(/DEBUG -- : \[knapsack_pro\] Detected 1 slow test files: \[\{"path".?=>.?"spec_integration\/a_spec\.rb"\}\]/)
2023
2024
 
2024
2025
  expect(actual.stdout).to include(
2025
2026
  <<~OUTPUT
@@ -2,7 +2,7 @@ describe KnapsackPro::TestCaseMergers::RSpecMerger do
2
2
  describe '#call' do
3
3
  subject { described_class.new(test_files).call }
4
4
 
5
- context 'when all test files are not test example paths' do
5
+ context 'when test files are regular file paths (not test example paths)' do
6
6
  let(:test_files) do
7
7
  [
8
8
  { 'path' => 'spec/a_spec.rb', 'time_execution' => 1.1 },
@@ -10,7 +10,7 @@ describe KnapsackPro::TestCaseMergers::RSpecMerger do
10
10
  ]
11
11
  end
12
12
 
13
- it do
13
+ it 'returns the test files unchanged' do
14
14
  expect(subject).to eq([
15
15
  { 'path' => 'spec/a_spec.rb', 'time_execution' => 1.1 },
16
16
  { 'path' => 'spec/b_spec.rb', 'time_execution' => 2.2 },
@@ -28,7 +28,7 @@ describe KnapsackPro::TestCaseMergers::RSpecMerger do
28
28
  ]
29
29
  end
30
30
 
31
- it 'returns merged paths for test examples and sum of their time_execution' do
31
+ it 'merges the test example paths and sums their execution times' do
32
32
  expect(subject).to eq([
33
33
  { 'path' => 'spec/a_spec.rb', 'time_execution' => 1.1 },
34
34
  { 'path' => 'spec/test_case_spec.rb', 'time_execution' => 3.0 },
@@ -36,23 +36,45 @@ describe KnapsackPro::TestCaseMergers::RSpecMerger do
36
36
  end
37
37
  end
38
38
 
39
- context 'when test files have test example paths and at the same time test file path for test example path is present as full test file path' do
40
- let(:test_files) do
41
- [
42
- { 'path' => 'spec/a_spec.rb', 'time_execution' => 1.1 },
43
- # full test file path is present despite existing test example paths
44
- { 'path' => 'spec/test_case_spec.rb', 'time_execution' => 1.0 },
45
- # test example paths
46
- { 'path' => 'spec/test_case_spec.rb[1:1]', 'time_execution' => 2.2 },
47
- { 'path' => 'spec/test_case_spec.rb[1:2]', 'time_execution' => 0.8 },
48
- ]
39
+ context 'when test files have test example paths and the full test file path exists simultaneously' do
40
+ context 'when the full test file path has a higher execution time than the sum of test example paths' do
41
+ let(:test_files) do
42
+ [
43
+ { 'path' => 'spec/a_spec.rb', 'time_execution' => 1.1 },
44
+ # full test file path exists alongside test example paths
45
+ { 'path' => 'spec/test_case_spec.rb', 'time_execution' => 3.1 },
46
+ # test example paths
47
+ { 'path' => 'spec/test_case_spec.rb[1:1]', 'time_execution' => 2.2 },
48
+ { 'path' => 'spec/test_case_spec.rb[1:2]', 'time_execution' => 0.8 },
49
+ ]
50
+ end
51
+
52
+ it 'returns the full test file path execution time' do
53
+ expect(subject).to eq([
54
+ { 'path' => 'spec/a_spec.rb', 'time_execution' => 1.1 },
55
+ { 'path' => 'spec/test_case_spec.rb', 'time_execution' => 3.1 },
56
+ ])
57
+ end
49
58
  end
50
59
 
51
- it 'returns merged paths for test examples and sum of their time_execution' do
52
- expect(subject).to eq([
53
- { 'path' => 'spec/a_spec.rb', 'time_execution' => 1.1 },
54
- { 'path' => 'spec/test_case_spec.rb', 'time_execution' => 4.0 },
55
- ])
60
+ context 'when the full test file path has a lower execution time than the sum of test example paths' do
61
+ let(:test_files) do
62
+ [
63
+ { 'path' => 'spec/a_spec.rb', 'time_execution' => 1.1 },
64
+ # full test file path exists alongside test example paths
65
+ { 'path' => 'spec/test_case_spec.rb', 'time_execution' => 2.9 },
66
+ # test example paths
67
+ { 'path' => 'spec/test_case_spec.rb[1:1]', 'time_execution' => 2.2 },
68
+ { 'path' => 'spec/test_case_spec.rb[1:2]', 'time_execution' => 0.8 },
69
+ ]
70
+ end
71
+
72
+ it "returns the sum of test example paths' execution times" do
73
+ expect(subject).to eq([
74
+ { 'path' => 'spec/a_spec.rb', 'time_execution' => 1.1 },
75
+ { 'path' => 'spec/test_case_spec.rb', 'time_execution' => 3.0 },
76
+ ])
77
+ end
56
78
  end
57
79
  end
58
80
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: knapsack_pro
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.10.0
4
+ version: 7.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ArturT
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-10-29 00:00:00.000000000 Z
11
+ date: 2024-10-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -178,6 +178,20 @@ dependencies:
178
178
  - - ">="
179
179
  - !ruby/object:Gem::Version
180
180
  version: 0.9.9
181
+ - !ruby/object:Gem::Dependency
182
+ name: ostruct
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: 0.6.0
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: 0.6.0
181
195
  description: Knapsack Pro wraps your current test runner(s) and works with your existing
182
196
  CI infrastructure to parallelize tests optimally. It dynamically splits your tests
183
197
  based on up-to-date test execution data. It's designed from the ground up for CI