knapsack_pro 2.11.0 → 2.16.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +40 -0
- data/README.md +35 -1600
- data/lib/knapsack_pro/adapters/rspec_adapter.rb +12 -2
- data/lib/knapsack_pro/allocator.rb +1 -1
- data/lib/knapsack_pro/queue_allocator.rb +1 -1
- data/lib/knapsack_pro/runners/queue/rspec_runner.rb +23 -4
- data/lib/knapsack_pro/tracker.rb +13 -4
- data/lib/knapsack_pro/version.rb +1 -1
- data/spec/knapsack_pro/adapters/rspec_adapter_spec.rb +30 -12
- data/spec/knapsack_pro/runners/queue/rspec_runner_spec.rb +37 -7
- data/spec/knapsack_pro/tracker_spec.rb +4 -2
- metadata +2 -2
@@ -21,7 +21,15 @@ module KnapsackPro
|
|
21
21
|
|
22
22
|
def bind_time_tracker
|
23
23
|
::RSpec.configure do |config|
|
24
|
+
config.prepend_before(:context) do
|
25
|
+
KnapsackPro.tracker.start_timer
|
26
|
+
end
|
27
|
+
|
24
28
|
config.around(:each) do |example|
|
29
|
+
# stop timer to update time for a previously run test example
|
30
|
+
# this way we count time spend in runtime for the previous test example after around(:each) is already done
|
31
|
+
KnapsackPro.tracker.stop_timer
|
32
|
+
|
25
33
|
current_example_group =
|
26
34
|
if ::RSpec.respond_to?(:current_example)
|
27
35
|
::RSpec.current_example.metadata[:example_group]
|
@@ -38,10 +46,12 @@ module KnapsackPro
|
|
38
46
|
current_test_path
|
39
47
|
end
|
40
48
|
|
41
|
-
KnapsackPro.tracker.start_timer
|
42
|
-
|
43
49
|
example.run
|
50
|
+
end
|
44
51
|
|
52
|
+
config.append_after(:context) do
|
53
|
+
# after(:context) hook is run one time only, after all of the examples in a group
|
54
|
+
# stop timer to count time for the very last executed test example
|
45
55
|
KnapsackPro.tracker.stop_timer
|
46
56
|
end
|
47
57
|
|
@@ -26,7 +26,7 @@ module KnapsackPro
|
|
26
26
|
KnapsackPro.logger.error(message)
|
27
27
|
raise message
|
28
28
|
else
|
29
|
-
KnapsackPro.logger.warn("Fallback mode started. We could not connect with Knapsack Pro API. Your tests will be executed based on directory names. Read more about fallback mode at https://
|
29
|
+
KnapsackPro.logger.warn("Fallback mode started. We could not connect with Knapsack Pro API. Your tests will be executed based on directory names. Read more about fallback mode at https://knapsackpro.com/faq/question/what-happens-when-knapsack-pro-api-is-not-availablenot-reachable-temporarily")
|
30
30
|
fallback_test_files
|
31
31
|
end
|
32
32
|
end
|
@@ -39,7 +39,7 @@ module KnapsackPro
|
|
39
39
|
raise message
|
40
40
|
else
|
41
41
|
@fallback_activated = true
|
42
|
-
KnapsackPro.logger.warn("Fallback mode started. We could not connect with Knapsack Pro API. Your tests will be executed based on directory names. If other CI nodes were able to connect with Knapsack Pro API then you may notice that some of the test files will be executed twice across CI nodes. The most important thing is to guarantee each of test files is run at least once! Read more about fallback mode at https://
|
42
|
+
KnapsackPro.logger.warn("Fallback mode started. We could not connect with Knapsack Pro API. Your tests will be executed based on directory names. If other CI nodes were able to connect with Knapsack Pro API then you may notice that some of the test files will be executed twice across CI nodes. The most important thing is to guarantee each of test files is run at least once! Read more about fallback mode at https://knapsackpro.com/faq/question/what-happens-when-knapsack-pro-api-is-not-availablenot-reachable-temporarily")
|
43
43
|
fallback_test_files(executed_test_files)
|
44
44
|
end
|
45
45
|
end
|
@@ -14,12 +14,18 @@ module KnapsackPro
|
|
14
14
|
runner = new(KnapsackPro::Adapters::RSpecAdapter)
|
15
15
|
|
16
16
|
cli_args = (args || '').split
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
|
18
|
+
if KnapsackPro::Config::Env.rspec_split_by_test_examples? && has_tag_option?(cli_args)
|
19
|
+
error_message = 'It is not allowed to use the RSpec tag option together with the RSpec split by test examples feature. Please see: https://knapsackpro.com/faq/question/how-to-split-slow-rspec-test-files-by-test-examples-by-individual-it#warning-dont-use-rspec-tag-option'
|
20
|
+
KnapsackPro.logger.error(error_message)
|
21
|
+
raise error_message
|
21
22
|
end
|
23
|
+
|
24
|
+
# when format option is not defined by user then use progress formatter to show tests execution progress
|
25
|
+
cli_args += ['--format', 'progress'] unless has_format_option?(cli_args)
|
26
|
+
|
22
27
|
cli_args += [
|
28
|
+
# shows summary of all tests executed in Queue Mode at the very end
|
23
29
|
'--format', KnapsackPro::Formatters::RSpecQueueSummaryFormatter.to_s,
|
24
30
|
'--default-path', runner.test_dir,
|
25
31
|
]
|
@@ -148,6 +154,19 @@ module KnapsackPro
|
|
148
154
|
::RSpec.configuration.reset_filters
|
149
155
|
end
|
150
156
|
end
|
157
|
+
|
158
|
+
def self.has_tag_option?(cli_args)
|
159
|
+
# use start_with? because user can define tag option in a few ways:
|
160
|
+
# -t mytag
|
161
|
+
# -tmytag
|
162
|
+
# --tag mytag
|
163
|
+
# --tag=mytag
|
164
|
+
cli_args.any? { |arg| arg.start_with?('-t') || arg.start_with?('--tag') }
|
165
|
+
end
|
166
|
+
|
167
|
+
def self.has_format_option?(cli_args)
|
168
|
+
cli_args.any? { |arg| arg.start_with?('-f') || arg.start_with?('--format') }
|
169
|
+
end
|
151
170
|
end
|
152
171
|
end
|
153
172
|
end
|
data/lib/knapsack_pro/tracker.rb
CHANGED
@@ -4,7 +4,7 @@ module KnapsackPro
|
|
4
4
|
|
5
5
|
# when test file is pending, empty with no tests or has syntax error then assume time execution
|
6
6
|
# to better allocate it in Queue Mode for future CI build runs
|
7
|
-
DEFAULT_TEST_FILE_TIME = 0.
|
7
|
+
DEFAULT_TEST_FILE_TIME = 0.0 # seconds
|
8
8
|
|
9
9
|
attr_reader :global_time_since_beginning, :global_time, :test_files_with_time
|
10
10
|
attr_writer :current_test_path
|
@@ -19,13 +19,22 @@ module KnapsackPro
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def start_timer
|
22
|
+
@start_time ||= now_without_mock_time.to_f
|
23
|
+
end
|
24
|
+
|
25
|
+
def reset_timer
|
22
26
|
@start_time = now_without_mock_time.to_f
|
23
27
|
end
|
24
28
|
|
25
29
|
def stop_timer
|
26
30
|
execution_time = @start_time ? now_without_mock_time.to_f - @start_time : 0.0
|
27
|
-
|
28
|
-
|
31
|
+
|
32
|
+
if @current_test_path
|
33
|
+
update_global_time(execution_time)
|
34
|
+
update_test_file_time(execution_time)
|
35
|
+
reset_timer
|
36
|
+
end
|
37
|
+
|
29
38
|
execution_time
|
30
39
|
end
|
31
40
|
|
@@ -63,7 +72,7 @@ module KnapsackPro
|
|
63
72
|
def set_defaults
|
64
73
|
@global_time = 0
|
65
74
|
@test_files_with_time = {}
|
66
|
-
@
|
75
|
+
@current_test_path = nil
|
67
76
|
end
|
68
77
|
|
69
78
|
def update_global_time(execution_time)
|
data/lib/knapsack_pro/version.rb
CHANGED
@@ -86,20 +86,26 @@ describe KnapsackPro::Adapters::RSpecAdapter do
|
|
86
86
|
end
|
87
87
|
|
88
88
|
it 'records time for current test path' do
|
89
|
+
expect(config).to receive(:prepend_before).with(:context).and_yield
|
90
|
+
|
91
|
+
allow(KnapsackPro).to receive(:tracker).and_return(tracker)
|
92
|
+
expect(tracker).to receive(:start_timer).ordered
|
93
|
+
|
89
94
|
expect(config).to receive(:around).with(:each).and_yield(example)
|
95
|
+
expect(config).to receive(:append_after).with(:context).and_yield
|
90
96
|
expect(config).to receive(:after).with(:suite).and_yield
|
91
97
|
expect(::RSpec).to receive(:configure).and_yield(config)
|
92
98
|
|
99
|
+
expect(tracker).to receive(:stop_timer).ordered
|
100
|
+
|
93
101
|
expect(::RSpec).to receive(:current_example).twice.and_return(current_example)
|
94
102
|
expect(described_class).to receive(:test_path).with(example_group).and_return(test_path)
|
95
103
|
|
96
|
-
|
97
|
-
expect(tracker).to receive(:current_test_path=).with(test_path)
|
98
|
-
expect(tracker).to receive(:start_timer)
|
104
|
+
expect(tracker).to receive(:current_test_path=).with(test_path).ordered
|
99
105
|
|
100
106
|
expect(example).to receive(:run)
|
101
107
|
|
102
|
-
expect(tracker).to receive(:stop_timer)
|
108
|
+
expect(tracker).to receive(:stop_timer).ordered
|
103
109
|
|
104
110
|
expect(KnapsackPro::Presenter).to receive(:global_time).and_return(global_time)
|
105
111
|
expect(KnapsackPro).to receive(:logger).and_return(logger)
|
@@ -124,20 +130,26 @@ describe KnapsackPro::Adapters::RSpecAdapter do
|
|
124
130
|
it 'records time for example.id' do
|
125
131
|
expect(example).to receive(:id).and_return(test_example_path)
|
126
132
|
|
133
|
+
expect(config).to receive(:prepend_before).with(:context).and_yield
|
134
|
+
|
135
|
+
allow(KnapsackPro).to receive(:tracker).and_return(tracker)
|
136
|
+
expect(tracker).to receive(:start_timer).ordered
|
137
|
+
|
127
138
|
expect(config).to receive(:around).with(:each).and_yield(example)
|
139
|
+
expect(config).to receive(:append_after).with(:context).and_yield
|
128
140
|
expect(config).to receive(:after).with(:suite).and_yield
|
129
141
|
expect(::RSpec).to receive(:configure).and_yield(config)
|
130
142
|
|
143
|
+
expect(tracker).to receive(:stop_timer).ordered
|
144
|
+
|
131
145
|
expect(::RSpec).to receive(:current_example).twice.and_return(current_example)
|
132
146
|
expect(described_class).to receive(:test_path).with(example_group).and_return(test_path)
|
133
147
|
|
134
|
-
|
135
|
-
expect(tracker).to receive(:current_test_path=).with(test_example_path)
|
136
|
-
expect(tracker).to receive(:start_timer)
|
148
|
+
expect(tracker).to receive(:current_test_path=).with(test_example_path).ordered
|
137
149
|
|
138
150
|
expect(example).to receive(:run)
|
139
151
|
|
140
|
-
expect(tracker).to receive(:stop_timer)
|
152
|
+
expect(tracker).to receive(:stop_timer).ordered
|
141
153
|
|
142
154
|
expect(KnapsackPro::Presenter).to receive(:global_time).and_return(global_time)
|
143
155
|
expect(KnapsackPro).to receive(:logger).and_return(logger)
|
@@ -153,20 +165,26 @@ describe KnapsackPro::Adapters::RSpecAdapter do
|
|
153
165
|
end
|
154
166
|
|
155
167
|
it 'records time for current test path' do
|
168
|
+
expect(config).to receive(:prepend_before).with(:context).and_yield
|
169
|
+
|
170
|
+
allow(KnapsackPro).to receive(:tracker).and_return(tracker)
|
171
|
+
expect(tracker).to receive(:start_timer).ordered
|
172
|
+
|
156
173
|
expect(config).to receive(:around).with(:each).and_yield(example)
|
174
|
+
expect(config).to receive(:append_after).with(:context).and_yield
|
157
175
|
expect(config).to receive(:after).with(:suite).and_yield
|
158
176
|
expect(::RSpec).to receive(:configure).and_yield(config)
|
159
177
|
|
160
178
|
expect(::RSpec).to receive(:current_example).twice.and_return(current_example)
|
161
179
|
expect(described_class).to receive(:test_path).with(example_group).and_return(test_path)
|
162
180
|
|
163
|
-
|
164
|
-
|
165
|
-
expect(tracker).to receive(:
|
181
|
+
expect(tracker).to receive(:stop_timer).ordered
|
182
|
+
|
183
|
+
expect(tracker).to receive(:current_test_path=).with(test_path).ordered
|
166
184
|
|
167
185
|
expect(example).to receive(:run)
|
168
186
|
|
169
|
-
expect(tracker).to receive(:stop_timer)
|
187
|
+
expect(tracker).to receive(:stop_timer).ordered
|
170
188
|
|
171
189
|
expect(KnapsackPro::Presenter).to receive(:global_time).and_return(global_time)
|
172
190
|
expect(KnapsackPro).to receive(:logger).and_return(logger)
|
@@ -30,7 +30,7 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
|
|
30
30
|
end
|
31
31
|
|
32
32
|
context 'when args provided' do
|
33
|
-
context 'when format
|
33
|
+
context 'when format option is not provided' do
|
34
34
|
let(:args) { '--example-arg example-value' }
|
35
35
|
|
36
36
|
it 'uses default formatter progress' do
|
@@ -55,10 +55,10 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
|
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
|
-
context 'when format
|
58
|
+
context 'when format option is provided as --format' do
|
59
59
|
let(:args) { '--format documentation' }
|
60
60
|
|
61
|
-
it 'uses provided format
|
61
|
+
it 'uses provided format option instead of default formatter progress' do
|
62
62
|
expected_exitstatus = 0
|
63
63
|
expected_accumulator = {
|
64
64
|
status: :completed,
|
@@ -80,10 +80,10 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
|
|
80
80
|
end
|
81
81
|
end
|
82
82
|
|
83
|
-
context 'when format
|
83
|
+
context 'when format option is provided as -f' do
|
84
84
|
let(:args) { '-f d' }
|
85
85
|
|
86
|
-
it 'uses provided format
|
86
|
+
it 'uses provided format option instead of default formatter progress' do
|
87
87
|
expected_exitstatus = 0
|
88
88
|
expected_accumulator = {
|
89
89
|
status: :completed,
|
@@ -105,10 +105,10 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
|
|
105
105
|
end
|
106
106
|
end
|
107
107
|
|
108
|
-
context 'when format
|
108
|
+
context 'when format option is provided without a delimiter' do
|
109
109
|
let(:args) { '-fMyCustomFormatter' }
|
110
110
|
|
111
|
-
it 'uses provided format
|
111
|
+
it 'uses provided format option instead of default formatter progress' do
|
112
112
|
expected_exitstatus = 0
|
113
113
|
expected_accumulator = {
|
114
114
|
status: :completed,
|
@@ -129,6 +129,36 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
|
|
129
129
|
subject
|
130
130
|
end
|
131
131
|
end
|
132
|
+
|
133
|
+
context 'when RSpec split by test examples feature is enabled' do
|
134
|
+
before do
|
135
|
+
expect(KnapsackPro::Config::Env).to receive(:rspec_split_by_test_examples?).and_return(true)
|
136
|
+
end
|
137
|
+
|
138
|
+
context 'when tag option is provided as --tag' do
|
139
|
+
let(:args) { '--tag example-value' }
|
140
|
+
|
141
|
+
it do
|
142
|
+
expect { subject }.to raise_error(/It is not allowed to use the RSpec tag option together with the RSpec split by test examples feature/)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
context 'when tag option is provided as -t' do
|
147
|
+
let(:args) { '-t example-value' }
|
148
|
+
|
149
|
+
it do
|
150
|
+
expect { subject }.to raise_error(/It is not allowed to use the RSpec tag option together with the RSpec split by test examples feature/)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
context 'when tag option is provided without delimiter' do
|
155
|
+
let(:args) { '-texample-value' }
|
156
|
+
|
157
|
+
it do
|
158
|
+
expect { subject }.to raise_error(/It is not allowed to use the RSpec tag option together with the RSpec split by test examples feature/)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
132
162
|
end
|
133
163
|
|
134
164
|
context 'when args not provided' do
|
@@ -95,10 +95,12 @@ describe KnapsackPro::Tracker do
|
|
95
95
|
end
|
96
96
|
end
|
97
97
|
|
98
|
-
it { expect(tracker.global_time).to
|
98
|
+
it { expect(tracker.global_time).to be > 0 }
|
99
99
|
it { expect(tracker.test_files_with_time.keys.size).to eql 2 }
|
100
100
|
it { expect(tracker.test_files_with_time['a_spec.rb'][:time_execution]).to eq 0 }
|
101
|
-
it
|
101
|
+
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
|
102
|
+
expect(tracker.test_files_with_time['b_spec.rb'][:time_execution]).to be > 0
|
103
|
+
end
|
102
104
|
it_behaves_like '#to_a'
|
103
105
|
end
|
104
106
|
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.
|
4
|
+
version: 2.16.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ArturT
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-05-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|