knapsack_pro 5.6.0 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -8,6 +8,8 @@ module KnapsackPro
8
8
 
9
9
  def self.run(args)
10
10
  require 'rspec/core'
11
+ require_relative '../../formatters/time_tracker'
12
+ require_relative '../../formatters/time_tracker_fetcher'
11
13
  require_relative '../../formatters/rspec_queue_summary_formatter'
12
14
  require_relative '../../formatters/rspec_queue_profile_formatter_extension'
13
15
 
@@ -27,6 +29,7 @@ module KnapsackPro
27
29
  cli_args += [
28
30
  # shows summary of all tests executed in Queue Mode at the very end
29
31
  '--format', KnapsackPro::Formatters::RSpecQueueSummaryFormatter.to_s,
32
+ '--format', KnapsackPro::Formatters::TimeTracker.to_s,
30
33
  '--default-path', runner.test_dir,
31
34
  ]
32
35
 
@@ -72,7 +75,8 @@ module KnapsackPro
72
75
 
73
76
  KnapsackPro::Hooks::Queue.call_after_queue
74
77
 
75
- KnapsackPro::Report.save_node_queue_to_api
78
+ time_tracker = KnapsackPro::Formatters::TimeTrackerFetcher.call
79
+ KnapsackPro::Report.save_node_queue_to_api(time_tracker&.queue(all_test_file_paths) || [])
76
80
 
77
81
  return {
78
82
  status: :completed,
@@ -82,15 +86,12 @@ module KnapsackPro
82
86
  subset_queue_id = KnapsackPro::Config::EnvGenerator.set_subset_queue_id
83
87
  ENV['KNAPSACK_PRO_SUBSET_QUEUE_ID'] = subset_queue_id
84
88
 
85
- KnapsackPro.tracker.reset!
86
- KnapsackPro.tracker.set_prerun_tests(test_file_paths)
87
-
88
89
  KnapsackPro::Hooks::Queue.call_before_subset_queue
89
90
 
90
91
  all_test_file_paths += test_file_paths
91
92
  cli_args = args + test_file_paths
92
93
 
93
- ensure_spec_opts_have_rspec_queue_summary_formatter
94
+ ensure_spec_opts_have_knapsack_pro_formatters
94
95
  options = ::RSpec::Core::ConfigurationOptions.new(cli_args)
95
96
  rspec_runner = ::RSpec::Core::Runner.new(options)
96
97
 
@@ -99,7 +100,7 @@ module KnapsackPro
99
100
  exitstatus = exit_code if exit_code != 0
100
101
  rescue Exception => exception
101
102
  KnapsackPro.logger.error("Having exception when running RSpec: #{exception.inspect}")
102
- KnapsackPro::Formatters::RSpecQueueSummaryFormatter.print_exit_summary
103
+ KnapsackPro::Formatters::RSpecQueueSummaryFormatter.print_exit_summary(all_test_file_paths)
103
104
  KnapsackPro::Hooks::Queue.call_after_subset_queue
104
105
  KnapsackPro::Hooks::Queue.call_after_queue
105
106
  Kernel.exit(1)
@@ -121,8 +122,6 @@ module KnapsackPro
121
122
 
122
123
  KnapsackPro::Hooks::Queue.call_after_subset_queue
123
124
 
124
- KnapsackPro::Report.save_subset_queue_to_file
125
-
126
125
  return {
127
126
  status: :next,
128
127
  runner: runner,
@@ -135,13 +134,23 @@ module KnapsackPro
135
134
  end
136
135
  end
137
136
 
138
- def self.ensure_spec_opts_have_rspec_queue_summary_formatter
139
- spec_opts = ENV['SPEC_OPTS']
137
+ def self.ensure_spec_opts_have_knapsack_pro_formatters
138
+ return unless ENV['SPEC_OPTS']
139
+
140
+ if [
141
+ ENV['SPEC_OPTS'].include?(KnapsackPro::Formatters::RSpecQueueSummaryFormatter.to_s),
142
+ ENV['SPEC_OPTS'].include?(KnapsackPro::Formatters::TimeTracker.to_s),
143
+ ].all?
144
+ return
145
+ end
140
146
 
141
- return unless spec_opts
142
- return if spec_opts.include?(KnapsackPro::Formatters::RSpecQueueSummaryFormatter.to_s)
147
+ unless ENV['SPEC_OPTS'].include?(KnapsackPro::Formatters::RSpecQueueSummaryFormatter.to_s)
148
+ ENV['SPEC_OPTS'] = "#{ENV['SPEC_OPTS']} --format #{KnapsackPro::Formatters::RSpecQueueSummaryFormatter}"
149
+ end
143
150
 
144
- ENV['SPEC_OPTS'] = "#{spec_opts} --format #{KnapsackPro::Formatters::RSpecQueueSummaryFormatter.to_s}"
151
+ unless ENV['SPEC_OPTS'].include?(KnapsackPro::Formatters::TimeTracker.to_s)
152
+ ENV['SPEC_OPTS'] = "#{ENV['SPEC_OPTS']} --format #{KnapsackPro::Formatters::TimeTracker}"
153
+ end
145
154
  end
146
155
 
147
156
  private
@@ -158,7 +167,9 @@ module KnapsackPro
158
167
  KnapsackPro.logger.info("To retry all the tests assigned to this CI node, please run the following command on your machine:")
159
168
  end
160
169
 
161
- stringified_cli_args = cli_args.join(' ').sub(" --format #{KnapsackPro::Formatters::RSpecQueueSummaryFormatter}", '')
170
+ stringified_cli_args = cli_args.join(' ')
171
+ .sub(" --format #{KnapsackPro::Formatters::RSpecQueueSummaryFormatter}", '')
172
+ .sub(" --format #{KnapsackPro::Formatters::TimeTracker}", '')
162
173
 
163
174
  KnapsackPro.logger.info(
164
175
  "bundle exec rspec #{stringified_cli_args} " +
@@ -19,8 +19,6 @@ module KnapsackPro
19
19
  cli_args = (args || '').split
20
20
  adapter_class.ensure_no_tag_option_when_rspec_split_by_test_examples_enabled!(cli_args)
21
21
 
22
- KnapsackPro.tracker.set_prerun_tests(runner.test_file_paths)
23
-
24
22
  require 'rspec/core/rake_task'
25
23
 
26
24
  task_name = 'knapsack_pro:rspec_run'
@@ -33,12 +31,30 @@ module KnapsackPro
33
31
  # because pattern does not accept test example path like spec/a_spec.rb[1:2]
34
32
  # instead we pass test files and test example paths to t.rspec_opts
35
33
  t.pattern = []
36
- t.rspec_opts = "#{args} --default-path #{runner.test_dir} #{runner.stringify_test_file_paths}"
34
+ t.rspec_opts = "#{args} #{self.formatters} --default-path #{runner.test_dir} #{runner.stringify_test_file_paths}"
37
35
  t.verbose = KnapsackPro::Config::Env.log_level < ::Logger::WARN
38
36
  end
39
37
  Rake::Task[task_name].invoke
40
38
  end
41
39
  end
40
+
41
+ # Use RSpec::Core::ConfigurationOptions to respect external configurations like .rspec
42
+ def self.formatters
43
+ require_relative '../formatters/time_tracker'
44
+
45
+ formatters = ::RSpec::Core::ConfigurationOptions
46
+ .new([])
47
+ .options
48
+ .fetch(:formatters, [])
49
+ .map do |formatter, output|
50
+ arg = "--format #{formatter}"
51
+ arg += " --out #{output}" if output
52
+ arg
53
+ end
54
+ formatters = ['--format progress'] if formatters.empty?
55
+ formatters += ["--format #{KnapsackPro::Formatters::TimeTracker}"]
56
+ formatters.join(' ')
57
+ end
42
58
  end
43
59
  end
44
60
  end
@@ -8,11 +8,10 @@ module KnapsackPro
8
8
  # to better allocate it in Queue Mode for future CI build runs
9
9
  DEFAULT_TEST_FILE_TIME = 0.0 # seconds
10
10
 
11
- attr_reader :global_time_since_beginning, :global_time, :test_files_with_time, :prerun_tests_loaded
11
+ attr_reader :global_time, :test_files_with_time, :prerun_tests_loaded
12
12
  attr_writer :current_test_path
13
13
 
14
14
  def initialize
15
- @global_time_since_beginning = 0
16
15
  KnapsackPro::Config::TempFiles.ensure_temp_directory_exists!
17
16
  FileUtils.mkdir_p(tracker_dir_path)
18
17
  set_defaults
@@ -70,12 +69,6 @@ module KnapsackPro
70
69
  @prerun_tests_loaded = true
71
70
  end
72
71
 
73
- def unexecuted_test_files
74
- @test_files_with_time.map do |path, hash|
75
- path unless hash[:measured_time]
76
- end.compact
77
- end
78
-
79
72
  def to_a
80
73
  # When the test files are not loaded in the memory then load them from the disk.
81
74
  # Useful for the Regular Mode when the memory is not shared between tracker instances.
@@ -141,7 +134,6 @@ module KnapsackPro
141
134
 
142
135
  def update_global_time(execution_time)
143
136
  @global_time += execution_time
144
- @global_time_since_beginning += execution_time
145
137
  end
146
138
 
147
139
  def update_test_file_time(execution_time)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module KnapsackPro
4
- VERSION = '5.6.0'
4
+ VERSION = '6.0.0'
5
5
  end
data/lib/knapsack_pro.rb CHANGED
@@ -11,7 +11,6 @@ require 'securerandom'
11
11
  require 'timeout'
12
12
  require_relative 'knapsack_pro/urls'
13
13
  require_relative 'knapsack_pro/version'
14
- require_relative 'knapsack_pro/extensions/time'
15
14
  require_relative 'knapsack_pro/hooks/queue'
16
15
  require_relative 'knapsack_pro/utils'
17
16
  require_relative 'knapsack_pro/config/ci/base'
@@ -42,6 +42,18 @@ describe KnapsackPro::Adapters::BaseAdapter do
42
42
  end
43
43
  end
44
44
 
45
+ describe '.split_by_test_cases_enabled?' do
46
+ subject { described_class.split_by_test_cases_enabled? }
47
+
48
+ it { expect(subject).to be false }
49
+ end
50
+
51
+ describe '.test_file_cases_for' do
52
+ subject { described_class.test_file_cases_for([]) }
53
+
54
+ it { expect { subject }.to raise_error NotImplementedError }
55
+ end
56
+
45
57
  describe '.slow_test_file?' do
46
58
  let(:adapter_class) { double }
47
59
  let(:slow_test_files) do
@@ -1,3 +1,5 @@
1
+ require_relative '../../../lib/knapsack_pro/formatters/time_tracker'
2
+
1
3
  describe KnapsackPro::Adapters::RSpecAdapter do
2
4
  it 'backwards compatibility with knapsack gem old rspec adapter name' do
3
5
  expect(KnapsackPro::Adapters::RspecAdapter.new).to be_kind_of(described_class)
@@ -8,10 +10,85 @@ describe KnapsackPro::Adapters::RSpecAdapter do
8
10
  end
9
11
 
10
12
  context do
11
- before { expect(::RSpec).to receive(:configure) }
13
+ before { expect(::RSpec).to receive(:configure).at_least(:once) }
12
14
  it_behaves_like 'adapter'
13
15
  end
14
16
 
17
+ describe '.split_by_test_cases_enabled?' do
18
+ subject { described_class.split_by_test_cases_enabled? }
19
+
20
+ before do
21
+ expect(KnapsackPro::Config::Env).to receive(:rspec_split_by_test_examples?).and_return(rspec_split_by_test_examples_enabled)
22
+ end
23
+
24
+ context 'when the RSpec split by test examples is enabled' do
25
+ let(:rspec_split_by_test_examples_enabled) { true }
26
+
27
+ it { expect(subject).to be true }
28
+
29
+ context 'when the RSpec version is < 3.3.0' do
30
+ before do
31
+ stub_const('RSpec::Core::Version::STRING', '3.2.0')
32
+ end
33
+
34
+ it do
35
+ expect { subject }.to raise_error RuntimeError, 'RSpec >= 3.3.0 is required to split test files by test examples. Learn more: https://knapsackpro.com/perma/ruby/split-by-test-examples'
36
+ end
37
+ end
38
+ end
39
+
40
+ context 'when the RSpec split by test examples is disabled' do
41
+ let(:rspec_split_by_test_examples_enabled) { false }
42
+
43
+ it { expect(subject).to be false }
44
+ end
45
+ end
46
+
47
+ describe '.test_file_cases_for' do
48
+ let(:slow_test_files) do
49
+ [
50
+ '1_spec.rb',
51
+ '2_spec.rb',
52
+ '3_spec.rb',
53
+ '4_spec.rb',
54
+ '5_spec.rb',
55
+ ]
56
+ end
57
+
58
+ subject { described_class.test_file_cases_for(slow_test_files) }
59
+
60
+ before do
61
+ logger = instance_double(Logger)
62
+ expect(KnapsackPro).to receive(:logger).and_return(logger)
63
+ expect(logger).to receive(:info).with("Generating RSpec test examples JSON report for slow test files to prepare it to be split by test examples (by individual test cases). Thanks to that, a single slow test file can be split across parallel CI nodes. Analyzing 5 slow test files.")
64
+
65
+ cmd = 'RACK_ENV=test RAILS_ENV=test bundle exec rake knapsack_pro:rspec_test_example_detector'
66
+ expect(Kernel).to receive(:system).with(cmd).and_return(cmd_result)
67
+ end
68
+
69
+ context 'when the rake task to detect RSpec test examples succeeded' do
70
+ let(:cmd_result) { true }
71
+
72
+ it 'returns test example paths for slow test files' do
73
+ rspec_test_example_detector = instance_double(KnapsackPro::TestCaseDetectors::RSpecTestExampleDetector)
74
+ expect(KnapsackPro::TestCaseDetectors::RSpecTestExampleDetector).to receive(:new).and_return(rspec_test_example_detector)
75
+
76
+ test_file_example_paths = double
77
+ expect(rspec_test_example_detector).to receive(:test_file_example_paths).and_return(test_file_example_paths)
78
+
79
+ expect(subject).to eq test_file_example_paths
80
+ end
81
+ end
82
+
83
+ context 'when the rake task to detect RSpec test examples failed' do
84
+ let(:cmd_result) { false }
85
+
86
+ it do
87
+ expect { subject }.to raise_error(RuntimeError, 'Could not generate JSON report for RSpec. Rake task failed when running RACK_ENV=test RAILS_ENV=test bundle exec rake knapsack_pro:rspec_test_example_detector')
88
+ end
89
+ end
90
+ end
91
+
15
92
  describe '.ensure_no_tag_option_when_rspec_split_by_test_examples_enabled!' do
16
93
  let(:cli_args) { double }
17
94
 
@@ -162,59 +239,70 @@ describe KnapsackPro::Adapters::RSpecAdapter do
162
239
  end
163
240
  end
164
241
 
165
- describe '.test_path' do
166
- let(:example_group) do
167
- {
168
- file_path: '1_shared_example.rb',
169
- parent_example_group: {
170
- file_path: '2_shared_example.rb',
171
- parent_example_group: {
172
- file_path: 'a_spec.rb'
173
- }
174
- }
175
- }
242
+ describe '.file_path_for' do
243
+ let(:current_example) { ::RSpec.describe.example }
244
+
245
+ subject { described_class.file_path_for(current_example) }
246
+
247
+ context "when id ends in _spec.rb" do
248
+ it "returns the first part of the id" do
249
+ allow(current_example).to receive(:id).and_return("./foo_spec.rb[1:1]")
250
+
251
+ expect(subject).to eq('./foo_spec.rb')
252
+ end
176
253
  end
177
- let(:current_example) do
178
- OpenStruct.new(metadata: {
179
- example_group: example_group
180
- })
254
+
255
+ context "when id does not end in _spec.rb" do
256
+ it "returns the file_path" do
257
+ allow(current_example).to receive(:id).and_return("./foo.rb")
258
+ allow(current_example).to receive(:metadata).and_return(file_path: "./foo_spec.rb")
259
+
260
+ expect(subject).to eq('./foo_spec.rb')
261
+ end
181
262
  end
182
263
 
183
- subject { described_class.test_path(current_example) }
264
+ context "when id and file_path do not end in _spec.rb" do
265
+ it "returns the example_group's file_path" do
266
+ allow(current_example).to receive(:id).and_return("./foo.rb")
267
+ allow(current_example).to receive(:metadata).and_return(
268
+ file_path: "./foo.rb", example_group: { file_path: "./foo_spec.rb" }
269
+ )
184
270
 
185
- it { should eql 'a_spec.rb' }
271
+ expect(subject).to eq('./foo_spec.rb')
272
+ end
273
+ end
186
274
 
187
- context 'with turnip features' do
188
- describe 'when the turnip version is less than 2' do
189
- let(:example_group) do
190
- {
191
- file_path: "./spec/features/logging_in.feature",
192
- turnip: true,
275
+ context "when id, file_path, and example_group's file_path do not end in _spec.rb" do
276
+ it "returns the top_level_group's file_path" do
277
+ allow(current_example).to receive(:id).and_return("./foo.rb")
278
+ allow(current_example).to receive(:metadata).and_return(
279
+ file_path: "./foo.rb",
280
+ example_group: {
281
+ file_path: "./foo.rb",
193
282
  parent_example_group: {
194
- file_path: "gems/turnip-1.2.4/lib/turnip/rspec.rb"
283
+ file_path: "./foo_spec.rb",
195
284
  }
196
285
  }
197
- end
286
+ )
198
287
 
199
- before { stub_const("Turnip::VERSION", '1.2.4') }
200
-
201
- it { should eql './spec/features/logging_in.feature' }
288
+ expect(subject).to eq('./foo_spec.rb')
202
289
  end
290
+ end
203
291
 
204
- describe 'when turnip is version 2 or greater' do
205
- let(:example_group) do
206
- {
207
- file_path: "gems/turnip-2.0.0/lib/turnip/rspec.rb",
208
- turnip: true,
292
+ context "when id, file_path, example_group's, and top_level_group's file_path do not end in _spec.rb" do
293
+ it "returns empty string" do
294
+ allow(current_example).to receive(:id).and_return("./foo.rb")
295
+ allow(current_example).to receive(:metadata).and_return(
296
+ file_path: "./foo.rb",
297
+ example_group: {
298
+ file_path: "./foo.rb",
209
299
  parent_example_group: {
210
- file_path: "./spec/features/logging_in.feature",
300
+ file_path: "./foo.rb",
211
301
  }
212
302
  }
213
- end
214
-
215
- before { stub_const("Turnip::VERSION", '2.0.0') }
303
+ )
216
304
 
217
- it { should eql './spec/features/logging_in.feature' }
305
+ expect(subject).to eq('')
218
306
  end
219
307
  end
220
308
  end
@@ -223,155 +311,48 @@ describe KnapsackPro::Adapters::RSpecAdapter do
223
311
  let(:config) { double }
224
312
 
225
313
  describe '#bind_time_tracker' do
226
- let(:tracker) { instance_double(KnapsackPro::Tracker) }
227
- let(:logger) { instance_double(Logger) }
228
- let(:global_time) { 'Global time: 01m 05s' }
229
- let(:test_path) { 'spec/a_spec.rb' }
230
314
  let(:current_example) { double(metadata: {}) }
231
315
 
232
316
  context "when the example's metadata has :focus tag AND RSpec inclusion rule includes :focus" do
233
317
  let(:current_example) { double(metadata: { focus: true }) }
318
+ let(:test_path) { 'spec/a_spec.rb' }
234
319
 
235
320
  it do
236
- expect(KnapsackPro::Config::Env).to receive(:rspec_split_by_test_examples?).and_return(false)
237
-
238
- expect(config).to receive(:prepend_before).with(:context).and_yield
239
-
240
- allow(KnapsackPro).to receive(:tracker).and_return(tracker)
241
- expect(tracker).to receive(:start_timer).ordered
242
-
243
321
  expect(config).to receive(:around).with(:each).and_yield(current_example)
244
322
  expect(::RSpec).to receive(:configure).and_yield(config)
245
323
 
246
- expect(tracker).to receive(:current_test_path).ordered.and_return(test_path)
247
- expect(tracker).to receive(:stop_timer).ordered
248
-
249
- expect(described_class).to receive(:test_path).with(current_example).and_return(test_path)
250
-
251
- expect(tracker).to receive(:current_test_path=).with(test_path).ordered
324
+ expect(described_class).to receive(:file_path_for).with(current_example).and_return(test_path)
252
325
 
253
326
  expect(described_class).to receive_message_chain(:rspec_configuration, :filter, :rules, :[]).with(:focus).and_return(true)
254
327
 
255
328
  expect {
256
329
  subject.bind_time_tracker
257
- }.to raise_error /We detected a test file path spec\/a_spec\.rb with a test using the metadata `:focus` tag/
330
+ }.to raise_error /Knapsack Pro found an example tagged with focus in spec\/a_spec\.rb/i
258
331
  end
259
332
  end
260
333
 
261
- context 'when rspec split by test examples is disabled' do
262
- before do
263
- expect(KnapsackPro::Config::Env).to receive(:rspec_split_by_test_examples?).and_return(false)
264
- end
334
+ context 'with no focus' do
335
+ let(:logger) { instance_double(Logger) }
336
+ let(:duration) { 65 }
337
+ let(:global_time) { 'Global time execution for tests: 01m 05s' }
338
+ let(:time_tracker) { instance_double(KnapsackPro::Formatters::TimeTracker) }
265
339
 
266
340
  it 'records time for current test path' do
267
- expect(config).to receive(:prepend_before).with(:context).and_yield
268
-
269
- allow(KnapsackPro).to receive(:tracker).and_return(tracker)
270
- expect(tracker).to receive(:start_timer).ordered
271
-
272
341
  expect(config).to receive(:around).with(:each).and_yield(current_example)
273
- expect(config).to receive(:append_after).with(:context).and_yield
274
342
  expect(config).to receive(:after).with(:suite).and_yield
275
- expect(::RSpec).to receive(:configure).and_yield(config)
276
-
277
- expect(tracker).to receive(:current_test_path).ordered.and_return(test_path)
278
- expect(tracker).to receive(:stop_timer).ordered
279
-
280
- expect(described_class).to receive(:test_path).with(current_example).and_return(test_path)
281
-
282
- expect(tracker).to receive(:current_test_path=).with(test_path).ordered
343
+ expect(::RSpec).to receive(:configure).twice.and_yield(config)
283
344
 
284
345
  expect(current_example).to receive(:run)
285
346
 
286
- expect(tracker).to receive(:stop_timer).ordered
347
+ expect(time_tracker).to receive(:batch_duration).and_return(duration)
348
+ expect(KnapsackPro::Formatters::TimeTrackerFetcher).to receive(:call).and_return(time_tracker)
287
349
 
288
- expect(KnapsackPro::Presenter).to receive(:global_time).and_return(global_time)
289
350
  expect(KnapsackPro).to receive(:logger).and_return(logger)
290
351
  expect(logger).to receive(:debug).with(global_time)
291
352
 
292
353
  subject.bind_time_tracker
293
354
  end
294
355
  end
295
-
296
- context 'when rspec split by test examples is enabled' do
297
- let(:test_example_path) { 'spec/a_spec.rb[1:1]' }
298
-
299
- before do
300
- expect(KnapsackPro::Config::Env).to receive(:rspec_split_by_test_examples?).and_return(true)
301
- end
302
-
303
- context 'when current test_path is a slow test file' do
304
- before do
305
- expect(described_class).to receive(:slow_test_file?).with(described_class, test_path).and_return(true)
306
- end
307
-
308
- it 'records time for example.id' do
309
- expect(current_example).to receive(:id).and_return(test_example_path)
310
-
311
- expect(config).to receive(:prepend_before).with(:context).and_yield
312
-
313
- allow(KnapsackPro).to receive(:tracker).and_return(tracker)
314
- expect(tracker).to receive(:start_timer).ordered
315
-
316
- expect(config).to receive(:around).with(:each).and_yield(current_example)
317
- expect(config).to receive(:append_after).with(:context).and_yield
318
- expect(config).to receive(:after).with(:suite).and_yield
319
- expect(::RSpec).to receive(:configure).and_yield(config)
320
-
321
- expect(tracker).to receive(:current_test_path).ordered.and_return(test_path)
322
- expect(tracker).to receive(:stop_timer).ordered
323
-
324
- expect(described_class).to receive(:test_path).with(current_example).and_return(test_path)
325
-
326
- expect(tracker).to receive(:current_test_path=).with(test_example_path).ordered
327
-
328
- expect(current_example).to receive(:run)
329
-
330
- expect(tracker).to receive(:stop_timer).ordered
331
-
332
- expect(KnapsackPro::Presenter).to receive(:global_time).and_return(global_time)
333
- expect(KnapsackPro).to receive(:logger).and_return(logger)
334
- expect(logger).to receive(:debug).with(global_time)
335
-
336
- subject.bind_time_tracker
337
- end
338
- end
339
-
340
- context 'when current test_path is not a slow test file' do
341
- before do
342
- expect(described_class).to receive(:slow_test_file?).with(described_class, test_path).and_return(false)
343
- end
344
-
345
- it 'records time for current test path' do
346
- expect(config).to receive(:prepend_before).with(:context).and_yield
347
-
348
- allow(KnapsackPro).to receive(:tracker).and_return(tracker)
349
- expect(tracker).to receive(:start_timer).ordered
350
-
351
- expect(config).to receive(:around).with(:each).and_yield(current_example)
352
- expect(config).to receive(:append_after).with(:context).and_yield
353
- expect(config).to receive(:after).with(:suite).and_yield
354
- expect(::RSpec).to receive(:configure).and_yield(config)
355
-
356
- expect(described_class).to receive(:test_path).with(current_example).and_return(test_path)
357
-
358
- expect(tracker).to receive(:current_test_path).ordered.and_return(test_path)
359
- expect(tracker).to receive(:stop_timer).ordered
360
-
361
- expect(tracker).to receive(:current_test_path=).with(test_path).ordered
362
-
363
- expect(current_example).to receive(:run)
364
-
365
- expect(tracker).to receive(:stop_timer).ordered
366
-
367
- expect(KnapsackPro::Presenter).to receive(:global_time).and_return(global_time)
368
- expect(KnapsackPro).to receive(:logger).and_return(logger)
369
- expect(logger).to receive(:debug).with(global_time)
370
-
371
- subject.bind_time_tracker
372
- end
373
- end
374
- end
375
356
  end
376
357
 
377
358
  describe '#bind_save_report' do
@@ -379,7 +360,11 @@ describe KnapsackPro::Adapters::RSpecAdapter do
379
360
  expect(config).to receive(:after).with(:suite).and_yield
380
361
  expect(::RSpec).to receive(:configure).and_yield(config)
381
362
 
382
- expect(KnapsackPro::Report).to receive(:save)
363
+ time_tracker = instance_double(KnapsackPro::Formatters::TimeTracker)
364
+ times = [{ path: "foo_spec.rb", time_execution: 1.0 }]
365
+ expect(time_tracker).to receive(:batch).and_return(times)
366
+ expect(KnapsackPro::Formatters::TimeTrackerFetcher).to receive(:call).and_return(time_tracker)
367
+ expect(KnapsackPro::Report).to receive(:save).with(times)
383
368
 
384
369
  subject.bind_save_report
385
370
  end