knapsack_pro 2.18.1 → 2.18.2

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: dfa70d9f5566c820f5ca45bc6c0dc52302ee7de056f4b50ad86739b3ca34960d
4
- data.tar.gz: a5c877f7c89a4c94bbcd247a6fe75b8ff01a9e2be7f82b82fe4ac42dcdac489c
3
+ metadata.gz: 6a298724c7651190199978edc99b96116abcbb827d12237e128f2c5d87297847
4
+ data.tar.gz: 2750130109b114747278d86fd4bc2477d143b2f1f3564f7b36d224f5044e29cf
5
5
  SHA512:
6
- metadata.gz: 390be4aa9a3bfa79da3149bbc7acdec09905aed17ddbac32998e7324cc23571bcb321e3ba541d3890df1993ab5a125c10edf5cfcf28f8568347ff96af8b18a94
7
- data.tar.gz: 431ec87a1b9c17fb9e2c5dfde14d93118e0378731f6c70ff7fcb1ed4f74dcef773bd861be33d0d4327689d4d8fb9df333df59630f44c9be3212b3915f2ab5cd4
6
+ metadata.gz: 7742dbaf98eb6bc1aeda1c15c2dd3b8f627fe27c91fa58a4f46e71d2ff4839d5899005b36deddcb619745689dd6426f9319df1b70ad26f317be2cea2e6922799
7
+ data.tar.gz: a102bc5ab00cabc5ec4f7007e52081fd97ca194ea8e84072b2df8fb66664c6e320ea7b76d0970aa702ed9549e36bd5c702a7156de914b5fbdf9fe00c43de8351
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Change Log
2
2
 
3
+ ### 2.18.2
4
+
5
+ * Track all test files assigned to a CI node in Regular Mode including pending test files in order to retry proper set of tests on the retried CI node
6
+
7
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/152
8
+
9
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v2.18.1...v2.18.2
10
+
3
11
  ### 2.18.1
4
12
 
5
13
  * Ensure RSpec is loaded to check its version for RSpec split by test examples feature
data/README.md CHANGED
@@ -440,13 +440,13 @@ If your test suite is very long and the RSpec output is too long for your CI nod
440
440
  ### Additional info about queue mode
441
441
 
442
442
  * You should use a separate API token for queue mode than for regular mode to avoid problems with test suite split (especially in case you would like to go back to regular mode).
443
- There might be some cached test suite splits for git commits you have run in past for API token you used in queue mode because of the [flag `KNAPSACK_PRO_FIXED_TEST_SUITE_SPLIT=true` for regular mode which is default](#knapsack_pro_fixed_test_suite_splite-test-suite-split-based-on-seed).
443
+ There might be some cached test suite splits for git commits you have run in past for API token you used in queue mode because of the [flag `KNAPSACK_PRO_FIXED_TEST_SUITE_SPLIT=true` for regular mode which is default](#knapsack_pro_fixed_test_suite_split-test-suite-split-based-on-seed).
444
444
 
445
445
  * If you are not using one of the [supported CI providers](#supported-ci-providers) then please note that the knapsack_pro gem doesn't have a CI build ID in order to generate a queue for each particular CI build. This may result in two different CI builds taking tests from the same queue when CI builds are running at the same time against the same git commit.
446
446
 
447
447
  To avoid this you should specify a unique `KNAPSACK_PRO_CI_NODE_BUILD_ID` environment variable for each CI build. This mean that each CI node that is part of particular CI build should have the same value for `KNAPSACK_PRO_CI_NODE_BUILD_ID`.
448
448
 
449
- * Note that in the Queue Mode by default you cannot retry the failed CI node with exactly the same subset of tests that were run on the CI node in the first place. It's possible in regular mode ([read more](#knapsack_pro_fixed_test_suite_splite-test-suite-split-based-on-seed)). If you want to have similar behavior in Queue Mode you need to explicitly [enable it](#knapsack_pro_fixed_queue_split-remember-queue-split-on-retry-ci-node).
449
+ * Note that in the Queue Mode by default you cannot retry the failed CI node with exactly the same subset of tests that were run on the CI node in the first place. It's possible in regular mode ([read more](#knapsack_pro_fixed_test_suite_split-test-suite-split-based-on-seed)). If you want to have similar behavior in Queue Mode you need to explicitly [enable it](#knapsack_pro_fixed_queue_split-remember-queue-split-on-retry-ci-node).
450
450
 
451
451
  By default the Queue Mode works this way:
452
452
 
@@ -626,7 +626,7 @@ This is only for maintainer of knapsack_pro gem. Not for the end users.
626
626
 
627
627
  ### Required CI configuration if you use retry single failed CI node feature on your CI server when KNAPSACK_PRO_FIXED_QUEUE_SPLIT=true (in Queue Mode) or KNAPSACK_PRO_FIXED_TEST_SUITE_SPLIT=true (in Regular Mode)
628
628
 
629
- Read below required configuration step if you use Queue Mode and you set [`KNAPSACK_PRO_FIXED_QUEUE_SPLIT=true`](#knapsack_pro_fixed_queue_split-remember-queue-split-on-retry-ci-node) or you use Regular Mode which has by default [`KNAPSACK_PRO_FIXED_TEST_SUITE_SPLIT=true`](#knapsack_pro_fixed_test_suite_splite-test-suite-split-based-on-seed).
629
+ Read below required configuration step if you use Queue Mode and you set [`KNAPSACK_PRO_FIXED_QUEUE_SPLIT=true`](#knapsack_pro_fixed_queue_split-remember-queue-split-on-retry-ci-node) or you use Regular Mode which has by default [`KNAPSACK_PRO_FIXED_TEST_SUITE_SPLIT=true`](#knapsack_pro_fixed_test_suite_split-test-suite-split-based-on-seed).
630
630
 
631
631
  * __IMPORTANT:__ If you use __the feature to retry only a single failed CI node__ on your CI server (for instance you use Buildkite and you use [auto-retry](https://buildkite.com/docs/pipelines/command-step#retry-attributes) for the failed job) then you need to be aware of [a race condition that could happen](https://github.com/KnapsackPro/knapsack_pro-ruby/pull/100). knapsack_pro should not allow running tests in Fallback Mode in the case when the failed CI node was retried to prevent running the wrong set of tests.
632
632
 
@@ -257,6 +257,14 @@ module KnapsackPro
257
257
  ENV['KNAPSACK_PRO_LOG_DIR']
258
258
  end
259
259
 
260
+ def test_runner_adapter
261
+ ENV['KNAPSACK_PRO_TEST_RUNNER_ADAPTER']
262
+ end
263
+
264
+ def set_test_runner_adapter(adapter_class)
265
+ ENV['KNAPSACK_PRO_TEST_RUNNER_ADAPTER'] = adapter_class.to_s.split('::').last
266
+ end
267
+
260
268
  private
261
269
 
262
270
  def required_env(env_name)
@@ -6,11 +6,14 @@ module KnapsackPro
6
6
  ENV['KNAPSACK_PRO_RECORDING_ENABLED'] = 'true'
7
7
 
8
8
  adapter_class = KnapsackPro::Adapters::CucumberAdapter
9
+ KnapsackPro::Config::Env.set_test_runner_adapter(adapter_class)
9
10
  runner = new(adapter_class)
10
11
 
11
12
  if runner.test_files_to_execute_exist?
12
13
  adapter_class.verify_bind_method_called
13
14
 
15
+ KnapsackPro.tracker.set_prerun_tests(runner.test_file_paths)
16
+
14
17
  require 'cucumber/rake/task'
15
18
 
16
19
  task_name = 'knapsack_pro:cucumber_run'
@@ -6,11 +6,14 @@ module KnapsackPro
6
6
  ENV['KNAPSACK_PRO_RECORDING_ENABLED'] = 'true'
7
7
 
8
8
  adapter_class = KnapsackPro::Adapters::MinitestAdapter
9
+ KnapsackPro::Config::Env.set_test_runner_adapter(adapter_class)
9
10
  runner = new(adapter_class)
10
11
 
11
12
  if runner.test_files_to_execute_exist?
12
13
  adapter_class.verify_bind_method_called
13
14
 
15
+ KnapsackPro.tracker.set_prerun_tests(runner.test_file_paths)
16
+
14
17
  task_name = 'knapsack_pro:minitest_run'
15
18
 
16
19
  if Rake::Task.task_defined?(task_name)
@@ -9,7 +9,9 @@ module KnapsackPro
9
9
  ENV['KNAPSACK_PRO_QUEUE_RECORDING_ENABLED'] = 'true'
10
10
  ENV['KNAPSACK_PRO_QUEUE_ID'] = KnapsackPro::Config::EnvGenerator.set_queue_id
11
11
 
12
- runner = new(KnapsackPro::Adapters::CucumberAdapter)
12
+ adapter_class = KnapsackPro::Adapters::CucumberAdapter
13
+ KnapsackPro::Config::Env.set_test_runner_adapter(adapter_class)
14
+ runner = new(adapter_class)
13
15
 
14
16
  accumulator = {
15
17
  status: :next,
@@ -9,7 +9,9 @@ module KnapsackPro
9
9
  ENV['KNAPSACK_PRO_QUEUE_RECORDING_ENABLED'] = 'true'
10
10
  ENV['KNAPSACK_PRO_QUEUE_ID'] = KnapsackPro::Config::EnvGenerator.set_queue_id
11
11
 
12
- runner = new(KnapsackPro::Adapters::MinitestAdapter)
12
+ adapter_class = KnapsackPro::Adapters::MinitestAdapter
13
+ KnapsackPro::Config::Env.set_test_runner_adapter(adapter_class)
14
+ runner = new(adapter_class)
13
15
 
14
16
  # Add test_dir to load path to make work:
15
17
  # require 'test_helper'
@@ -12,6 +12,7 @@ module KnapsackPro
12
12
  ENV['KNAPSACK_PRO_QUEUE_ID'] = KnapsackPro::Config::EnvGenerator.set_queue_id
13
13
 
14
14
  adapter_class = KnapsackPro::Adapters::RSpecAdapter
15
+ KnapsackPro::Config::Env.set_test_runner_adapter(adapter_class)
15
16
  runner = new(adapter_class)
16
17
 
17
18
  cli_args = (args || '').split
@@ -6,6 +6,7 @@ module KnapsackPro
6
6
  ENV['KNAPSACK_PRO_RECORDING_ENABLED'] = 'true'
7
7
 
8
8
  adapter_class = KnapsackPro::Adapters::RSpecAdapter
9
+ KnapsackPro::Config::Env.set_test_runner_adapter(adapter_class)
9
10
  runner = new(adapter_class)
10
11
 
11
12
  if runner.test_files_to_execute_exist?
@@ -14,6 +15,8 @@ module KnapsackPro
14
15
  cli_args = (args || '').split
15
16
  adapter_class.ensure_no_tag_option_when_rspec_split_by_test_examples_enabled!(cli_args)
16
17
 
18
+ KnapsackPro.tracker.set_prerun_tests(runner.test_file_paths)
19
+
17
20
  require 'rspec/core/rake_task'
18
21
 
19
22
  task_name = 'knapsack_pro:rspec_run'
@@ -5,11 +5,14 @@ module KnapsackPro
5
5
  ENV['KNAPSACK_PRO_TEST_SUITE_TOKEN'] = KnapsackPro::Config::Env.test_suite_token_spinach
6
6
 
7
7
  adapter_class = KnapsackPro::Adapters::SpinachAdapter
8
+ KnapsackPro::Config::Env.set_test_runner_adapter(adapter_class)
8
9
  runner = new(adapter_class)
9
10
 
10
11
  if runner.test_files_to_execute_exist?
11
12
  adapter_class.verify_bind_method_called
12
13
 
14
+ KnapsackPro.tracker.set_prerun_tests(runner.test_file_paths)
15
+
13
16
  cmd = %Q[KNAPSACK_PRO_RECORDING_ENABLED=true KNAPSACK_PRO_TEST_SUITE_TOKEN=#{ENV['KNAPSACK_PRO_TEST_SUITE_TOKEN']} bundle exec spinach #{args} --features_path #{runner.test_dir} -- #{runner.stringify_test_file_paths}]
14
17
 
15
18
  Kernel.system(cmd)
@@ -6,11 +6,14 @@ module KnapsackPro
6
6
  ENV['KNAPSACK_PRO_RECORDING_ENABLED'] = 'true'
7
7
 
8
8
  adapter_class = KnapsackPro::Adapters::TestUnitAdapter
9
+ KnapsackPro::Config::Env.set_test_runner_adapter(adapter_class)
9
10
  runner = new(adapter_class)
10
11
 
11
12
  if runner.test_files_to_execute_exist?
12
13
  adapter_class.verify_bind_method_called
13
14
 
15
+ KnapsackPro.tracker.set_prerun_tests(runner.test_file_paths)
16
+
14
17
  cli_args =
15
18
  (args || '').split +
16
19
  runner.test_file_paths.map do |f|
@@ -6,16 +6,22 @@ module KnapsackPro
6
6
  # to better allocate it in Queue Mode for future CI build runs
7
7
  DEFAULT_TEST_FILE_TIME = 0.0 # seconds
8
8
 
9
- attr_reader :global_time_since_beginning, :global_time, :test_files_with_time
9
+ attr_reader :global_time_since_beginning, :global_time, :test_files_with_time, :prerun_tests_loaded
10
10
  attr_writer :current_test_path
11
11
 
12
12
  def initialize
13
13
  @global_time_since_beginning = 0
14
+ FileUtils.mkdir_p(tracker_dir_path)
14
15
  set_defaults
15
16
  end
16
17
 
17
18
  def reset!
18
19
  set_defaults
20
+
21
+ # Remove report only when the reset! method is called explicitly.
22
+ # The report should be persisted on the disk so that multiple tracker instances can share the report state.
23
+ # Tracker instance can be created by knapsack_pro process and a separate tracker is created by rake task (e.g., RSpec) in Regular Mode.
24
+ File.delete(prerun_tests_report_path) if File.exists?(prerun_tests_report_path)
19
25
  end
20
26
 
21
27
  def start_timer
@@ -54,9 +60,18 @@ module KnapsackPro
54
60
  measured_time: false,
55
61
  }
56
62
  end
63
+
64
+ save_prerun_tests_report(@test_files_with_time)
65
+
66
+ @prerun_tests_loaded = true
57
67
  end
58
68
 
59
69
  def to_a
70
+ # When the test files are not loaded in the memory then load them from the disk.
71
+ # Useful for the Regular Mode when the memory is not shared between tracker instances.
72
+ # Tracker instance can be created by knapsack_pro process and a separate tracker is created by rake task (e.g., RSpec)
73
+ load_prerun_tests unless prerun_tests_loaded
74
+
60
75
  test_files = []
61
76
  @test_files_with_time.each do |path, hash|
62
77
  test_files << {
@@ -73,6 +88,44 @@ module KnapsackPro
73
88
  @global_time = 0
74
89
  @test_files_with_time = {}
75
90
  @current_test_path = nil
91
+ @prerun_tests_loaded = false
92
+ end
93
+
94
+ def tracker_dir_path
95
+ "#{KnapsackPro::Config::Env::TMP_DIR}/tracker"
96
+ end
97
+
98
+ def prerun_tests_report_path
99
+ raise 'Test runner adapter not set. Report a bug to the Knapsack Pro support.' unless KnapsackPro::Config::Env.test_runner_adapter
100
+ report_name = "prerun_tests_#{KnapsackPro::Config::Env.test_runner_adapter}_node_#{KnapsackPro::Config::Env.ci_node_index}.json"
101
+ File.join(tracker_dir_path, report_name)
102
+ end
103
+
104
+ def save_prerun_tests_report(hash)
105
+ report_json = JSON.pretty_generate(hash)
106
+
107
+ File.open(prerun_tests_report_path, 'w+') do |f|
108
+ f.write(report_json)
109
+ end
110
+ end
111
+
112
+ def read_prerun_tests_report
113
+ JSON.parse(File.read(prerun_tests_report_path))
114
+ end
115
+
116
+ def load_prerun_tests
117
+ read_prerun_tests_report.each do |test_file_path, hash|
118
+ # Load only test files that were not measured. For example,
119
+ # track test files assigned to CI node but never executed by test runner (e.g., pending RSpec spec files).
120
+ next if @test_files_with_time.key?(test_file_path)
121
+
122
+ @test_files_with_time[test_file_path] = {
123
+ time_execution: hash.fetch('time_execution'),
124
+ measured_time: hash.fetch('measured_time'),
125
+ }
126
+ end
127
+
128
+ @prerun_tests_loaded = true
76
129
  end
77
130
 
78
131
  def update_global_time(execution_time)
@@ -1,3 +1,3 @@
1
1
  module KnapsackPro
2
- VERSION = '2.18.1'
2
+ VERSION = '2.18.2'
3
3
  end
@@ -950,4 +950,29 @@ describe KnapsackPro::Config::Env do
950
950
  it { should be_nil }
951
951
  end
952
952
  end
953
+
954
+ describe '.test_runner_adapter' do
955
+ subject { described_class.test_runner_adapter }
956
+
957
+ context 'when ENV exists' do
958
+ let(:test_runner_adapter) { 'RSpecAdapter' }
959
+ before { stub_const('ENV', { 'KNAPSACK_PRO_TEST_RUNNER_ADAPTER' => test_runner_adapter }) }
960
+ it { should eql 'RSpecAdapter' }
961
+ end
962
+
963
+ context "when ENV doesn't exist" do
964
+ it { should be_nil }
965
+ end
966
+ end
967
+
968
+ describe '.set_test_runner_adapter' do
969
+ let(:adapter_class) { KnapsackPro::Adapters::RSpecAdapter }
970
+
971
+ subject { described_class.set_test_runner_adapter(adapter_class) }
972
+
973
+ it 'sets test runner adapter' do
974
+ subject
975
+ expect(described_class.test_runner_adapter).to eql 'RSpecAdapter'
976
+ end
977
+ end
953
978
  end
@@ -18,16 +18,20 @@ describe KnapsackPro::Runners::CucumberRunner do
18
18
  expect(ENV).to receive(:[]=).with('KNAPSACK_PRO_TEST_SUITE_TOKEN', test_suite_token_cucumber)
19
19
  expect(ENV).to receive(:[]=).with('KNAPSACK_PRO_RECORDING_ENABLED', 'true')
20
20
 
21
+ expect(KnapsackPro::Config::Env).to receive(:set_test_runner_adapter).with(KnapsackPro::Adapters::CucumberAdapter)
22
+
21
23
  expect(described_class).to receive(:new)
22
24
  .with(KnapsackPro::Adapters::CucumberAdapter).and_return(runner)
23
25
  end
24
26
 
25
27
  context 'when test files were returned by Knapsack Pro API' do
26
28
  let(:test_dir) { 'fake-test-dir' }
27
- let(:stringify_test_file_paths) { 'features/fake1.scenario features/fake2.scenario' }
29
+ let(:test_file_paths) { ['features/fake1.scenario', 'features/fake2.scenario'] }
30
+ let(:stringify_test_file_paths) { test_file_paths.join(' ') }
28
31
  let(:runner) do
29
32
  instance_double(described_class,
30
33
  test_dir: test_dir,
34
+ test_file_paths: test_file_paths,
31
35
  stringify_test_file_paths: stringify_test_file_paths,
32
36
  test_files_to_execute_exist?: true)
33
37
  end
@@ -36,6 +40,10 @@ describe KnapsackPro::Runners::CucumberRunner do
36
40
  before do
37
41
  expect(KnapsackPro::Adapters::CucumberAdapter).to receive(:verify_bind_method_called)
38
42
 
43
+ tracker = instance_double(KnapsackPro::Tracker)
44
+ expect(KnapsackPro).to receive(:tracker).and_return(tracker)
45
+ expect(tracker).to receive(:set_prerun_tests).with(test_file_paths)
46
+
39
47
  expect(Rake::Task).to receive(:[]).with('knapsack_pro:cucumber_run').at_least(1).and_return(task)
40
48
 
41
49
  t = double
@@ -19,6 +19,8 @@ describe KnapsackPro::Runners::Queue::CucumberRunner do
19
19
  expect(ENV).to receive(:[]=).with('KNAPSACK_PRO_QUEUE_RECORDING_ENABLED', 'true')
20
20
  expect(ENV).to receive(:[]=).with('KNAPSACK_PRO_QUEUE_ID', queue_id)
21
21
 
22
+ expect(KnapsackPro::Config::Env).to receive(:set_test_runner_adapter).with(KnapsackPro::Adapters::CucumberAdapter)
23
+
22
24
  expect(described_class).to receive(:new).with(KnapsackPro::Adapters::CucumberAdapter).and_return(runner)
23
25
  end
24
26
 
@@ -19,6 +19,8 @@ describe KnapsackPro::Runners::Queue::MinitestRunner do
19
19
  expect(ENV).to receive(:[]=).with('KNAPSACK_PRO_QUEUE_RECORDING_ENABLED', 'true')
20
20
  expect(ENV).to receive(:[]=).with('KNAPSACK_PRO_QUEUE_ID', queue_id)
21
21
 
22
+ expect(KnapsackPro::Config::Env).to receive(:set_test_runner_adapter).with(KnapsackPro::Adapters::MinitestAdapter)
23
+
22
24
  expect(described_class).to receive(:new).with(KnapsackPro::Adapters::MinitestAdapter).and_return(runner)
23
25
 
24
26
  expect($LOAD_PATH).to receive(:unshift).with(test_dir)
@@ -26,6 +26,8 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
26
26
  expect(ENV).to receive(:[]=).with('KNAPSACK_PRO_QUEUE_RECORDING_ENABLED', 'true')
27
27
  expect(ENV).to receive(:[]=).with('KNAPSACK_PRO_QUEUE_ID', queue_id)
28
28
 
29
+ expect(KnapsackPro::Config::Env).to receive(:set_test_runner_adapter).with(KnapsackPro::Adapters::RSpecAdapter)
30
+
29
31
  expect(described_class).to receive(:new).with(KnapsackPro::Adapters::RSpecAdapter).and_return(runner)
30
32
  end
31
33
 
@@ -18,16 +18,20 @@ describe KnapsackPro::Runners::RSpecRunner do
18
18
  expect(ENV).to receive(:[]=).with('KNAPSACK_PRO_TEST_SUITE_TOKEN', test_suite_token_rspec)
19
19
  expect(ENV).to receive(:[]=).with('KNAPSACK_PRO_RECORDING_ENABLED', 'true')
20
20
 
21
+ expect(KnapsackPro::Config::Env).to receive(:set_test_runner_adapter).with(KnapsackPro::Adapters::RSpecAdapter)
22
+
21
23
  expect(described_class).to receive(:new)
22
24
  .with(KnapsackPro::Adapters::RSpecAdapter).and_return(runner)
23
25
  end
24
26
 
25
27
  context 'when test files were returned by Knapsack Pro API' do
26
28
  let(:test_dir) { 'fake-test-dir' }
27
- let(:stringify_test_file_paths) { "spec/a_spec.rb spec/b_spec.rb[1:1]" }
29
+ let(:test_file_paths) { ['spec/a_spec.rb', 'spec/b_spec.rb[1:1]'] }
30
+ let(:stringify_test_file_paths) { test_file_paths.join(' ') }
28
31
  let(:runner) do
29
32
  instance_double(described_class,
30
33
  test_dir: test_dir,
34
+ test_file_paths: test_file_paths,
31
35
  stringify_test_file_paths: stringify_test_file_paths,
32
36
  test_files_to_execute_exist?: true)
33
37
  end
@@ -37,6 +41,10 @@ describe KnapsackPro::Runners::RSpecRunner do
37
41
  expect(KnapsackPro::Adapters::RSpecAdapter).to receive(:verify_bind_method_called).ordered
38
42
  expect(KnapsackPro::Adapters::RSpecAdapter).to receive(:ensure_no_tag_option_when_rspec_split_by_test_examples_enabled!).with(['--profile', '--color']).ordered
39
43
 
44
+ tracker = instance_double(KnapsackPro::Tracker)
45
+ expect(KnapsackPro).to receive(:tracker).and_return(tracker)
46
+ expect(tracker).to receive(:set_prerun_tests).with(test_file_paths)
47
+
40
48
  expect(Rake::Task).to receive(:[]).with('knapsack_pro:rspec_run').at_least(1).and_return(task)
41
49
 
42
50
  t = double
@@ -11,16 +11,20 @@ describe KnapsackPro::Runners::SpinachRunner do
11
11
  before do
12
12
  stub_const("ENV", { 'KNAPSACK_PRO_TEST_SUITE_TOKEN_SPINACH' => 'spinach-token' })
13
13
 
14
+ expect(KnapsackPro::Config::Env).to receive(:set_test_runner_adapter).with(KnapsackPro::Adapters::SpinachAdapter)
15
+
14
16
  expect(described_class).to receive(:new)
15
17
  .with(KnapsackPro::Adapters::SpinachAdapter).and_return(runner)
16
18
  end
17
19
 
18
20
  context 'when test files were returned by Knapsack Pro API' do
19
- let(:stringify_test_file_paths) { 'features/a.feature features/b.feature' }
21
+ let(:test_file_paths) { ['features/a.feature', 'features/b.feature'] }
22
+ let(:stringify_test_file_paths) { test_file_paths.join(' ') }
20
23
  let(:test_dir) { 'fake-test-dir' }
21
24
  let(:runner) do
22
25
  instance_double(described_class,
23
26
  test_dir: test_dir,
27
+ test_file_paths: test_file_paths,
24
28
  stringify_test_file_paths: stringify_test_file_paths,
25
29
  test_files_to_execute_exist?: true)
26
30
  end
@@ -29,6 +33,10 @@ describe KnapsackPro::Runners::SpinachRunner do
29
33
  before do
30
34
  expect(KnapsackPro::Adapters::SpinachAdapter).to receive(:verify_bind_method_called)
31
35
 
36
+ tracker = instance_double(KnapsackPro::Tracker)
37
+ expect(KnapsackPro).to receive(:tracker).and_return(tracker)
38
+ expect(tracker).to receive(:set_prerun_tests).with(test_file_paths)
39
+
32
40
  expect(Kernel).to receive(:system).with('KNAPSACK_PRO_RECORDING_ENABLED=true KNAPSACK_PRO_TEST_SUITE_TOKEN=spinach-token bundle exec spinach --custom-arg --features_path fake-test-dir -- features/a.feature features/b.feature')
33
41
 
34
42
  allow(described_class).to receive(:child_status).and_return(child_status)
@@ -1,11 +1,18 @@
1
1
  shared_examples 'default trakcer attributes' do
2
2
  it { expect(tracker.global_time).to eql 0 }
3
3
  it { expect(tracker.test_files_with_time).to eql({}) }
4
+ it { expect(tracker.prerun_tests_loaded).to be false }
4
5
  end
5
6
 
6
7
  describe KnapsackPro::Tracker do
8
+ let(:adapter) { 'RSpecAdapter' }
7
9
  let(:tracker) { described_class.send(:new) }
8
10
 
11
+ before do
12
+ allow(KnapsackPro::Config::Env).to receive(:test_runner_adapter).and_return(adapter)
13
+ allow(KnapsackPro::Config::Env).to receive(:ci_node_index).and_return(0)
14
+ end
15
+
9
16
  it_behaves_like 'default trakcer attributes'
10
17
 
11
18
  describe '#current_test_path' do
@@ -34,6 +41,10 @@ describe KnapsackPro::Tracker do
34
41
  let(:test_paths) { ['a_spec.rb', 'b_spec.rb'] }
35
42
  let(:delta) { 0.02 }
36
43
 
44
+ before do
45
+ tracker.set_prerun_tests(test_paths)
46
+ end
47
+
37
48
  shared_examples '#to_a' do
38
49
  subject { tracker.to_a }
39
50
 
@@ -55,13 +66,14 @@ describe KnapsackPro::Tracker do
55
66
  end
56
67
 
57
68
  it { expect(tracker.global_time).to be_within(delta).of(0.3) }
69
+ it { expect(tracker.prerun_tests_loaded).to be true }
58
70
  it { expect(tracker.test_files_with_time.keys.size).to eql 2 }
59
71
  it { expect(tracker.test_files_with_time['a_spec.rb'][:time_execution]).to be_within(delta).of(0.1) }
60
72
  it { expect(tracker.test_files_with_time['b_spec.rb'][:time_execution]).to be_within(delta).of(0.2) }
61
73
  it_behaves_like '#to_a'
62
74
  end
63
75
 
64
- context "with Timecop - Timecop shouldn't have impact on measured test time" do
76
+ context "with Timecop - Timecop shouldn't have impact on the measured test time" do
65
77
  let(:now) { Time.now }
66
78
 
67
79
  before do
@@ -80,6 +92,7 @@ describe KnapsackPro::Tracker do
80
92
 
81
93
  it { expect(tracker.global_time).to be > 0 }
82
94
  it { expect(tracker.global_time).to be_within(delta).of(0) }
95
+ it { expect(tracker.prerun_tests_loaded).to be true }
83
96
  it { expect(tracker.test_files_with_time.keys.size).to eql 2 }
84
97
  it { expect(tracker.test_files_with_time['a_spec.rb'][:time_execution]).to be_within(delta).of(0) }
85
98
  it { expect(tracker.test_files_with_time['b_spec.rb'][:time_execution]).to be_within(delta).of(0) }
@@ -96,6 +109,7 @@ describe KnapsackPro::Tracker do
96
109
  end
97
110
 
98
111
  it { expect(tracker.global_time).to be > 0 }
112
+ it { expect(tracker.prerun_tests_loaded).to be true }
99
113
  it { expect(tracker.test_files_with_time.keys.size).to eql 2 }
100
114
  it { expect(tracker.test_files_with_time['a_spec.rb'][:time_execution]).to eq 0 }
101
115
  it '2nd spec (b_spec.rb) should have recorded time execution - because start_time was set during first call of stop_timer for the first spec (a_spec.rb)' do
@@ -103,15 +117,62 @@ describe KnapsackPro::Tracker do
103
117
  end
104
118
  it_behaves_like '#to_a'
105
119
  end
120
+
121
+ context 'when a new tracker instance is created' do
122
+ let(:non_pending_test_paths) { ['a_spec.rb', 'b_spec.rb'] }
123
+ let(:test_paths) { non_pending_test_paths + ['pending_spec.rb'] }
124
+
125
+ before do
126
+ # measure tests only for non pending tests
127
+ non_pending_test_paths.each_with_index do |test_path, index|
128
+ tracker.current_test_path = test_path
129
+ tracker.start_timer
130
+ sleep index.to_f / 10 + 0.1
131
+ tracker.stop_timer
132
+ end
133
+ end
134
+
135
+ it '2nd tracker instance loads prerun tests from the disk' do
136
+ expect(tracker.prerun_tests_loaded).to be true
137
+ expect(tracker.to_a.size).to eq 3
138
+ expect(tracker.to_a[0][:path]).to eq 'a_spec.rb'
139
+ expect(tracker.to_a[0][:time_execution]).to be >= 0
140
+ expect(tracker.to_a[1][:path]).to eq 'b_spec.rb'
141
+ expect(tracker.to_a[1][:time_execution]).to be >= 0
142
+ expect(tracker.to_a[2][:path]).to eq 'pending_spec.rb'
143
+ expect(tracker.to_a[2][:time_execution]).to eq 0
144
+
145
+ tracker2 = described_class.send(:new)
146
+ expect(tracker2.prerun_tests_loaded).to be false
147
+ expect(tracker2.to_a.size).to eq 3
148
+ expect(tracker2.to_a[0][:path]).to eq 'a_spec.rb'
149
+ expect(tracker2.to_a[0][:time_execution]).to be >= 0
150
+ expect(tracker2.to_a[1][:path]).to eq 'b_spec.rb'
151
+ expect(tracker2.to_a[1][:time_execution]).to be >= 0
152
+ expect(tracker2.to_a[2][:path]).to eq 'pending_spec.rb'
153
+ expect(tracker2.to_a[2][:time_execution]).to eq 0
154
+ expect(tracker2.prerun_tests_loaded).to be true
155
+ end
156
+ end
106
157
  end
107
158
 
108
159
  describe '#reset!' do
160
+ let(:test_file_path) { 'a_spec.rb' }
161
+
109
162
  before do
110
- tracker.current_test_path = 'a_spec.rb'
163
+ tracker.set_prerun_tests([test_file_path])
164
+ end
165
+
166
+ before do
167
+ expect(tracker.prerun_tests_loaded).to be true
168
+
169
+ tracker.current_test_path = test_file_path
111
170
  tracker.start_timer
112
171
  sleep 0.1
113
172
  tracker.stop_timer
173
+
114
174
  expect(tracker.global_time).not_to eql 0
175
+
115
176
  tracker.reset!
116
177
  end
117
178
 
@@ -120,5 +181,9 @@ describe KnapsackPro::Tracker do
120
181
  it "global time since beginning won't be reset" do
121
182
  expect(tracker.global_time_since_beginning).to be >= 0.1
122
183
  end
184
+
185
+ it 'resets prerun_tests_loaded to false' do
186
+ expect(tracker.prerun_tests_loaded).to be false
187
+ end
123
188
  end
124
189
  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: 2.18.1
4
+ version: 2.18.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - ArturT
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-07-22 00:00:00.000000000 Z
11
+ date: 2021-07-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake