knapsack_pro 1.9.0 → 1.10.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: 5d7bf901385b7f5c6010f0ec20241cf9d74e4c954cf69ae75ca7f5ac1d4c549b
4
- data.tar.gz: 0a24d55e70d9055e70ae052ef152e0cf1a85716d4d93025e800a5b1769853f0d
3
+ metadata.gz: 15d64502a63c7087b4d8793ad780d0f7454d2414c93c0da46967e20620578fe0
4
+ data.tar.gz: 88addd61d85b84f2fc043ff17e554564d95b40be262fe55a51714efa5ae4f719
5
5
  SHA512:
6
- metadata.gz: '0482cd76a5a08df97ce43abf6d89763f1f8fb83cd3aca349c09de993513a87c623bfe0abb31a05d9dd5701101ebf19789e0a41145b3f2e435567a244a462a992'
7
- data.tar.gz: 0b958c6d1bf0d8f9cdfcb4a97b5f48a0ad3b046acdc6c6b7198e0a7865f37928fe8f2d4d62acb0306489d5779bd07b613cb5774aca426dd774b81fd6cf431435
6
+ metadata.gz: 67664f1170199a4f5f6cb2fbabdfd15fbebd2c73d04a0646bacdc20411411722f5b7b0946d8a76417150fcbe60211b13b97f27a09ca10840a44caaea8beccb0a
7
+ data.tar.gz: d835f28e6af4885f42e6daa218caace7401f1ab9e406d1f8a4c06af6f20ad671e37b8501e35aceaea41183d94d56feec462badb86747053843b7a1957ec64867
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Change Log
2
2
 
3
+ ### 1.10.0
4
+
5
+ * Logs error on lost info about recorded timing for test files due to missing json files in Queue Mode
6
+
7
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/83
8
+
9
+ * Fix bug: default test file time should not be added to measured time
10
+
11
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/84
12
+
13
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v1.9.0...v1.10.0
14
+
3
15
  ### 1.9.0
4
16
 
5
17
  * Reduce data transfer and speed up usage of Knapsack Pro API for Queue Mode
data/README.md CHANGED
@@ -1414,7 +1414,7 @@ end
1414
1414
  ##### Why when I use Queue Mode for RSpec then my tests fail?
1415
1415
 
1416
1416
  knapsack_pro Queue Mode uses `RSpec::Core::Runner` feature that allows [running specs multiple times with different runner options in the same process](https://relishapp.com/rspec/rspec-core/docs/running-specs-multiple-times-with-different-runner-options-in-the-same-process).
1417
- Thanks to that we can run subset of test suite pulled from Knapsack Pro API work queue. This allows dynamic allocation of your tests across CI nodes without reloading whole Ruby/Rails application for each run of test suite subset .
1417
+ Thanks to that we can run subset of test suite pulled from Knapsack Pro API work queue. This allows dynamic allocation of your tests across CI nodes without reloading whole Ruby/Rails application for each run of test suite subset.
1418
1418
 
1419
1419
  If you have custom things that are not common in how typical RSpec spec looks like then the RSpec feature won't be able to handle it between test suite subset runs.
1420
1420
  In that case you need to resolve failed tests in a way that allows RSpec to run the tests. Feel free to [ask me for help](https://knapsackpro.com/contact).
@@ -1540,6 +1540,15 @@ If you go to [user dashboard](https://knapsackpro.com/dashboard) and open `Build
1540
1540
  If you go to [user dashboard](https://knapsackpro.com/dashboard) and open `Build metrics` for your API token and you open CI build for your last git commit you should see there info about collected time execution data from all CI nodes. If you see all test files have 0.1s time execution then please ensure:
1541
1541
 
1542
1542
  * you don't clean up `tmp` directory in your tests (for instance in RSpec hooks like `before` or `after`) so knapsack_pro can publish measured time execution data to Knapsack Pro API server. knapsack_pro Queue Mode saves temporary files with collected time execution data in `your_rails_project/tmp/knapsack_pro/queue/`.
1543
+ * please ensure you have in your `rails_helper.rb` or `spec_helper.rb` line:
1544
+
1545
+ ```ruby
1546
+ require 'knapsack_pro'
1547
+
1548
+ # CUSTOM_CONFIG_GOES_HERE
1549
+
1550
+ KnapsackPro::Adapters::RSpecAdapter.bind
1551
+ ```
1543
1552
 
1544
1553
  The 0.1s is a default time execution used when test file is an empty file or its content are all pending tests.
1545
1554
 
@@ -27,7 +27,7 @@ module KnapsackPro
27
27
  end
28
28
  end
29
29
 
30
- def self.save_node_queue_to_api
30
+ def self.save_node_queue_to_api(executed_test_files_count)
31
31
  test_files = []
32
32
  Dir.glob("#{queue_path}/*.json").each do |file|
33
33
  report = JSON.parse(File.read(file))
@@ -35,9 +35,15 @@ module KnapsackPro
35
35
  end
36
36
 
37
37
  if test_files.empty?
38
- KnapsackPro.logger.warn("No test files were executed on this CI node.")
39
- KnapsackPro.logger.debug("When you use knapsack_pro queue mode then probably reason might be that CI node was started after the test files from the queue were already executed by other CI nodes. That is why this CI node has no test files to execute.")
40
- KnapsackPro.logger.debug("Another reason might be when your CI node failed in a way that prevented knapsack_pro to save time execution data to Knapsack Pro API and you have just tried to retry failed CI node but instead you got no test files to execute. In that case knapsack_pro don't know what testes should be executed here.")
38
+ if executed_test_files_count == 0
39
+ KnapsackPro.logger.warn("No test files were executed on this CI node.")
40
+ KnapsackPro.logger.debug("When you use knapsack_pro queue mode then probably reason might be that CI node was started after the test files from the queue were already executed by other CI nodes. That is why this CI node has no test files to execute.")
41
+ KnapsackPro.logger.debug("Another reason might be when your CI node failed in a way that prevented knapsack_pro to save time execution data to Knapsack Pro API and you have just tried to retry failed CI node but instead you got no test files to execute. In that case knapsack_pro don't know what testes should be executed here.")
42
+ end
43
+
44
+ if executed_test_files_count > 0
45
+ KnapsackPro.logger.error("#{executed_test_files_count} test files were executed on this CI node but the recorded time of it was lost. Probably you have a code (i.e. RSpec hooks) that clears tmp directory in your project. Please ensure you do not remove the content of tmp/knapsack_pro/queue/ directory between tests run. Another reason might be that you forgot to add Knapsack::Adapters::RspecAdapter.bind in your rails_helper.rb or spec_helper.rb. Please follow the installation guide again: https://docs.knapsackpro.com/integration/")
46
+ end
41
47
  end
42
48
 
43
49
  create_build_subset(test_files)
@@ -48,7 +48,7 @@ module KnapsackPro
48
48
  if test_file_paths.empty?
49
49
  KnapsackPro::Hooks::Queue.call_after_queue
50
50
 
51
- KnapsackPro::Report.save_node_queue_to_api
51
+ KnapsackPro::Report.save_node_queue_to_api(all_test_file_paths.count)
52
52
 
53
53
  return {
54
54
  status: :completed,
@@ -59,7 +59,7 @@ module KnapsackPro
59
59
 
60
60
  KnapsackPro::Hooks::Queue.call_after_queue
61
61
 
62
- KnapsackPro::Report.save_node_queue_to_api
62
+ KnapsackPro::Report.save_node_queue_to_api(all_test_file_paths.count)
63
63
 
64
64
  return {
65
65
  status: :completed,
@@ -2,6 +2,10 @@ module KnapsackPro
2
2
  class Tracker
3
3
  include Singleton
4
4
 
5
+ # when test file is pending, empty with no tests or has syntax error then assume time execution
6
+ # to better allocate it in Queue Mode for future CI build runs
7
+ DEFAULT_TEST_FILE_TIME = 0.1 # seconds
8
+
5
9
  attr_reader :global_time_since_beginning, :global_time, :test_files_with_time
6
10
  attr_writer :current_test_path
7
11
 
@@ -36,16 +40,19 @@ module KnapsackPro
36
40
  # in case when the test file will not be run
37
41
  # due syntax error or being pending.
38
42
  # The time is required by Knapsack Pro API.
39
- @test_files_with_time[test_file_path] = 0.1
43
+ @test_files_with_time[test_file_path] = {
44
+ time_execution: DEFAULT_TEST_FILE_TIME,
45
+ measured_time: false,
46
+ }
40
47
  end
41
48
  end
42
49
 
43
50
  def to_a
44
51
  test_files = []
45
- @test_files_with_time.each do |path, time_execution|
52
+ @test_files_with_time.each do |path, hash|
46
53
  test_files << {
47
54
  path: path,
48
- time_execution: time_execution
55
+ time_execution: hash[:time_execution]
49
56
  }
50
57
  end
51
58
  test_files
@@ -65,8 +72,21 @@ module KnapsackPro
65
72
  end
66
73
 
67
74
  def update_test_file_time(execution_time)
68
- @test_files_with_time[current_test_path] ||= 0
69
- @test_files_with_time[current_test_path] += execution_time
75
+ @test_files_with_time[current_test_path] ||= {
76
+ time_execution: 0,
77
+ measured_time: false,
78
+ }
79
+
80
+ hash = @test_files_with_time[current_test_path]
81
+
82
+ if hash[:measured_time]
83
+ hash[:time_execution] += execution_time
84
+ else
85
+ hash[:time_execution] = execution_time
86
+ hash[:measured_time] = true
87
+ end
88
+
89
+ @test_files_with_time[current_test_path] = hash
70
90
  end
71
91
 
72
92
  def now_without_mock_time
@@ -1,3 +1,3 @@
1
1
  module KnapsackPro
2
- VERSION = '1.9.0'
2
+ VERSION = '1.10.0'
3
3
  end
@@ -43,33 +43,85 @@ describe KnapsackPro::Report do
43
43
  end
44
44
 
45
45
  describe '.save_node_queue_to_api' do
46
- let(:json_test_file_a_path) { double }
47
- let(:json_test_file_a) { [{ 'path' => 'a_spec.rb' }] }
46
+ context 'when json files with recorded time exist for executed test files' do
47
+ let(:json_test_file_a_path) { double }
48
+ let(:json_test_file_a) { [{ 'path' => 'a_spec.rb' }] }
48
49
 
49
- let(:json_test_file_b_path) { double }
50
- let(:json_test_file_b) { [{ 'path' => 'b_spec.rb' }] }
50
+ let(:json_test_file_b_path) { double }
51
+ let(:json_test_file_b) { [{ 'path' => 'b_spec.rb' }] }
51
52
 
52
- subject { described_class.save_node_queue_to_api }
53
+ let(:executed_test_files_count) { 2 }
53
54
 
54
- before do
55
- queue_id = 'fake-queue-id'
56
- expect(KnapsackPro::Config::Env).to receive(:queue_id).and_return(queue_id)
55
+ subject { described_class.save_node_queue_to_api(executed_test_files_count) }
57
56
 
58
- expect(Dir).to receive(:glob).with('tmp/knapsack_pro/queue/fake-queue-id/*.json').and_return([
59
- json_test_file_a_path,
60
- json_test_file_b_path
61
- ])
57
+ before do
58
+ queue_id = 'fake-queue-id'
59
+ expect(KnapsackPro::Config::Env).to receive(:queue_id).and_return(queue_id)
60
+
61
+ expect(Dir).to receive(:glob).with('tmp/knapsack_pro/queue/fake-queue-id/*.json').and_return([
62
+ json_test_file_a_path,
63
+ json_test_file_b_path
64
+ ])
65
+
66
+ expect(File).to receive(:read).with(json_test_file_a_path).and_return(json_test_file_a.to_json)
67
+ expect(File).to receive(:read).with(json_test_file_b_path).and_return(json_test_file_b.to_json)
68
+ end
69
+
70
+ it 'creates build subset for 2 recorded test files timing' do
71
+ expect(described_class).to receive(:create_build_subset).with(
72
+ json_test_file_a + json_test_file_b
73
+ )
62
74
 
63
- expect(File).to receive(:read).with(json_test_file_a_path).and_return(json_test_file_a.to_json)
64
- expect(File).to receive(:read).with(json_test_file_b_path).and_return(json_test_file_b.to_json)
75
+ subject
76
+ end
65
77
  end
66
78
 
67
- it do
68
- expect(described_class).to receive(:create_build_subset).with(
69
- json_test_file_a + json_test_file_b
70
- )
79
+ context 'when json files with recorded time does not exist for executed test files' do
80
+ let(:executed_test_files_count) { 2 }
71
81
 
72
- subject
82
+ subject { described_class.save_node_queue_to_api(executed_test_files_count) }
83
+
84
+ before do
85
+ queue_id = 'fake-queue-id'
86
+ expect(KnapsackPro::Config::Env).to receive(:queue_id).and_return(queue_id)
87
+
88
+ expect(Dir).to receive(:glob).with('tmp/knapsack_pro/queue/fake-queue-id/*.json').and_return([])
89
+ end
90
+
91
+ it 'logs error on lost info about recorded timing for test files due missing json files AND creates empty build subset' do
92
+ logger = instance_double(Logger)
93
+ expect(KnapsackPro).to receive(:logger).and_return(logger)
94
+ expect(logger).to receive(:error).with('2 test files were executed on this CI node but the recorded time of it was lost. Probably you have a code (i.e. RSpec hooks) that clears tmp directory in your project. Please ensure you do not remove the content of tmp/knapsack_pro/queue/ directory between tests run. Another reason might be that you forgot to add Knapsack::Adapters::RspecAdapter.bind in your rails_helper.rb or spec_helper.rb. Please follow the installation guide again: https://docs.knapsackpro.com/integration/')
95
+
96
+ expect(described_class).to receive(:create_build_subset).with([])
97
+
98
+ subject
99
+ end
100
+ end
101
+
102
+ context 'when json files with recorded time does not exist AND no executed test files' do
103
+ let(:executed_test_files_count) { 0 }
104
+
105
+ subject { described_class.save_node_queue_to_api(executed_test_files_count) }
106
+
107
+ before do
108
+ queue_id = 'fake-queue-id'
109
+ expect(KnapsackPro::Config::Env).to receive(:queue_id).and_return(queue_id)
110
+
111
+ expect(Dir).to receive(:glob).with('tmp/knapsack_pro/queue/fake-queue-id/*.json').and_return([])
112
+ end
113
+
114
+ it 'logs warning about reasons why no test files were executed on this CI node' do
115
+ logger = instance_double(Logger)
116
+ expect(KnapsackPro).to receive(:logger).exactly(3).and_return(logger)
117
+ expect(logger).to receive(:warn).with('No test files were executed on this CI node.')
118
+ expect(logger).to receive(:debug).with('When you use knapsack_pro queue mode then probably reason might be that CI node was started after the test files from the queue were already executed by other CI nodes. That is why this CI node has no test files to execute.')
119
+ expect(logger).to receive(:debug).with("Another reason might be when your CI node failed in a way that prevented knapsack_pro to save time execution data to Knapsack Pro API and you have just tried to retry failed CI node but instead you got no test files to execute. In that case knapsack_pro don't know what testes should be executed here.")
120
+
121
+ expect(described_class).to receive(:create_build_subset).with([])
122
+
123
+ subject
124
+ end
73
125
  end
74
126
  end
75
127
 
@@ -161,7 +161,7 @@ describe KnapsackPro::Runners::Queue::MinitestRunner do
161
161
 
162
162
  it 'returns exit code 0' do
163
163
  expect(KnapsackPro::Hooks::Queue).to receive(:call_after_queue)
164
- expect(KnapsackPro::Report).to receive(:save_node_queue_to_api)
164
+ expect(KnapsackPro::Report).to receive(:save_node_queue_to_api).with(0)
165
165
 
166
166
  expect(subject).to eq({
167
167
  status: :completed,
@@ -203,7 +203,7 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
203
203
  expect(KnapsackPro::Formatters::RSpecQueueProfileFormatterExtension).to receive(:print_summary)
204
204
 
205
205
  expect(KnapsackPro::Hooks::Queue).to receive(:call_after_queue)
206
- expect(KnapsackPro::Report).to receive(:save_node_queue_to_api)
206
+ expect(KnapsackPro::Report).to receive(:save_node_queue_to_api).with(1)
207
207
 
208
208
  expect(subject).to eq({
209
209
  status: :completed,
@@ -217,7 +217,7 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
217
217
 
218
218
  it do
219
219
  expect(KnapsackPro::Hooks::Queue).to receive(:call_after_queue)
220
- expect(KnapsackPro::Report).to receive(:save_node_queue_to_api)
220
+ expect(KnapsackPro::Report).to receive(:save_node_queue_to_api).with(0)
221
221
 
222
222
  expect(subject).to eq({
223
223
  status: :completed,
@@ -56,8 +56,8 @@ describe KnapsackPro::Tracker do
56
56
 
57
57
  it { expect(tracker.global_time).to be_within(delta).of(0.3) }
58
58
  it { expect(tracker.test_files_with_time.keys.size).to eql 2 }
59
- it { expect(tracker.test_files_with_time['a_spec.rb']).to be_within(delta).of(0.1) }
60
- it { expect(tracker.test_files_with_time['b_spec.rb']).to be_within(delta).of(0.2) }
59
+ it { expect(tracker.test_files_with_time['a_spec.rb'][:time_execution]).to be_within(delta).of(0.1) }
60
+ it { expect(tracker.test_files_with_time['b_spec.rb'][:time_execution]).to be_within(delta).of(0.2) }
61
61
  it_behaves_like '#to_a'
62
62
  end
63
63
 
@@ -81,8 +81,8 @@ describe KnapsackPro::Tracker do
81
81
  it { expect(tracker.global_time).to be > 0 }
82
82
  it { expect(tracker.global_time).to be_within(delta).of(0) }
83
83
  it { expect(tracker.test_files_with_time.keys.size).to eql 2 }
84
- it { expect(tracker.test_files_with_time['a_spec.rb']).to be_within(delta).of(0) }
85
- it { expect(tracker.test_files_with_time['b_spec.rb']).to be_within(delta).of(0) }
84
+ it { expect(tracker.test_files_with_time['a_spec.rb'][:time_execution]).to be_within(delta).of(0) }
85
+ it { expect(tracker.test_files_with_time['b_spec.rb'][:time_execution]).to be_within(delta).of(0) }
86
86
  it_behaves_like '#to_a'
87
87
  end
88
88
 
@@ -97,8 +97,8 @@ describe KnapsackPro::Tracker do
97
97
 
98
98
  it { expect(tracker.global_time).to eq 0 }
99
99
  it { expect(tracker.test_files_with_time.keys.size).to eql 2 }
100
- it { expect(tracker.test_files_with_time['a_spec.rb']).to eq 0 }
101
- it { expect(tracker.test_files_with_time['b_spec.rb']).to eq 0 }
100
+ it { expect(tracker.test_files_with_time['a_spec.rb'][:time_execution]).to eq 0 }
101
+ it { expect(tracker.test_files_with_time['b_spec.rb'][:time_execution]).to eq 0 }
102
102
  it_behaves_like '#to_a'
103
103
  end
104
104
  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: 1.9.0
4
+ version: 1.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ArturT
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-04-13 00:00:00.000000000 Z
11
+ date: 2019-05-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake