knapsack_pro 2.10.1 → 2.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: 9b0ef524a80bd3e88c8c12c631880e644734fc8be8253bd4aa8d9c58fcc2dc48
4
- data.tar.gz: 7fa53878c1cbf1fb421f2637c98db03133654df1abf07d058179b2516a01da49
3
+ metadata.gz: beae91b61b862b583d31eb96e90528168f2d744b85cf89ec657a2bb9eb3b605a
4
+ data.tar.gz: 2ddaec300265bd38f33438629a457d6e559f2a69ecb3e1b190deab30abebbdd1
5
5
  SHA512:
6
- metadata.gz: 6faf1e8b52b3d93c424945e560dba8caeda53a208b002c370b2e050f31aafbffd66856e06e7475043891923ef5315f40a3f6ee9e58fad243eb91fc12bde47ad7
7
- data.tar.gz: c4767bf21996e966db844779e177b10086626b6a8bfd7ffd67333842aa2376814234b54a00a945b70a676d481c70bea07ae74480c3f2359e5ab7588490194eca
6
+ metadata.gz: 17eedf845e8b54b6e3fbcb9bb53a156b63d989eb09f55f7daf82a1c458838294ffa9d5da5ce55097f0ec309d64fa4c51b1ed375cb5a9ae425bf9311cdbee952d
7
+ data.tar.gz: 6533850f09175a000f07f8933b721aee0b250725c8243111631c5ae1de174f519e95213d79ad66797d088678852c4afb072b5f13c2df37802408b5b44f855dd5
@@ -1,5 +1,13 @@
1
1
  # Change Log
2
2
 
3
+ ### 2.11.0
4
+
5
+ * Verify test runner adapter bind method is called to track test files time execution and ensure `tmp/knapsack_pro` directory is not removed accidentally
6
+
7
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/137
8
+
9
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v2.10.1...v2.11.0
10
+
3
11
  ### 2.10.1
4
12
 
5
13
  * Fix RSpec split by test examples feature broken by lazy generating of JSON report with test example ids
@@ -4,6 +4,11 @@ module KnapsackPro
4
4
  # Just example, please overwrite constant in subclass
5
5
  TEST_DIR_PATTERN = 'test/**{,/*/**}/*_test.rb'
6
6
 
7
+ def self.adapter_bind_method_called_file
8
+ adapter_name = self.to_s.gsub('::', '-')
9
+ "#{KnapsackPro::Config::Env::TMP_DIR}/#{adapter_name}-bind_method_called_for_node_#{KnapsackPro::Config::Env.ci_node_index}.txt"
10
+ end
11
+
7
12
  def self.slow_test_file?(adapter_class, test_file_path)
8
13
  @slow_test_file_paths ||=
9
14
  begin
@@ -26,7 +31,24 @@ module KnapsackPro
26
31
  adapter
27
32
  end
28
33
 
34
+ def self.verify_bind_method_called
35
+ ::Kernel.at_exit do
36
+ if File.exists?(adapter_bind_method_called_file)
37
+ File.delete(adapter_bind_method_called_file)
38
+ else
39
+ puts "\n\n"
40
+ KnapsackPro.logger.error('-'*10 + ' Configuration error ' + '-'*50)
41
+ KnapsackPro.logger.error("You forgot to call #{self}.bind method in your test runner configuration file. It is needed to record test files time execution. Please follow the installation guide to configure your project properly https://docs.knapsackpro.com/knapsack_pro-ruby/guide/")
42
+ KnapsackPro.logger.error("If you already have #{self}.bind method added and you still see this error then one of your tests must had to delete tmp/knapsack_pro directory from the disk accidentally. Please ensure you do not remove tmp/knapsack_pro directory: https://knapsackpro.com/faq/question/why-all-test-files-have-01s-time-execution-for-my-ci-build-in-user-dashboard")
43
+ Kernel.exit(1)
44
+ end
45
+ end
46
+ end
47
+
29
48
  def bind
49
+ FileUtils.mkdir_p(KnapsackPro::Config::Env::TMP_DIR)
50
+ File.write(self.class.adapter_bind_method_called_file, nil)
51
+
30
52
  if KnapsackPro::Config::Env.recording_enabled?
31
53
  KnapsackPro.logger.debug('Test suite time execution recording enabled.')
32
54
  bind_time_tracker
@@ -8,6 +8,7 @@ module KnapsackPro
8
8
  'info' => ::Logger::INFO,
9
9
  'debug' => ::Logger::DEBUG,
10
10
  }
11
+ TMP_DIR = 'tmp/knapsack_pro'
11
12
 
12
13
  class << self
13
14
  def ci_node_total
@@ -80,7 +80,7 @@ module KnapsackPro
80
80
 
81
81
  def self.queue_path
82
82
  queue_id = KnapsackPro::Config::Env.queue_id
83
- "tmp/knapsack_pro/queue/#{queue_id}"
83
+ "#{KnapsackPro::Config::Env::TMP_DIR}/queue/#{queue_id}"
84
84
  end
85
85
  end
86
86
  end
@@ -5,9 +5,12 @@ module KnapsackPro
5
5
  ENV['KNAPSACK_PRO_TEST_SUITE_TOKEN'] = KnapsackPro::Config::Env.test_suite_token_cucumber
6
6
  ENV['KNAPSACK_PRO_RECORDING_ENABLED'] = 'true'
7
7
 
8
- runner = new(KnapsackPro::Adapters::CucumberAdapter)
8
+ adapter_class = KnapsackPro::Adapters::CucumberAdapter
9
+ runner = new(adapter_class)
9
10
 
10
11
  if runner.test_files_to_execute_exist?
12
+ adapter_class.verify_bind_method_called
13
+
11
14
  require 'cucumber/rake/task'
12
15
 
13
16
  task_name = 'knapsack_pro:cucumber_run'
@@ -5,9 +5,12 @@ module KnapsackPro
5
5
  ENV['KNAPSACK_PRO_TEST_SUITE_TOKEN'] = KnapsackPro::Config::Env.test_suite_token_minitest
6
6
  ENV['KNAPSACK_PRO_RECORDING_ENABLED'] = 'true'
7
7
 
8
- runner = new(KnapsackPro::Adapters::MinitestAdapter)
8
+ adapter_class = KnapsackPro::Adapters::MinitestAdapter
9
+ runner = new(adapter_class)
9
10
 
10
11
  if runner.test_files_to_execute_exist?
12
+ adapter_class.verify_bind_method_called
13
+
11
14
  task_name = 'knapsack_pro:minitest_run'
12
15
 
13
16
  if Rake::Task.task_defined?(task_name)
@@ -39,6 +39,10 @@ module KnapsackPro
39
39
  )
40
40
 
41
41
  if test_file_paths.empty?
42
+ unless all_test_file_paths.empty?
43
+ KnapsackPro::Adapters::CucumberAdapter.verify_bind_method_called
44
+ end
45
+
42
46
  KnapsackPro::Hooks::Queue.call_after_queue
43
47
 
44
48
  KnapsackPro::Report.save_node_queue_to_api
@@ -46,6 +46,10 @@ module KnapsackPro
46
46
  )
47
47
 
48
48
  if test_file_paths.empty?
49
+ unless all_test_file_paths.empty?
50
+ KnapsackPro::Adapters::MinitestAdapter.verify_bind_method_called
51
+ end
52
+
49
53
  KnapsackPro::Hooks::Queue.call_after_queue
50
54
 
51
55
  KnapsackPro::Report.save_node_queue_to_api
@@ -53,6 +53,8 @@ module KnapsackPro
53
53
 
54
54
  if test_file_paths.empty?
55
55
  unless all_test_file_paths.empty?
56
+ KnapsackPro::Adapters::RSpecAdapter.verify_bind_method_called
57
+
56
58
  KnapsackPro::Formatters::RSpecQueueSummaryFormatter.print_summary
57
59
  KnapsackPro::Formatters::RSpecQueueProfileFormatterExtension.print_summary
58
60
 
@@ -5,9 +5,12 @@ module KnapsackPro
5
5
  ENV['KNAPSACK_PRO_TEST_SUITE_TOKEN'] = KnapsackPro::Config::Env.test_suite_token_rspec
6
6
  ENV['KNAPSACK_PRO_RECORDING_ENABLED'] = 'true'
7
7
 
8
- runner = new(KnapsackPro::Adapters::RSpecAdapter)
8
+ adapter_class = KnapsackPro::Adapters::RSpecAdapter
9
+ runner = new(adapter_class)
9
10
 
10
11
  if runner.test_files_to_execute_exist?
12
+ adapter_class.verify_bind_method_called
13
+
11
14
  require 'rspec/core/rake_task'
12
15
 
13
16
  task_name = 'knapsack_pro:rspec_run'
@@ -4,9 +4,12 @@ module KnapsackPro
4
4
  def self.run(args)
5
5
  ENV['KNAPSACK_PRO_TEST_SUITE_TOKEN'] = KnapsackPro::Config::Env.test_suite_token_spinach
6
6
 
7
- runner = new(KnapsackPro::Adapters::SpinachAdapter)
7
+ adapter_class = KnapsackPro::Adapters::SpinachAdapter
8
+ runner = new(adapter_class)
8
9
 
9
10
  if runner.test_files_to_execute_exist?
11
+ adapter_class.verify_bind_method_called
12
+
10
13
  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}]
11
14
 
12
15
  Kernel.system(cmd)
@@ -5,9 +5,12 @@ module KnapsackPro
5
5
  ENV['KNAPSACK_PRO_TEST_SUITE_TOKEN'] = KnapsackPro::Config::Env.test_suite_token_test_unit
6
6
  ENV['KNAPSACK_PRO_RECORDING_ENABLED'] = 'true'
7
7
 
8
- runner = new(KnapsackPro::Adapters::TestUnitAdapter)
8
+ adapter_class = KnapsackPro::Adapters::TestUnitAdapter
9
+ runner = new(adapter_class)
9
10
 
10
11
  if runner.test_files_to_execute_exist?
12
+ adapter_class.verify_bind_method_called
13
+
11
14
  require 'test/unit'
12
15
 
13
16
  cli_args =
@@ -1,7 +1,7 @@
1
1
  module KnapsackPro
2
2
  class SlowTestFileDeterminer
3
3
  TIME_THRESHOLD_PER_CI_NODE = 0.7 # 70%
4
- REPORT_DIR = 'tmp/knapsack_pro/slow_test_file_determiner'
4
+ REPORT_DIR = "#{KnapsackPro::Config::Env::TMP_DIR}/slow_test_file_determiner"
5
5
 
6
6
  # test_files: { 'path' => 'a_spec.rb', 'time_execution' => 0.0 }
7
7
  # time_execution: of build distribution (total time of CI build run)
@@ -1,7 +1,7 @@
1
1
  module KnapsackPro
2
2
  module TestCaseDetectors
3
3
  class RSpecTestExampleDetector
4
- REPORT_DIR = 'tmp/knapsack_pro/test_case_detectors/rspec'
4
+ REPORT_DIR = "#{KnapsackPro::Config::Env::TMP_DIR}/test_case_detectors/rspec"
5
5
 
6
6
  def generate_json_report
7
7
  require 'rspec/core'
@@ -1,3 +1,3 @@
1
1
  module KnapsackPro
2
- VERSION = '2.10.1'
2
+ VERSION = '2.11.0'
3
3
  end
@@ -22,6 +22,27 @@ describe KnapsackPro::Adapters::BaseAdapter do
22
22
  end
23
23
  end
24
24
 
25
+ describe '.adapter_bind_method_called_file' do
26
+ subject { described_class.adapter_bind_method_called_file }
27
+
28
+ before do
29
+ expect(KnapsackPro::Config::Env).to receive(:ci_node_index).and_return(ci_node_index)
30
+ end
31
+
32
+ context 'when CI node index 0' do
33
+ let(:ci_node_index) { 0 }
34
+
35
+ it { expect(subject).to eq 'tmp/knapsack_pro/KnapsackPro-Adapters-BaseAdapter-bind_method_called_for_node_0.txt' }
36
+
37
+ end
38
+
39
+ context 'when CI node index 1' do
40
+ let(:ci_node_index) { 1 }
41
+
42
+ it { expect(subject).to eq 'tmp/knapsack_pro/KnapsackPro-Adapters-BaseAdapter-bind_method_called_for_node_1.txt' }
43
+ end
44
+ end
45
+
25
46
  describe '.slow_test_file?' do
26
47
  let(:adapter_class) { double }
27
48
  let(:slow_test_files) do
@@ -71,11 +92,41 @@ describe KnapsackPro::Adapters::BaseAdapter do
71
92
  it { should eql adapter }
72
93
  end
73
94
 
95
+ describe '.verify_bind_method_called' do
96
+ subject { described_class.verify_bind_method_called }
97
+
98
+ before do
99
+ expect(::Kernel).to receive(:at_exit).and_yield
100
+ expect(File).to receive(:exists?).with('tmp/knapsack_pro/KnapsackPro-Adapters-BaseAdapter-bind_method_called_for_node_0.txt').and_return(adapter_bind_method_called_file_exists)
101
+ end
102
+
103
+ context 'when adapter bind method called' do
104
+ let(:adapter_bind_method_called_file_exists) { true }
105
+
106
+ it do
107
+ expect(File).to receive(:delete).with('tmp/knapsack_pro/KnapsackPro-Adapters-BaseAdapter-bind_method_called_for_node_0.txt')
108
+ subject
109
+ end
110
+ end
111
+
112
+ context 'when adapter bind method was not call' do
113
+ let(:adapter_bind_method_called_file_exists) { false }
114
+
115
+ it do
116
+ expect(Kernel).to receive(:exit).with(1)
117
+ subject
118
+ end
119
+ end
120
+ end
121
+
74
122
  describe '#bind' do
75
123
  let(:recording_enabled?) { false }
76
124
  let(:queue_recording_enabled?) { false }
77
125
 
78
126
  before do
127
+ expect(FileUtils).to receive(:mkdir_p).with('tmp/knapsack_pro')
128
+ expect(File).to receive(:write).with('tmp/knapsack_pro/KnapsackPro-Adapters-BaseAdapter-bind_method_called_for_node_0.txt', nil)
129
+
79
130
  expect(KnapsackPro::Config::Env).to receive(:recording_enabled?).and_return(recording_enabled?)
80
131
  expect(KnapsackPro::Config::Env).to receive(:queue_recording_enabled?).and_return(queue_recording_enabled?)
81
132
  end
@@ -34,6 +34,8 @@ describe KnapsackPro::Runners::CucumberRunner do
34
34
  let(:task) { double }
35
35
 
36
36
  before do
37
+ expect(KnapsackPro::Adapters::CucumberAdapter).to receive(:verify_bind_method_called)
38
+
37
39
  expect(Rake::Task).to receive(:[]).with('knapsack_pro:cucumber_run').at_least(1).and_return(task)
38
40
 
39
41
  t = double
@@ -14,6 +14,10 @@ describe KnapsackPro::Runners::MinitestRunner do
14
14
  end
15
15
 
16
16
  context 'when test files were returned by Knapsack Pro API' do
17
+ before do
18
+ expect(KnapsackPro::Adapters::MinitestAdapter).to receive(:verify_bind_method_called)
19
+ end
20
+
17
21
  it 'runs tests' do
18
22
  test_file_paths = ['test_fake/a_test.rb', 'test_fake/b_test.rb']
19
23
  runner = instance_double(described_class,
@@ -167,14 +167,34 @@ describe KnapsackPro::Runners::Queue::CucumberRunner do
167
167
  context "when test files don't exist" do
168
168
  let(:test_file_paths) { [] }
169
169
 
170
- it 'returns exit code 0' do
171
- expect(KnapsackPro::Hooks::Queue).to receive(:call_after_queue)
172
- expect(KnapsackPro::Report).to receive(:save_node_queue_to_api)
170
+ context 'when all_test_file_paths exist' do
171
+ let(:all_test_file_paths) { ['features/a.feature'] }
173
172
 
174
- expect(subject).to eq({
175
- status: :completed,
176
- exitstatus: exitstatus,
177
- })
173
+ it 'returns exit code 0' do
174
+ expect(KnapsackPro::Adapters::CucumberAdapter).to receive(:verify_bind_method_called)
175
+
176
+ expect(KnapsackPro::Hooks::Queue).to receive(:call_after_queue)
177
+ expect(KnapsackPro::Report).to receive(:save_node_queue_to_api)
178
+
179
+ expect(subject).to eq({
180
+ status: :completed,
181
+ exitstatus: exitstatus,
182
+ })
183
+ end
184
+ end
185
+
186
+ context "when all_test_file_paths don't exist" do
187
+ let(:all_test_file_paths) { [] }
188
+
189
+ it 'returns exit code 0' do
190
+ expect(KnapsackPro::Hooks::Queue).to receive(:call_after_queue)
191
+ expect(KnapsackPro::Report).to receive(:save_node_queue_to_api)
192
+
193
+ expect(subject).to eq({
194
+ status: :completed,
195
+ exitstatus: exitstatus,
196
+ })
197
+ end
178
198
  end
179
199
  end
180
200
  end
@@ -159,14 +159,34 @@ describe KnapsackPro::Runners::Queue::MinitestRunner do
159
159
  context "when test files don't exist" do
160
160
  let(:test_file_paths) { [] }
161
161
 
162
- it 'returns exit code 0' do
163
- expect(KnapsackPro::Hooks::Queue).to receive(:call_after_queue)
164
- expect(KnapsackPro::Report).to receive(:save_node_queue_to_api)
162
+ context 'when all_test_file_paths exist' do
163
+ let(:all_test_file_paths) { ['a_test.rb'] }
165
164
 
166
- expect(subject).to eq({
167
- status: :completed,
168
- exitstatus: exitstatus,
169
- })
165
+ it 'returns exit code 0' do
166
+ expect(KnapsackPro::Adapters::MinitestAdapter).to receive(:verify_bind_method_called)
167
+
168
+ expect(KnapsackPro::Hooks::Queue).to receive(:call_after_queue)
169
+ expect(KnapsackPro::Report).to receive(:save_node_queue_to_api)
170
+
171
+ expect(subject).to eq({
172
+ status: :completed,
173
+ exitstatus: exitstatus,
174
+ })
175
+ end
176
+ end
177
+
178
+ context "when all_test_file_paths don't exist" do
179
+ let(:all_test_file_paths) { [] }
180
+
181
+ it 'returns exit code 0' do
182
+ expect(KnapsackPro::Hooks::Queue).to receive(:call_after_queue)
183
+ expect(KnapsackPro::Report).to receive(:save_node_queue_to_api)
184
+
185
+ expect(subject).to eq({
186
+ status: :completed,
187
+ exitstatus: exitstatus,
188
+ })
189
+ end
170
190
  end
171
191
  end
172
192
  end
@@ -249,6 +249,8 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
249
249
  let(:all_test_file_paths) { ['a_spec.rb'] }
250
250
 
251
251
  it do
252
+ expect(KnapsackPro::Adapters::RSpecAdapter).to receive(:verify_bind_method_called)
253
+
252
254
  expect(KnapsackPro::Formatters::RSpecQueueSummaryFormatter).to receive(:print_summary)
253
255
  expect(KnapsackPro::Formatters::RSpecQueueProfileFormatterExtension).to receive(:print_summary)
254
256
 
@@ -34,6 +34,8 @@ describe KnapsackPro::Runners::RSpecRunner do
34
34
  let(:task) { double }
35
35
 
36
36
  before do
37
+ expect(KnapsackPro::Adapters::RSpecAdapter).to receive(:verify_bind_method_called)
38
+
37
39
  expect(Rake::Task).to receive(:[]).with('knapsack_pro:rspec_run').at_least(1).and_return(task)
38
40
 
39
41
  t = double
@@ -26,6 +26,8 @@ describe KnapsackPro::Runners::SpinachRunner do
26
26
  end
27
27
 
28
28
  before do
29
+ expect(KnapsackPro::Adapters::SpinachAdapter).to receive(:verify_bind_method_called)
30
+
29
31
  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')
30
32
  end
31
33
 
@@ -16,6 +16,8 @@ describe KnapsackPro::Runners::TestUnitRunner do
16
16
 
17
17
  context 'when test files were returned by Knapsack Pro API' do
18
18
  it 'runs tests' do
19
+ expect(KnapsackPro::Adapters::TestUnitAdapter).to receive(:verify_bind_method_called)
20
+
19
21
  test_file_paths = ['test-unit_fake/a_test.rb', 'test-unit_fake/b_test.rb']
20
22
  runner = instance_double(described_class,
21
23
  test_dir: 'test-unit_fake',
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.10.1
4
+ version: 2.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ArturT
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-11-25 00:00:00.000000000 Z
11
+ date: 2021-01-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -408,7 +408,7 @@ metadata:
408
408
  documentation_uri: https://docs.knapsackpro.com/integration/
409
409
  homepage_uri: https://knapsackpro.com
410
410
  source_code_uri: https://github.com/KnapsackPro/knapsack_pro-ruby
411
- post_install_message:
411
+ post_install_message:
412
412
  rdoc_options: []
413
413
  require_paths:
414
414
  - lib
@@ -424,7 +424,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
424
424
  version: '0'
425
425
  requirements: []
426
426
  rubygems_version: 3.0.6
427
- signing_key:
427
+ signing_key:
428
428
  specification_version: 4
429
429
  summary: Knapsack Pro splits tests across parallel CI nodes and ensures each parallel
430
430
  job finish work at a similar time.