knapsack_pro 5.6.0 → 6.0.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: fa2ae33f8d962bbd8d5f1639e050f2a43e9ad28bf655d637d43ca2c23bc1d7d3
4
- data.tar.gz: 70e747f428235b65bba04ed2f748221170a6971e8982e0ab0fbbdb60177d9a94
3
+ metadata.gz: 315a4ff2f5885be68529cc0799affd8163fcad51558e4813a254b99bd057992a
4
+ data.tar.gz: 5709757ca30a22401be4dc170a926b16f5206d494d5b80c583bf03088d8570a6
5
5
  SHA512:
6
- metadata.gz: ed58c0b63af2f3301e7233c142da4165a9c2c9a4f31987d465a803d3b4fdab590137d2ef71bbf6b80b9abc95f513cea605091b5caa7fcd0598620790977cc29b
7
- data.tar.gz: 607af355f302481ca595f577428ea49565e711a790c284d7fb595f0f15106070a99e85acf4ebd5cf0e073e672ee37f9d851eb2b464c372dca550bf5c878c8050
6
+ metadata.gz: c43ee2474109d5e509fb57534857164ec0596cb018f61b44942ab261bdcb55345ac3025239fd3dde12c7d31f30841aa39aa480fb07bcab1519272788dad9c4b7
7
+ data.tar.gz: 9511b45fb2b0d59a309517ccc70ca10ebbb2b8a3cf0cfb2f2198e38a776838a402b531f64aea2ca94ce37489288dde8171b5fd36c45038014d781cba0fd5462d
data/.circleci/config.yml CHANGED
@@ -41,3 +41,5 @@ jobs:
41
41
  - run: rubocop -A --only Style/FrozenStringLiteralComment,Layout/EmptyLineAfterMagicComment lib/
42
42
 
43
43
  - run: bundle exec rspec spec
44
+
45
+ - run: bundle exec ruby spec/knapsack_pro/formatters/time_tracker_specs.rb
data/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ### 6.0.0
4
+
5
+ * __(breaking change)__ Dropped support for Turnip < 2.0.0
6
+ * Use an RSpec Formatter to track tests' execution times more accurately
7
+ * Removed `Time.raw_now`
8
+
9
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/229
10
+
11
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v5.7.0...UNRELEASED
12
+
13
+ ### 5.7.0
14
+
15
+ * Performance improvement: don't run `rake knapsack_pro:rspec_test_example_detector` when no slow test files are detected for RSpec.
16
+
17
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/225
18
+
19
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v5.6.0...v5.7.0
20
+
3
21
  ### 5.6.0
4
22
 
5
23
  * Use `frozen_string_literal: true` to reduce memory usage
data/README.md CHANGED
@@ -74,7 +74,7 @@ bundle update knapsack_pro
74
74
  RSpec:
75
75
 
76
76
  ```bash
77
- bundle exec rspec spec
77
+ bin/test
78
78
  ```
79
79
 
80
80
  Scripted tests can be found in the [Rails App With Knapsack Pro repository](https://github.com/KnapsackPro/rails-app-with-knapsack_pro/blob/master/bin/knapsack_pro_all.rb).
data/bin/test ADDED
@@ -0,0 +1,15 @@
1
+ #!/bin/bash
2
+
3
+ bundle exec ruby spec/knapsack_pro/formatters/time_tracker_specs.rb
4
+ export FORMATTERS_EXIT_CODE=$?
5
+
6
+ bundle exec rspec spec
7
+ export RSPEC_EXIT_CODE=$?
8
+
9
+ if [ "$FORMATTERS_EXIT_CODE" -ne "0" ]; then
10
+ exit $FORMATTERS_EXIT_CODE
11
+ fi
12
+
13
+ if [ "$RSPEC_EXIT_CODE" -ne "0" ]; then
14
+ exit $RSPEC_EXIT_CODE
15
+ fi
data/knapsack_pro.gemspec CHANGED
@@ -4,10 +4,10 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'knapsack_pro/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
- spec.name = "knapsack_pro"
7
+ spec.name = 'knapsack_pro'
8
8
  spec.version = KnapsackPro::VERSION
9
9
  spec.authors = ['ArturT']
10
- spec.email = ['arturtrzop@gmail.com']
10
+ spec.email = ['support@knapsackpro.com']
11
11
  spec.summary = %q{Knapsack Pro splits tests across parallel CI nodes and ensures each parallel job finish work at a similar time.}
12
12
  spec.description = %q{Run tests in parallel across CI server nodes based on tests execution time. Split tests in a dynamic way to ensure parallel jobs are done at a similar time. Thanks to that your CI build time is as fast as possible. It works with many CI providers.}
13
13
  spec.homepage = 'https://knapsackpro.com'
@@ -15,15 +15,15 @@ Gem::Specification.new do |spec|
15
15
  spec.metadata = {
16
16
  'bug_tracker_uri' => 'https://github.com/KnapsackPro/knapsack_pro-ruby/issues',
17
17
  'changelog_uri' => 'https://github.com/KnapsackPro/knapsack_pro-ruby/blob/master/CHANGELOG.md',
18
- 'documentation_uri' => 'https://docs.knapsackpro.com/integration/',
18
+ 'documentation_uri' => 'https://docs.knapsackpro.com/knapsack_pro-ruby/guide/',
19
19
  'homepage_uri' => 'https://knapsackpro.com',
20
20
  'source_code_uri' => 'https://github.com/KnapsackPro/knapsack_pro-ruby'
21
21
  }
22
22
 
23
23
  spec.files = `git ls-files -z`.split("\x0")
24
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
24
+ spec.executables = ['knapsack_pro']
25
25
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
26
- spec.require_paths = ["lib"]
26
+ spec.require_paths = ['lib']
27
27
 
28
28
  spec.add_dependency 'rake', '>= 0'
29
29
 
@@ -11,6 +11,14 @@ module KnapsackPro
11
11
  "#{KnapsackPro::Config::TempFiles::TEMP_DIRECTORY_PATH}/#{adapter_name}-bind_method_called_for_node_#{KnapsackPro::Config::Env.ci_node_index}.txt"
12
12
  end
13
13
 
14
+ def self.split_by_test_cases_enabled?
15
+ false
16
+ end
17
+
18
+ def self.test_file_cases_for(slow_test_files)
19
+ raise NotImplementedError
20
+ end
21
+
14
22
  def self.slow_test_file?(adapter_class, test_file_path)
15
23
  @slow_test_file_paths ||=
16
24
  begin
@@ -1,10 +1,41 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative '../formatters/time_tracker_fetcher'
4
+
3
5
  module KnapsackPro
4
6
  module Adapters
5
7
  class RSpecAdapter < BaseAdapter
6
8
  TEST_DIR_PATTERN = 'spec/**{,/*/**}/*_spec.rb'
7
9
 
10
+ def self.split_by_test_cases_enabled?
11
+ return false unless KnapsackPro::Config::Env.rspec_split_by_test_examples?
12
+
13
+ require 'rspec/core/version'
14
+ unless Gem::Version.new(::RSpec::Core::Version::STRING) >= Gem::Version.new('3.3.0')
15
+ raise "RSpec >= 3.3.0 is required to split test files by test examples. Learn more: #{KnapsackPro::Urls::SPLIT_BY_TEST_EXAMPLES}"
16
+ end
17
+
18
+ true
19
+ end
20
+
21
+ def self.test_file_cases_for(slow_test_files)
22
+ KnapsackPro.logger.info("Generating RSpec test examples JSON report for slow test files to prepare it to be split by test examples (by individual test cases). Thanks to that, a single slow test file can be split across parallel CI nodes. Analyzing #{slow_test_files.size} slow test files.")
23
+
24
+ # generate the RSpec JSON report in a separate process to not pollute the RSpec state
25
+ cmd = [
26
+ 'RACK_ENV=test',
27
+ 'RAILS_ENV=test',
28
+ KnapsackPro::Config::Env.rspec_test_example_detector_prefix,
29
+ 'rake knapsack_pro:rspec_test_example_detector',
30
+ ].join(' ')
31
+ unless Kernel.system(cmd)
32
+ raise "Could not generate JSON report for RSpec. Rake task failed when running #{cmd}"
33
+ end
34
+
35
+ # read the JSON report
36
+ KnapsackPro::TestCaseDetectors::RSpecTestExampleDetector.new.test_file_example_paths
37
+ end
38
+
8
39
  def self.ensure_no_tag_option_when_rspec_split_by_test_examples_enabled!(cli_args)
9
40
  if KnapsackPro::Config::Env.rspec_split_by_test_examples? && has_tag_option?(cli_args)
10
41
  error_message = "It is not allowed to use the RSpec tag option together with the RSpec split by test examples feature. Please see: #{KnapsackPro::Urls::RSPEC__SPLIT_BY_TEST_EXAMPLES__TAG}"
@@ -25,63 +56,61 @@ module KnapsackPro
25
56
  parsed_options(cli_args)&.[](:order)
26
57
  end
27
58
 
28
- def self.test_path(example)
29
- example_group = example.metadata[:example_group]
30
-
31
- if defined?(::Turnip) && Gem::Version.new(::Turnip::VERSION) < Gem::Version.new('2.0.0')
32
- unless example_group[:turnip]
33
- until example_group[:parent_example_group].nil?
34
- example_group = example_group[:parent_example_group]
35
- end
59
+ def self.file_path_for(example)
60
+ [
61
+ -> { parse_file_path(example.id) },
62
+ -> { example.metadata[:file_path] },
63
+ -> { example.metadata[:example_group][:file_path] },
64
+ -> { top_level_group(example)[:file_path] },
65
+ ]
66
+ .each do |path|
67
+ p = path.call
68
+ return p if p.include?('_spec.rb')
36
69
  end
37
- else
38
- until example_group[:parent_example_group].nil?
39
- example_group = example_group[:parent_example_group]
40
- end
41
- end
42
70
 
43
- example_group[:file_path]
71
+ return ''
44
72
  end
45
73
 
46
- def bind_time_tracker
47
- ::RSpec.configure do |config|
48
- config.prepend_before(:context) do
49
- KnapsackPro.tracker.start_timer
50
- end
74
+ def self.parse_file_path(id)
75
+ # https://github.com/rspec/rspec-core/blob/1eeadce5aa7137ead054783c31ff35cbfe9d07cc/lib/rspec/core/example.rb#L122
76
+ id.match(/\A(.*?)(?:\[([\d\s:,]+)\])?\z/).captures.first
77
+ end
51
78
 
52
- config.around(:each) do |example|
53
- current_test_path = KnapsackPro::Adapters::RSpecAdapter.test_path(example)
54
-
55
- # Stop timer to update time for a previously run test example.
56
- # This way we count time spent in runtime for the previous test example after around(:each) is already done.
57
- # Only do that if we're in the same test file. Otherwise, `before(:all)` execution time in the current file
58
- # will be applied to the previously ran test file.
59
- if KnapsackPro.tracker.current_test_path&.start_with?(KnapsackPro::TestFileCleaner.clean(current_test_path))
60
- KnapsackPro.tracker.stop_timer
61
- end
79
+ # private
80
+ def self.top_level_group(example)
81
+ group = example.metadata[:example_group]
82
+ until group[:parent_example_group].nil?
83
+ group = group[:parent_example_group]
84
+ end
85
+ group
86
+ end
62
87
 
63
- KnapsackPro.tracker.current_test_path =
64
- if KnapsackPro::Config::Env.rspec_split_by_test_examples? && KnapsackPro::Adapters::RSpecAdapter.slow_test_file?(RSpecAdapter, current_test_path)
65
- example.id
66
- else
67
- current_test_path
68
- end
88
+ def bind_time_tracker
89
+ ensure_no_focus!
90
+ log_batch_duration
91
+ end
69
92
 
93
+ def ensure_no_focus!
94
+ ::RSpec.configure do |config|
95
+ config.around(:each) do |example|
70
96
  if example.metadata[:focus] && KnapsackPro::Adapters::RSpecAdapter.rspec_configuration.filter.rules[:focus]
71
- raise "We detected a test file path #{current_test_path} with a test using the metadata `:focus` tag. RSpec might not run some tests in the Queue Mode (causing random tests skipping problem). Please remove the `:focus` tag from your codebase. See more: #{KnapsackPro::Urls::RSPEC__SKIPS_TESTS}"
97
+ file_path = KnapsackPro::Adapters::RSpecAdapter.file_path_for(example)
98
+ file_path = KnapsackPro::TestFileCleaner.clean(file_path)
99
+
100
+ raise "Knapsack Pro found an example tagged with focus in #{file_path}, please remove it. See more: #{KnapsackPro::Urls::RSPEC__SKIPS_TESTS}"
72
101
  end
73
102
 
74
103
  example.run
75
104
  end
105
+ end
106
+ end
76
107
 
77
- config.append_after(:context) do
78
- # after(:context) hook is run one time only, after all of the examples in a group
79
- # stop timer to count time for the very last executed test example
80
- KnapsackPro.tracker.stop_timer
81
- end
82
-
108
+ def log_batch_duration
109
+ ::RSpec.configure do |config|
83
110
  config.after(:suite) do
84
- KnapsackPro.logger.debug(KnapsackPro::Presenter.global_time)
111
+ time_tracker = KnapsackPro::Formatters::TimeTrackerFetcher.call
112
+ formatted = KnapsackPro::Presenter.global_time(time_tracker.batch_duration)
113
+ KnapsackPro.logger.debug(formatted)
85
114
  end
86
115
  end
87
116
  end
@@ -89,7 +118,8 @@ module KnapsackPro
89
118
  def bind_save_report
90
119
  ::RSpec.configure do |config|
91
120
  config.after(:suite) do
92
- KnapsackPro::Report.save
121
+ time_tracker = KnapsackPro::Formatters::TimeTrackerFetcher.call
122
+ KnapsackPro::Report.save(time_tracker.batch)
93
123
  end
94
124
  end
95
125
  end
@@ -35,35 +35,16 @@ module KnapsackPro
35
35
  def fast_and_slow_test_files_to_run
36
36
  test_files_to_run = all_test_files_to_run
37
37
 
38
- if adapter_class == KnapsackPro::Adapters::RSpecAdapter && KnapsackPro::Config::Env.rspec_split_by_test_examples?
39
- require 'rspec/core/version'
40
- unless Gem::Version.new(::RSpec::Core::Version::STRING) >= Gem::Version.new('3.3.0')
41
- raise "RSpec >= 3.3.0 is required to split test files by test examples. Learn more: #{KnapsackPro::Urls::SPLIT_BY_TEST_EXAMPLES}"
42
- end
43
-
38
+ if adapter_class.split_by_test_cases_enabled?
44
39
  slow_test_files = get_slow_test_files
40
+ return test_files_to_run if slow_test_files.empty?
45
41
 
46
- KnapsackPro.logger.info("Generating RSpec test examples JSON report for slow test files to prepare it to be split by test examples (by individual 'it's. Thanks to that a single slow test file can be split across parallel CI nodes). Analyzing #{slow_test_files.size} slow test files.")
47
-
48
- # generate RSpec JSON report in separate process to not pollute RSpec state
49
- cmd = [
50
- 'RACK_ENV=test',
51
- 'RAILS_ENV=test',
52
- KnapsackPro::Config::Env.rspec_test_example_detector_prefix,
53
- 'rake knapsack_pro:rspec_test_example_detector',
54
- ].join(' ')
55
- unless Kernel.system(cmd)
56
- raise "Could not generate JSON report for RSpec. Rake task failed when running #{cmd}"
57
- end
42
+ test_file_cases = adapter_class.test_file_cases_for(slow_test_files)
58
43
 
59
- # read JSON report
60
- detector = KnapsackPro::TestCaseDetectors::RSpecTestExampleDetector.new
61
- test_file_example_paths = detector.test_file_example_paths
62
-
63
- KnapsackPro::TestFilesWithTestCasesComposer.call(test_files_to_run, slow_test_files, test_file_example_paths)
64
- else
65
- test_files_to_run
44
+ return KnapsackPro::TestFilesWithTestCasesComposer.call(test_files_to_run, slow_test_files, test_file_cases)
66
45
  end
46
+
47
+ test_files_to_run
67
48
  end
68
49
 
69
50
  private
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative './time_tracker_fetcher'
4
+
3
5
  RSpec::Support.require_rspec_core('formatters/base_formatter')
4
6
  RSpec::Support.require_rspec_core('formatters/base_text_formatter')
5
7
 
@@ -76,11 +78,12 @@ module KnapsackPro
76
78
  registered_output.puts(most_recent_summary)
77
79
  end
78
80
 
79
- def self.print_exit_summary
81
+ def self.print_exit_summary(all_test_file_paths)
80
82
  registered_output.puts('Knapsack Pro Queue exited/aborted!')
81
83
  registered_output.puts('')
82
84
 
83
- unexecuted_test_files = KnapsackPro.tracker.unexecuted_test_files
85
+ time_tracker = KnapsackPro::Formatters::TimeTrackerFetcher.call
86
+ unexecuted_test_files = time_tracker&.unexecuted_test_files(all_test_file_paths) || []
84
87
  unless unexecuted_test_files.empty?
85
88
  registered_output.puts('Unexecuted tests on this CI node:')
86
89
  registered_output.puts(unexecuted_test_files)
@@ -119,7 +122,7 @@ module KnapsackPro
119
122
 
120
123
  def dump_summary(summary)
121
124
  colorizer = ::RSpec::Core::Formatters::ConsoleCodes
122
- duration = KnapsackPro.tracker.global_time_since_beginning
125
+ duration = KnapsackPro::Formatters::TimeTrackerFetcher.call.duration
123
126
  formatted_duration = ::RSpec::Core::Formatters::Helpers.format_duration(duration)
124
127
 
125
128
  formatted = "\nFinished in #{formatted_duration}\n" \
@@ -0,0 +1,161 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KnapsackPro
4
+ module Formatters
5
+ class TimeTracker
6
+ ::RSpec::Core::Formatters.register self,
7
+ :example_group_started,
8
+ :example_started,
9
+ :example_finished,
10
+ :example_group_finished,
11
+ :stop
12
+
13
+ # Called at the beginning of each batch,
14
+ # but only the first instance of this class is used,
15
+ # so don't rely on the initializer to reset values.
16
+ def initialize(_output)
17
+ @time_each = nil
18
+ @time_all = nil
19
+ @before_all = 0.0
20
+ @group = {}
21
+ @batch = {}
22
+ @queue = {}
23
+ @suite_started = now
24
+ @batch_started = now
25
+ end
26
+
27
+ def example_group_started(notification)
28
+ return unless top_level_group?(notification.group)
29
+ @time_all = now
30
+ end
31
+
32
+ def example_started(_notification)
33
+ @before_all = now - @time_all if @before_all == 0.0
34
+ @time_each = now
35
+ end
36
+
37
+ def example_finished(notification)
38
+ record_example(@group, notification.example, @time_each)
39
+ @time_all = now
40
+ end
41
+
42
+ def example_group_finished(notification)
43
+ return unless top_level_group?(notification.group)
44
+
45
+ add_hooks_time(@group, @before_all, now - @time_all)
46
+ @batch = merge(@batch, @group)
47
+ @before_all = 0.0
48
+ @group = {}
49
+ end
50
+
51
+ # Called at the end of each batch
52
+ def stop(_notification)
53
+ @queue = merge(@queue, @batch)
54
+ @batch = {}
55
+ @batch_started = now
56
+ end
57
+
58
+ def queue(scheduled_paths)
59
+ recorded_paths = @queue.values.map do |example|
60
+ KnapsackPro::Adapters::RSpecAdapter.parse_file_path(example[:path])
61
+ end
62
+
63
+ missing = (scheduled_paths - recorded_paths).each_with_object({}) do |path, object|
64
+ object[path] = { path: path, time_execution: 0.0 }
65
+ end
66
+
67
+ merge(@queue, missing).values.map do |example|
68
+ example.transform_keys(&:to_s)
69
+ end
70
+ end
71
+
72
+ def batch
73
+ @batch.values.map do |example|
74
+ example.transform_keys(&:to_s)
75
+ end
76
+ end
77
+
78
+ def duration
79
+ now - @suite_started
80
+ end
81
+
82
+ def batch_duration
83
+ now - @batch_started
84
+ end
85
+
86
+ def unexecuted_test_files(scheduled_paths)
87
+ pending_paths = (@queue.values + @batch.values)
88
+ .filter { |example| example[:time_execution] == 0.0 }
89
+ .map { |example| example[:path] }
90
+
91
+ not_run_paths = scheduled_paths -
92
+ (@queue.values + @batch.values)
93
+ .map { |example| example[:path] }
94
+
95
+ pending_paths + not_run_paths
96
+ end
97
+
98
+ private
99
+
100
+ def top_level_group?(group)
101
+ group.metadata[:parent_example_group].nil?
102
+ end
103
+
104
+ def add_hooks_time(group, before_all, after_all)
105
+ group.each do |_, example|
106
+ next if example[:time_execution] == 0.0
107
+ example[:time_execution] += before_all + after_all
108
+ end
109
+ end
110
+
111
+ def record_example(accumulator, example, started_at)
112
+ path = path_for(example)
113
+ time_execution = time_execution_for(example, started_at)
114
+
115
+ if accumulator.key?(path)
116
+ accumulator[path][:time_execution] += time_execution
117
+ else
118
+ accumulator[path] = { path: path, time_execution: time_execution }
119
+ end
120
+ end
121
+
122
+ def path_for(example)
123
+ file = file_path_for(example)
124
+ return "UNKNOWN_PATH" if file == ""
125
+ path = rspec_split_by_test_example?(file) ? example.id : file
126
+ KnapsackPro::TestFileCleaner.clean(path)
127
+ end
128
+
129
+ def rspec_split_by_test_example?(file)
130
+ return false unless KnapsackPro::Config::Env.rspec_split_by_test_examples?
131
+ return false unless KnapsackPro::Adapters::RSpecAdapter.slow_test_file?(KnapsackPro::Adapters::RSpecAdapter, file)
132
+ true
133
+ end
134
+
135
+ def file_path_for(example)
136
+ KnapsackPro::Adapters::RSpecAdapter.file_path_for(example)
137
+ end
138
+
139
+ def time_execution_for(example, started_at)
140
+ if example.execution_result.status.to_s == "pending"
141
+ 0.0
142
+ else
143
+ (now - started_at).to_f
144
+ end
145
+ end
146
+
147
+ def merge(h1, h2)
148
+ h1.merge(h2) do |key, v1, v2|
149
+ {
150
+ path: key,
151
+ time_execution: v1[:time_execution] + v2[:time_execution]
152
+ }
153
+ end
154
+ end
155
+
156
+ def now
157
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
158
+ end
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,12 @@
1
+ module KnapsackPro
2
+ module Formatters
3
+ class TimeTrackerFetcher
4
+ def self.call
5
+ ::RSpec
6
+ .configuration
7
+ .formatters
8
+ .find { |f| f.class.to_s == "KnapsackPro::Formatters::TimeTracker" }
9
+ end
10
+ end
11
+ end
12
+ end
@@ -3,8 +3,9 @@
3
3
  module KnapsackPro
4
4
  class Presenter
5
5
  class << self
6
- def global_time
7
- global_time = pretty_seconds(KnapsackPro.tracker.global_time)
6
+ def global_time(time = nil)
7
+ time = KnapsackPro.tracker.global_time if time.nil?
8
+ global_time = pretty_seconds(time)
8
9
  "Global time execution for tests: #{global_time}"
9
10
  end
10
11
 
@@ -2,15 +2,17 @@
2
2
 
3
3
  module KnapsackPro
4
4
  class Report
5
- def self.save
6
- test_files = KnapsackPro.tracker.to_a
5
+ def self.save(tests = nil)
6
+ if tests.nil?
7
+ tests = KnapsackPro.tracker.to_a
8
+ end
7
9
 
8
- if test_files.empty?
10
+ if tests.empty?
9
11
  KnapsackPro.logger.warn("No test files were executed on this CI node.")
10
12
  KnapsackPro.logger.debug("When you use knapsack_pro Regular Mode, the reason for no tests executing might be a very narrow tests list. Most likely, you run only tests with a specified tag, and there were fewer test files with the tag than parallel CI nodes.")
11
13
  end
12
14
 
13
- create_build_subset(test_files)
15
+ create_build_subset(tests)
14
16
  end
15
17
 
16
18
  def self.save_subset_queue_to_file
@@ -30,11 +32,13 @@ module KnapsackPro
30
32
  end
31
33
  end
32
34
 
33
- def self.save_node_queue_to_api
34
- test_files = []
35
- Dir.glob("#{queue_path}/*.json").each do |file|
36
- report = JSON.parse(File.read(file))
37
- test_files += report
35
+ def self.save_node_queue_to_api(test_files = nil)
36
+ if test_files.nil?
37
+ test_files = []
38
+ Dir.glob("#{queue_path}/*.json").each do |file|
39
+ report = JSON.parse(File.read(file))
40
+ test_files += report
41
+ end
38
42
  end
39
43
 
40
44
  if test_files.empty?