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.
@@ -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://github.com/KnapsackPro/knapsack_pro-ruby#what-happens-when-knapsack-pro-api-is-not-availablenot-reachable-temporarily")
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://github.com/KnapsackPro/knapsack_pro-ruby#what-happens-when-knapsack-pro-api-is-not-availablenot-reachable-temporarily")
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
- # if user didn't provide the format then use explicitly default progress formatter
18
- # in order to avoid KnapsackPro::Formatters::RSpecQueueSummaryFormatter being the only default formatter
19
- if !cli_args.any? { |arg| arg.start_with?('-f') || arg.start_with?('--format')}
20
- cli_args += ['--format', 'progress']
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
@@ -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.1 # seconds
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
- update_global_time(execution_time)
28
- update_test_file_time(execution_time)
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
- @test_path = nil
75
+ @current_test_path = nil
67
76
  end
68
77
 
69
78
  def update_global_time(execution_time)
@@ -1,3 +1,3 @@
1
1
  module KnapsackPro
2
- VERSION = '2.11.0'
2
+ VERSION = '2.16.0'
3
3
  end
@@ -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
- allow(KnapsackPro).to receive(:tracker).and_return(tracker)
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
- allow(KnapsackPro).to receive(:tracker).and_return(tracker)
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
- allow(KnapsackPro).to receive(:tracker).and_return(tracker)
164
- expect(tracker).to receive(:current_test_path=).with(test_path)
165
- expect(tracker).to receive(:start_timer)
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 param is not provided' do
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 param is provided as --format' do
58
+ context 'when format option is provided as --format' do
59
59
  let(:args) { '--format documentation' }
60
60
 
61
- it 'uses provided format param instead of default formatter progress' do
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 param is provided as -f' do
83
+ context 'when format option is provided as -f' do
84
84
  let(:args) { '-f d' }
85
85
 
86
- it 'uses provided format param instead of default formatter progress' do
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 param is provided without a delimiter' do
108
+ context 'when format option is provided without a delimiter' do
109
109
  let(:args) { '-fMyCustomFormatter' }
110
110
 
111
- it 'uses provided format param instead of default formatter progress' do
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 eq 0 }
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 { expect(tracker.test_files_with_time['b_spec.rb'][:time_execution]).to eq 0 }
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.11.0
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-01-04 00:00:00.000000000 Z
11
+ date: 2021-05-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake