knapsack_pro 2.17.0 → 3.0.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: e22a25e69f6cfda9a42568aed336631f601423b0b930525fc8becbc1b1ee7fe9
4
- data.tar.gz: ac1df0750000066a933cc4814f185d09a6d38ce09028680c8f20678bb7b0473e
3
+ metadata.gz: e5187abddda32d96fdec255f8aa2e740f0c85e856d882fa31790e4e8c93a87e8
4
+ data.tar.gz: 22320f9e0795684f81a53fb4fffb29295b28b0068fef5c54739c14e423eed003
5
5
  SHA512:
6
- metadata.gz: 91687797a4f7c80bcd852f7c8e5ec18f523eb5a9375b3dc069b6abce67bc58ccda010f36b6c003fefa01971e628518bf0b9f9e855d7992c86d9ea7dcb375be4b
7
- data.tar.gz: c32195b9e6fd4fdee7b5087f61f7d1b28fdb7a6a995930d23e109eda296156026a79fea579e06540e2a64c75ee3a03a6b216f2a8492eb48e422bc9193aad0146
6
+ metadata.gz: 07ea71f123f6995a6174b45561818c9ff5bf2565a141d1c49261ebf448027953fd1e822806ed1a04db962dad7fcee0fe27d025b4823c58b34d0519d2f04275a0
7
+ data.tar.gz: a84f3ae6a0b69d33e16e3efd5338e13e3b09c8db9bea6f26d77523436ff370722341586732ce28df4011f5379102fdae18ce9f7a5673286f2f0323c5b5102709
data/CHANGELOG.md CHANGED
@@ -1,5 +1,38 @@
1
1
  # Change Log
2
2
 
3
+ ### 3.0.0
4
+
5
+ * __(breaking change)__ Remove support for RSpec 2.x. This change was already done by accident in [the pull request](https://github.com/KnapsackPro/knapsack_pro-ruby/pull/143) when we added the RSpec `context` hook, which is available only since RSpec 3.x.
6
+ * Use RSpec `example` block argument instead of the global `RSpec.current_example`. This allows to run tests with the `async-rspec` gem.
7
+
8
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/153
9
+
10
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v2.18.2...v3.0.0
11
+
12
+ ### 2.18.2
13
+
14
+ * Track all test files assigned to a CI node in Regular Mode including pending test files in order to retry proper set of tests on the retried CI node
15
+
16
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/152
17
+
18
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v2.18.1...v2.18.2
19
+
20
+ ### 2.18.1
21
+
22
+ * Ensure RSpec is loaded to check its version for RSpec split by test examples feature
23
+
24
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/151
25
+
26
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v2.18.0...v2.18.1
27
+
28
+ ### 2.18.0
29
+
30
+ * Do not allow to use the RSpec tag option together with the RSpec split by test examples feature in knapsack_pro gem in Regular Mode
31
+
32
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/148
33
+
34
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v2.17.0...v2.18.0
35
+
3
36
  ### 2.17.0
4
37
 
5
38
  * Use Ruby 3 in development and add small improvements
data/README.md CHANGED
@@ -440,13 +440,13 @@ If your test suite is very long and the RSpec output is too long for your CI nod
440
440
  ### Additional info about queue mode
441
441
 
442
442
  * You should use a separate API token for queue mode than for regular mode to avoid problems with test suite split (especially in case you would like to go back to regular mode).
443
- There might be some cached test suite splits for git commits you have run in past for API token you used in queue mode because of the [flag `KNAPSACK_PRO_FIXED_TEST_SUITE_SPLIT=true` for regular mode which is default](#knapsack_pro_fixed_test_suite_splite-test-suite-split-based-on-seed).
443
+ There might be some cached test suite splits for git commits you have run in past for API token you used in queue mode because of the [flag `KNAPSACK_PRO_FIXED_TEST_SUITE_SPLIT=true` for regular mode which is default](#knapsack_pro_fixed_test_suite_split-test-suite-split-based-on-seed).
444
444
 
445
445
  * If you are not using one of the [supported CI providers](#supported-ci-providers) then please note that the knapsack_pro gem doesn't have a CI build ID in order to generate a queue for each particular CI build. This may result in two different CI builds taking tests from the same queue when CI builds are running at the same time against the same git commit.
446
446
 
447
447
  To avoid this you should specify a unique `KNAPSACK_PRO_CI_NODE_BUILD_ID` environment variable for each CI build. This mean that each CI node that is part of particular CI build should have the same value for `KNAPSACK_PRO_CI_NODE_BUILD_ID`.
448
448
 
449
- * Note that in the Queue Mode by default you cannot retry the failed CI node with exactly the same subset of tests that were run on the CI node in the first place. It's possible in regular mode ([read more](#knapsack_pro_fixed_test_suite_splite-test-suite-split-based-on-seed)). If you want to have similar behavior in Queue Mode you need to explicitly [enable it](#knapsack_pro_fixed_queue_split-remember-queue-split-on-retry-ci-node).
449
+ * Note that in the Queue Mode by default you cannot retry the failed CI node with exactly the same subset of tests that were run on the CI node in the first place. It's possible in regular mode ([read more](#knapsack_pro_fixed_test_suite_split-test-suite-split-based-on-seed)). If you want to have similar behavior in Queue Mode you need to explicitly [enable it](#knapsack_pro_fixed_queue_split-remember-queue-split-on-retry-ci-node).
450
450
 
451
451
  By default the Queue Mode works this way:
452
452
 
@@ -626,7 +626,7 @@ This is only for maintainer of knapsack_pro gem. Not for the end users.
626
626
 
627
627
  ### Required CI configuration if you use retry single failed CI node feature on your CI server when KNAPSACK_PRO_FIXED_QUEUE_SPLIT=true (in Queue Mode) or KNAPSACK_PRO_FIXED_TEST_SUITE_SPLIT=true (in Regular Mode)
628
628
 
629
- Read below required configuration step if you use Queue Mode and you set [`KNAPSACK_PRO_FIXED_QUEUE_SPLIT=true`](#knapsack_pro_fixed_queue_split-remember-queue-split-on-retry-ci-node) or you use Regular Mode which has by default [`KNAPSACK_PRO_FIXED_TEST_SUITE_SPLIT=true`](#knapsack_pro_fixed_test_suite_splite-test-suite-split-based-on-seed).
629
+ Read below required configuration step if you use Queue Mode and you set [`KNAPSACK_PRO_FIXED_QUEUE_SPLIT=true`](#knapsack_pro_fixed_queue_split-remember-queue-split-on-retry-ci-node) or you use Regular Mode which has by default [`KNAPSACK_PRO_FIXED_TEST_SUITE_SPLIT=true`](#knapsack_pro_fixed_test_suite_split-test-suite-split-based-on-seed).
630
630
 
631
631
  * __IMPORTANT:__ If you use __the feature to retry only a single failed CI node__ on your CI server (for instance you use Buildkite and you use [auto-retry](https://buildkite.com/docs/pipelines/command-step#retry-attributes) for the failed job) then you need to be aware of [a race condition that could happen](https://github.com/KnapsackPro/knapsack_pro-ruby/pull/100). knapsack_pro should not allow running tests in Fallback Mode in the case when the failed CI node was retried to prevent running the wrong set of tests.
632
632
 
@@ -838,7 +838,7 @@ Here you can read how to configure [junit formatter](https://knapsackpro.com/faq
838
838
  # spec_helper.rb or rails_helper.rb
839
839
 
840
840
  # TODO This must be the same path as value for rspec --out argument
841
- # Note the path should not contain sign ~, for instance path ~/project/tmp/rspec.xml may not work. Please use full path instead.
841
+ # Note the path should not contain ~ char, for instance path ~/project/tmp/rspec.xml may not work. Please use full path instead.
842
842
  TMP_RSPEC_XML_REPORT = 'tmp/rspec.xml'
843
843
  # move results to FINAL_RSPEC_XML_REPORT so the results won't accumulate with duplicated xml tags in TMP_RSPEC_XML_REPORT
844
844
  FINAL_RSPEC_XML_REPORT = 'tmp/rspec_final_results.xml'
data/knapsack_pro.gemspec CHANGED
@@ -28,7 +28,7 @@ Gem::Specification.new do |spec|
28
28
  spec.add_dependency 'rake', '>= 0'
29
29
 
30
30
  spec.add_development_dependency 'bundler', '>= 1.6'
31
- spec.add_development_dependency 'rspec', '~> 3.0', '>= 2.10.0'
31
+ spec.add_development_dependency 'rspec', '~> 3.0'
32
32
  spec.add_development_dependency 'rspec-its', '~> 1.3'
33
33
  spec.add_development_dependency 'cucumber', '>= 0'
34
34
  spec.add_development_dependency 'spinach', '>= 0.8'
@@ -3,8 +3,31 @@ module KnapsackPro
3
3
  class RSpecAdapter < BaseAdapter
4
4
  TEST_DIR_PATTERN = 'spec/**{,/*/**}/*_spec.rb'
5
5
 
6
- def self.test_path(example_group)
7
- if defined?(::Turnip) && ::Turnip::VERSION.to_i < 2
6
+ def self.ensure_no_tag_option_when_rspec_split_by_test_examples_enabled!(cli_args)
7
+ if KnapsackPro::Config::Env.rspec_split_by_test_examples? && has_tag_option?(cli_args)
8
+ 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'
9
+ KnapsackPro.logger.error(error_message)
10
+ raise error_message
11
+ end
12
+ end
13
+
14
+ def self.has_tag_option?(cli_args)
15
+ # use start_with? because user can define tag option in a few ways:
16
+ # -t mytag
17
+ # -tmytag
18
+ # --tag mytag
19
+ # --tag=mytag
20
+ cli_args.any? { |arg| arg.start_with?('-t') || arg.start_with?('--tag') }
21
+ end
22
+
23
+ def self.has_format_option?(cli_args)
24
+ cli_args.any? { |arg| arg.start_with?('-f') || arg.start_with?('--format') }
25
+ end
26
+
27
+ def self.test_path(example)
28
+ example_group = example.metadata[:example_group]
29
+
30
+ if defined?(::Turnip) && Gem::Version.new(::Turnip::VERSION) < Gem::Version.new('2.0.0')
8
31
  unless example_group[:turnip]
9
32
  until example_group[:parent_example_group].nil?
10
33
  example_group = example_group[:parent_example_group]
@@ -30,14 +53,7 @@ module KnapsackPro
30
53
  # this way we count time spend in runtime for the previous test example after around(:each) is already done
31
54
  KnapsackPro.tracker.stop_timer
32
55
 
33
- current_example_group =
34
- if ::RSpec.respond_to?(:current_example)
35
- ::RSpec.current_example.metadata[:example_group]
36
- else
37
- example.metadata
38
- end
39
-
40
- current_test_path = KnapsackPro::Adapters::RSpecAdapter.test_path(current_example_group)
56
+ current_test_path = KnapsackPro::Adapters::RSpecAdapter.test_path(example)
41
57
 
42
58
  KnapsackPro.tracker.current_test_path =
43
59
  if KnapsackPro::Config::Env.rspec_split_by_test_examples? && KnapsackPro::Adapters::RSpecAdapter.slow_test_file?(RSpecAdapter, current_test_path)
@@ -34,6 +34,7 @@ module KnapsackPro
34
34
  test_files_to_run = all_test_files_to_run
35
35
 
36
36
  if adapter_class == KnapsackPro::Adapters::RSpecAdapter && KnapsackPro::Config::Env.rspec_split_by_test_examples?
37
+ require 'rspec/core/version'
37
38
  unless Gem::Version.new(::RSpec::Core::Version::STRING) >= Gem::Version.new('3.3.0')
38
39
  raise 'RSpec >= 3.3.0 is required to split test files by test examples. Learn more: https://github.com/KnapsackPro/knapsack_pro-ruby#split-test-files-by-test-cases'
39
40
  end
@@ -257,6 +257,14 @@ module KnapsackPro
257
257
  ENV['KNAPSACK_PRO_LOG_DIR']
258
258
  end
259
259
 
260
+ def test_runner_adapter
261
+ ENV['KNAPSACK_PRO_TEST_RUNNER_ADAPTER']
262
+ end
263
+
264
+ def set_test_runner_adapter(adapter_class)
265
+ ENV['KNAPSACK_PRO_TEST_RUNNER_ADAPTER'] = adapter_class.to_s.split('::').last
266
+ end
267
+
260
268
  private
261
269
 
262
270
  def required_env(env_name)
@@ -6,11 +6,14 @@ module KnapsackPro
6
6
  ENV['KNAPSACK_PRO_RECORDING_ENABLED'] = 'true'
7
7
 
8
8
  adapter_class = KnapsackPro::Adapters::CucumberAdapter
9
+ KnapsackPro::Config::Env.set_test_runner_adapter(adapter_class)
9
10
  runner = new(adapter_class)
10
11
 
11
12
  if runner.test_files_to_execute_exist?
12
13
  adapter_class.verify_bind_method_called
13
14
 
15
+ KnapsackPro.tracker.set_prerun_tests(runner.test_file_paths)
16
+
14
17
  require 'cucumber/rake/task'
15
18
 
16
19
  task_name = 'knapsack_pro:cucumber_run'
@@ -6,11 +6,14 @@ module KnapsackPro
6
6
  ENV['KNAPSACK_PRO_RECORDING_ENABLED'] = 'true'
7
7
 
8
8
  adapter_class = KnapsackPro::Adapters::MinitestAdapter
9
+ KnapsackPro::Config::Env.set_test_runner_adapter(adapter_class)
9
10
  runner = new(adapter_class)
10
11
 
11
12
  if runner.test_files_to_execute_exist?
12
13
  adapter_class.verify_bind_method_called
13
14
 
15
+ KnapsackPro.tracker.set_prerun_tests(runner.test_file_paths)
16
+
14
17
  task_name = 'knapsack_pro:minitest_run'
15
18
 
16
19
  if Rake::Task.task_defined?(task_name)
@@ -9,7 +9,9 @@ module KnapsackPro
9
9
  ENV['KNAPSACK_PRO_QUEUE_RECORDING_ENABLED'] = 'true'
10
10
  ENV['KNAPSACK_PRO_QUEUE_ID'] = KnapsackPro::Config::EnvGenerator.set_queue_id
11
11
 
12
- runner = new(KnapsackPro::Adapters::CucumberAdapter)
12
+ adapter_class = KnapsackPro::Adapters::CucumberAdapter
13
+ KnapsackPro::Config::Env.set_test_runner_adapter(adapter_class)
14
+ runner = new(adapter_class)
13
15
 
14
16
  accumulator = {
15
17
  status: :next,
@@ -9,7 +9,9 @@ module KnapsackPro
9
9
  ENV['KNAPSACK_PRO_QUEUE_RECORDING_ENABLED'] = 'true'
10
10
  ENV['KNAPSACK_PRO_QUEUE_ID'] = KnapsackPro::Config::EnvGenerator.set_queue_id
11
11
 
12
- runner = new(KnapsackPro::Adapters::MinitestAdapter)
12
+ adapter_class = KnapsackPro::Adapters::MinitestAdapter
13
+ KnapsackPro::Config::Env.set_test_runner_adapter(adapter_class)
14
+ runner = new(adapter_class)
13
15
 
14
16
  # Add test_dir to load path to make work:
15
17
  # require 'test_helper'
@@ -11,18 +11,15 @@ module KnapsackPro
11
11
  ENV['KNAPSACK_PRO_QUEUE_RECORDING_ENABLED'] = 'true'
12
12
  ENV['KNAPSACK_PRO_QUEUE_ID'] = KnapsackPro::Config::EnvGenerator.set_queue_id
13
13
 
14
- runner = new(KnapsackPro::Adapters::RSpecAdapter)
14
+ adapter_class = KnapsackPro::Adapters::RSpecAdapter
15
+ KnapsackPro::Config::Env.set_test_runner_adapter(adapter_class)
16
+ runner = new(adapter_class)
15
17
 
16
18
  cli_args = (args || '').split
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
22
- end
19
+ adapter_class.ensure_no_tag_option_when_rspec_split_by_test_examples_enabled!(cli_args)
23
20
 
24
21
  # 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)
22
+ cli_args += ['--format', 'progress'] unless adapter_class.has_format_option?(cli_args)
26
23
 
27
24
  cli_args += [
28
25
  # shows summary of all tests executed in Queue Mode at the very end
@@ -154,19 +151,6 @@ module KnapsackPro
154
151
  ::RSpec.configuration.reset_filters
155
152
  end
156
153
  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
170
154
  end
171
155
  end
172
156
  end
@@ -6,11 +6,17 @@ module KnapsackPro
6
6
  ENV['KNAPSACK_PRO_RECORDING_ENABLED'] = 'true'
7
7
 
8
8
  adapter_class = KnapsackPro::Adapters::RSpecAdapter
9
+ KnapsackPro::Config::Env.set_test_runner_adapter(adapter_class)
9
10
  runner = new(adapter_class)
10
11
 
11
12
  if runner.test_files_to_execute_exist?
12
13
  adapter_class.verify_bind_method_called
13
14
 
15
+ cli_args = (args || '').split
16
+ adapter_class.ensure_no_tag_option_when_rspec_split_by_test_examples_enabled!(cli_args)
17
+
18
+ KnapsackPro.tracker.set_prerun_tests(runner.test_file_paths)
19
+
14
20
  require 'rspec/core/rake_task'
15
21
 
16
22
  task_name = 'knapsack_pro:rspec_run'
@@ -5,11 +5,14 @@ module KnapsackPro
5
5
  ENV['KNAPSACK_PRO_TEST_SUITE_TOKEN'] = KnapsackPro::Config::Env.test_suite_token_spinach
6
6
 
7
7
  adapter_class = KnapsackPro::Adapters::SpinachAdapter
8
+ KnapsackPro::Config::Env.set_test_runner_adapter(adapter_class)
8
9
  runner = new(adapter_class)
9
10
 
10
11
  if runner.test_files_to_execute_exist?
11
12
  adapter_class.verify_bind_method_called
12
13
 
14
+ KnapsackPro.tracker.set_prerun_tests(runner.test_file_paths)
15
+
13
16
  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}]
14
17
 
15
18
  Kernel.system(cmd)
@@ -6,11 +6,14 @@ module KnapsackPro
6
6
  ENV['KNAPSACK_PRO_RECORDING_ENABLED'] = 'true'
7
7
 
8
8
  adapter_class = KnapsackPro::Adapters::TestUnitAdapter
9
+ KnapsackPro::Config::Env.set_test_runner_adapter(adapter_class)
9
10
  runner = new(adapter_class)
10
11
 
11
12
  if runner.test_files_to_execute_exist?
12
13
  adapter_class.verify_bind_method_called
13
14
 
15
+ KnapsackPro.tracker.set_prerun_tests(runner.test_file_paths)
16
+
14
17
  cli_args =
15
18
  (args || '').split +
16
19
  runner.test_file_paths.map do |f|
@@ -6,16 +6,22 @@ module KnapsackPro
6
6
  # to better allocate it in Queue Mode for future CI build runs
7
7
  DEFAULT_TEST_FILE_TIME = 0.0 # seconds
8
8
 
9
- attr_reader :global_time_since_beginning, :global_time, :test_files_with_time
9
+ attr_reader :global_time_since_beginning, :global_time, :test_files_with_time, :prerun_tests_loaded
10
10
  attr_writer :current_test_path
11
11
 
12
12
  def initialize
13
13
  @global_time_since_beginning = 0
14
+ FileUtils.mkdir_p(tracker_dir_path)
14
15
  set_defaults
15
16
  end
16
17
 
17
18
  def reset!
18
19
  set_defaults
20
+
21
+ # Remove report only when the reset! method is called explicitly.
22
+ # The report should be persisted on the disk so that multiple tracker instances can share the report state.
23
+ # Tracker instance can be created by knapsack_pro process and a separate tracker is created by rake task (e.g., RSpec) in Regular Mode.
24
+ File.delete(prerun_tests_report_path) if File.exists?(prerun_tests_report_path)
19
25
  end
20
26
 
21
27
  def start_timer
@@ -54,9 +60,18 @@ module KnapsackPro
54
60
  measured_time: false,
55
61
  }
56
62
  end
63
+
64
+ save_prerun_tests_report(@test_files_with_time)
65
+
66
+ @prerun_tests_loaded = true
57
67
  end
58
68
 
59
69
  def to_a
70
+ # When the test files are not loaded in the memory then load them from the disk.
71
+ # Useful for the Regular Mode when the memory is not shared between tracker instances.
72
+ # Tracker instance can be created by knapsack_pro process and a separate tracker is created by rake task (e.g., RSpec)
73
+ load_prerun_tests unless prerun_tests_loaded
74
+
60
75
  test_files = []
61
76
  @test_files_with_time.each do |path, hash|
62
77
  test_files << {
@@ -73,6 +88,44 @@ module KnapsackPro
73
88
  @global_time = 0
74
89
  @test_files_with_time = {}
75
90
  @current_test_path = nil
91
+ @prerun_tests_loaded = false
92
+ end
93
+
94
+ def tracker_dir_path
95
+ "#{KnapsackPro::Config::Env::TMP_DIR}/tracker"
96
+ end
97
+
98
+ def prerun_tests_report_path
99
+ raise 'Test runner adapter not set. Report a bug to the Knapsack Pro support.' unless KnapsackPro::Config::Env.test_runner_adapter
100
+ report_name = "prerun_tests_#{KnapsackPro::Config::Env.test_runner_adapter}_node_#{KnapsackPro::Config::Env.ci_node_index}.json"
101
+ File.join(tracker_dir_path, report_name)
102
+ end
103
+
104
+ def save_prerun_tests_report(hash)
105
+ report_json = JSON.pretty_generate(hash)
106
+
107
+ File.open(prerun_tests_report_path, 'w+') do |f|
108
+ f.write(report_json)
109
+ end
110
+ end
111
+
112
+ def read_prerun_tests_report
113
+ JSON.parse(File.read(prerun_tests_report_path))
114
+ end
115
+
116
+ def load_prerun_tests
117
+ read_prerun_tests_report.each do |test_file_path, hash|
118
+ # Load only test files that were not measured. For example,
119
+ # track test files assigned to CI node but never executed by test runner (e.g., pending RSpec spec files).
120
+ next if @test_files_with_time.key?(test_file_path)
121
+
122
+ @test_files_with_time[test_file_path] = {
123
+ time_execution: hash.fetch('time_execution'),
124
+ measured_time: hash.fetch('measured_time'),
125
+ }
126
+ end
127
+
128
+ @prerun_tests_loaded = true
76
129
  end
77
130
 
78
131
  def update_global_time(execution_time)
@@ -1,3 +1,3 @@
1
1
  module KnapsackPro
2
- VERSION = '2.17.0'
2
+ VERSION = '3.0.0'
3
3
  end
@@ -12,8 +12,106 @@ describe KnapsackPro::Adapters::RSpecAdapter do
12
12
  it_behaves_like 'adapter'
13
13
  end
14
14
 
15
+ describe '.ensure_no_tag_option_when_rspec_split_by_test_examples_enabled!' do
16
+ let(:cli_args) { double }
17
+
18
+ subject { described_class.ensure_no_tag_option_when_rspec_split_by_test_examples_enabled!(cli_args) }
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 RSpec split by test examples enabled' do
25
+ let(:rspec_split_by_test_examples_enabled) { true }
26
+
27
+ before do
28
+ expect(described_class).to receive(:has_tag_option?).with(cli_args).and_return(has_tag_option)
29
+ end
30
+
31
+ context 'when RSpec tag option is provided' do
32
+ let(:has_tag_option) { true }
33
+
34
+ it do
35
+ expect { subject }.to raise_error(/It is not allowed to use the RSpec tag option together with the RSpec split by test examples feature/)
36
+ end
37
+ end
38
+
39
+ context 'when RSpec tag option is not provided' do
40
+ let(:has_tag_option) { false }
41
+
42
+ it 'does nothing' do
43
+ expect(subject).to be_nil
44
+ end
45
+ end
46
+ end
47
+
48
+ context 'when RSpec split by test examples disabled' do
49
+ let(:rspec_split_by_test_examples_enabled) { false }
50
+
51
+ it 'does nothing' do
52
+ expect(subject).to be_nil
53
+ end
54
+ end
55
+ end
56
+
57
+ describe '.has_tag_option?' do
58
+ subject { described_class.has_tag_option?(cli_args) }
59
+
60
+ context 'when tag option is provided as -t' do
61
+ let(:cli_args) { ['-t', 'mytag'] }
62
+
63
+ it { expect(subject).to be true }
64
+ end
65
+
66
+ context 'when tag option is provided as --tag' do
67
+ let(:cli_args) { ['--tag', 'mytag'] }
68
+
69
+ it { expect(subject).to be true }
70
+ end
71
+
72
+ context 'when tag option is provided without delimiter' do
73
+ let(:cli_args) { ['-tmytag'] }
74
+
75
+ it { expect(subject).to be true }
76
+ end
77
+
78
+ context 'when tag option is not provided' do
79
+ let(:cli_args) { ['--fake', 'value'] }
80
+
81
+ it { expect(subject).to be false }
82
+ end
83
+ end
84
+
85
+ describe '.has_format_option?' do
86
+ subject { described_class.has_format_option?(cli_args) }
87
+
88
+ context 'when format option is provided as -f' do
89
+ let(:cli_args) { ['-f', 'documentation'] }
90
+
91
+ it { expect(subject).to be true }
92
+ end
93
+
94
+ context 'when format option is provided as --format' do
95
+ let(:cli_args) { ['--format', 'documentation'] }
96
+
97
+ it { expect(subject).to be true }
98
+ end
99
+
100
+ context 'when format option is provided without delimiter' do
101
+ let(:cli_args) { ['-fd'] }
102
+
103
+ it { expect(subject).to be true }
104
+ end
105
+
106
+ context 'when format option is not provided' do
107
+ let(:cli_args) { ['--fake', 'value'] }
108
+
109
+ it { expect(subject).to be false }
110
+ end
111
+ end
112
+
15
113
  describe '.test_path' do
16
- let(:current_example_metadata) do
114
+ let(:example_group) do
17
115
  {
18
116
  file_path: '1_shared_example.rb',
19
117
  parent_example_group: {
@@ -24,14 +122,19 @@ describe KnapsackPro::Adapters::RSpecAdapter do
24
122
  }
25
123
  }
26
124
  end
125
+ let(:current_example) do
126
+ OpenStruct.new(metadata: {
127
+ example_group: example_group
128
+ })
129
+ end
27
130
 
28
- subject { described_class.test_path(current_example_metadata) }
131
+ subject { described_class.test_path(current_example) }
29
132
 
30
133
  it { should eql 'a_spec.rb' }
31
134
 
32
135
  context 'with turnip features' do
33
136
  describe 'when the turnip version is less than 2' do
34
- let(:current_example_metadata) do
137
+ let(:example_group) do
35
138
  {
36
139
  file_path: "./spec/features/logging_in.feature",
37
140
  turnip: true,
@@ -47,7 +150,7 @@ describe KnapsackPro::Adapters::RSpecAdapter do
47
150
  end
48
151
 
49
152
  describe 'when turnip is version 2 or greater' do
50
- let(:current_example_metadata) do
153
+ let(:example_group) do
51
154
  {
52
155
  file_path: "gems/turnip-2.0.0/lib/turnip/rspec.rb",
53
156
  turnip: true,
@@ -72,13 +175,7 @@ describe KnapsackPro::Adapters::RSpecAdapter do
72
175
  let(:logger) { instance_double(Logger) }
73
176
  let(:global_time) { 'Global time: 01m 05s' }
74
177
  let(:test_path) { 'spec/a_spec.rb' }
75
- let(:example) { double }
76
- let(:example_group) { double }
77
- let(:current_example) do
78
- OpenStruct.new(metadata: {
79
- example_group: example_group
80
- })
81
- end
178
+ let(:current_example) { double }
82
179
 
83
180
  context 'when rspec split by test examples is disabled' do
84
181
  before do
@@ -91,19 +188,18 @@ describe KnapsackPro::Adapters::RSpecAdapter do
91
188
  allow(KnapsackPro).to receive(:tracker).and_return(tracker)
92
189
  expect(tracker).to receive(:start_timer).ordered
93
190
 
94
- expect(config).to receive(:around).with(:each).and_yield(example)
191
+ expect(config).to receive(:around).with(:each).and_yield(current_example)
95
192
  expect(config).to receive(:append_after).with(:context).and_yield
96
193
  expect(config).to receive(:after).with(:suite).and_yield
97
194
  expect(::RSpec).to receive(:configure).and_yield(config)
98
195
 
99
196
  expect(tracker).to receive(:stop_timer).ordered
100
197
 
101
- expect(::RSpec).to receive(:current_example).twice.and_return(current_example)
102
- expect(described_class).to receive(:test_path).with(example_group).and_return(test_path)
198
+ expect(described_class).to receive(:test_path).with(current_example).and_return(test_path)
103
199
 
104
200
  expect(tracker).to receive(:current_test_path=).with(test_path).ordered
105
201
 
106
- expect(example).to receive(:run)
202
+ expect(current_example).to receive(:run)
107
203
 
108
204
  expect(tracker).to receive(:stop_timer).ordered
109
205
 
@@ -128,26 +224,25 @@ describe KnapsackPro::Adapters::RSpecAdapter do
128
224
  end
129
225
 
130
226
  it 'records time for example.id' do
131
- expect(example).to receive(:id).and_return(test_example_path)
227
+ expect(current_example).to receive(:id).and_return(test_example_path)
132
228
 
133
229
  expect(config).to receive(:prepend_before).with(:context).and_yield
134
230
 
135
231
  allow(KnapsackPro).to receive(:tracker).and_return(tracker)
136
232
  expect(tracker).to receive(:start_timer).ordered
137
233
 
138
- expect(config).to receive(:around).with(:each).and_yield(example)
234
+ expect(config).to receive(:around).with(:each).and_yield(current_example)
139
235
  expect(config).to receive(:append_after).with(:context).and_yield
140
236
  expect(config).to receive(:after).with(:suite).and_yield
141
237
  expect(::RSpec).to receive(:configure).and_yield(config)
142
238
 
143
239
  expect(tracker).to receive(:stop_timer).ordered
144
240
 
145
- expect(::RSpec).to receive(:current_example).twice.and_return(current_example)
146
- expect(described_class).to receive(:test_path).with(example_group).and_return(test_path)
241
+ expect(described_class).to receive(:test_path).with(current_example).and_return(test_path)
147
242
 
148
243
  expect(tracker).to receive(:current_test_path=).with(test_example_path).ordered
149
244
 
150
- expect(example).to receive(:run)
245
+ expect(current_example).to receive(:run)
151
246
 
152
247
  expect(tracker).to receive(:stop_timer).ordered
153
248
 
@@ -170,19 +265,18 @@ describe KnapsackPro::Adapters::RSpecAdapter do
170
265
  allow(KnapsackPro).to receive(:tracker).and_return(tracker)
171
266
  expect(tracker).to receive(:start_timer).ordered
172
267
 
173
- expect(config).to receive(:around).with(:each).and_yield(example)
268
+ expect(config).to receive(:around).with(:each).and_yield(current_example)
174
269
  expect(config).to receive(:append_after).with(:context).and_yield
175
270
  expect(config).to receive(:after).with(:suite).and_yield
176
271
  expect(::RSpec).to receive(:configure).and_yield(config)
177
272
 
178
- expect(::RSpec).to receive(:current_example).twice.and_return(current_example)
179
- expect(described_class).to receive(:test_path).with(example_group).and_return(test_path)
273
+ expect(described_class).to receive(:test_path).with(current_example).and_return(test_path)
180
274
 
181
275
  expect(tracker).to receive(:stop_timer).ordered
182
276
 
183
277
  expect(tracker).to receive(:current_test_path=).with(test_path).ordered
184
278
 
185
- expect(example).to receive(:run)
279
+ expect(current_example).to receive(:run)
186
280
 
187
281
  expect(tracker).to receive(:stop_timer).ordered
188
282
 
@@ -950,4 +950,29 @@ describe KnapsackPro::Config::Env do
950
950
  it { should be_nil }
951
951
  end
952
952
  end
953
+
954
+ describe '.test_runner_adapter' do
955
+ subject { described_class.test_runner_adapter }
956
+
957
+ context 'when ENV exists' do
958
+ let(:test_runner_adapter) { 'RSpecAdapter' }
959
+ before { stub_const('ENV', { 'KNAPSACK_PRO_TEST_RUNNER_ADAPTER' => test_runner_adapter }) }
960
+ it { should eql 'RSpecAdapter' }
961
+ end
962
+
963
+ context "when ENV doesn't exist" do
964
+ it { should be_nil }
965
+ end
966
+ end
967
+
968
+ describe '.set_test_runner_adapter' do
969
+ let(:adapter_class) { KnapsackPro::Adapters::RSpecAdapter }
970
+
971
+ subject { described_class.set_test_runner_adapter(adapter_class) }
972
+
973
+ it 'sets test runner adapter' do
974
+ subject
975
+ expect(described_class.test_runner_adapter).to eql 'RSpecAdapter'
976
+ end
977
+ end
953
978
  end
@@ -18,16 +18,20 @@ describe KnapsackPro::Runners::CucumberRunner do
18
18
  expect(ENV).to receive(:[]=).with('KNAPSACK_PRO_TEST_SUITE_TOKEN', test_suite_token_cucumber)
19
19
  expect(ENV).to receive(:[]=).with('KNAPSACK_PRO_RECORDING_ENABLED', 'true')
20
20
 
21
+ expect(KnapsackPro::Config::Env).to receive(:set_test_runner_adapter).with(KnapsackPro::Adapters::CucumberAdapter)
22
+
21
23
  expect(described_class).to receive(:new)
22
24
  .with(KnapsackPro::Adapters::CucumberAdapter).and_return(runner)
23
25
  end
24
26
 
25
27
  context 'when test files were returned by Knapsack Pro API' do
26
28
  let(:test_dir) { 'fake-test-dir' }
27
- let(:stringify_test_file_paths) { 'features/fake1.scenario features/fake2.scenario' }
29
+ let(:test_file_paths) { ['features/fake1.scenario', 'features/fake2.scenario'] }
30
+ let(:stringify_test_file_paths) { test_file_paths.join(' ') }
28
31
  let(:runner) do
29
32
  instance_double(described_class,
30
33
  test_dir: test_dir,
34
+ test_file_paths: test_file_paths,
31
35
  stringify_test_file_paths: stringify_test_file_paths,
32
36
  test_files_to_execute_exist?: true)
33
37
  end
@@ -36,6 +40,10 @@ describe KnapsackPro::Runners::CucumberRunner do
36
40
  before do
37
41
  expect(KnapsackPro::Adapters::CucumberAdapter).to receive(:verify_bind_method_called)
38
42
 
43
+ tracker = instance_double(KnapsackPro::Tracker)
44
+ expect(KnapsackPro).to receive(:tracker).and_return(tracker)
45
+ expect(tracker).to receive(:set_prerun_tests).with(test_file_paths)
46
+
39
47
  expect(Rake::Task).to receive(:[]).with('knapsack_pro:cucumber_run').at_least(1).and_return(task)
40
48
 
41
49
  t = double
@@ -14,12 +14,17 @@ describe KnapsackPro::Runners::MinitestRunner do
14
14
  end
15
15
 
16
16
  context 'when test files were returned by Knapsack Pro API' do
17
+ let(:test_file_paths) { ['test_fake/a_test.rb', 'test_fake/b_test.rb'] }
18
+
17
19
  before do
18
20
  expect(KnapsackPro::Adapters::MinitestAdapter).to receive(:verify_bind_method_called)
21
+
22
+ tracker = instance_double(KnapsackPro::Tracker)
23
+ expect(KnapsackPro).to receive(:tracker).and_return(tracker)
24
+ expect(tracker).to receive(:set_prerun_tests).with(test_file_paths)
19
25
  end
20
26
 
21
27
  it 'runs tests' do
22
- test_file_paths = ['test_fake/a_test.rb', 'test_fake/b_test.rb']
23
28
  runner = instance_double(described_class,
24
29
  test_dir: 'test',
25
30
  test_file_paths: test_file_paths,
@@ -19,6 +19,8 @@ describe KnapsackPro::Runners::Queue::CucumberRunner do
19
19
  expect(ENV).to receive(:[]=).with('KNAPSACK_PRO_QUEUE_RECORDING_ENABLED', 'true')
20
20
  expect(ENV).to receive(:[]=).with('KNAPSACK_PRO_QUEUE_ID', queue_id)
21
21
 
22
+ expect(KnapsackPro::Config::Env).to receive(:set_test_runner_adapter).with(KnapsackPro::Adapters::CucumberAdapter)
23
+
22
24
  expect(described_class).to receive(:new).with(KnapsackPro::Adapters::CucumberAdapter).and_return(runner)
23
25
  end
24
26
 
@@ -19,6 +19,8 @@ describe KnapsackPro::Runners::Queue::MinitestRunner do
19
19
  expect(ENV).to receive(:[]=).with('KNAPSACK_PRO_QUEUE_RECORDING_ENABLED', 'true')
20
20
  expect(ENV).to receive(:[]=).with('KNAPSACK_PRO_QUEUE_ID', queue_id)
21
21
 
22
+ expect(KnapsackPro::Config::Env).to receive(:set_test_runner_adapter).with(KnapsackPro::Adapters::MinitestAdapter)
23
+
22
24
  expect(described_class).to receive(:new).with(KnapsackPro::Adapters::MinitestAdapter).and_return(runner)
23
25
 
24
26
  expect($LOAD_PATH).to receive(:unshift).with(test_dir)
@@ -26,6 +26,8 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
26
26
  expect(ENV).to receive(:[]=).with('KNAPSACK_PRO_QUEUE_RECORDING_ENABLED', 'true')
27
27
  expect(ENV).to receive(:[]=).with('KNAPSACK_PRO_QUEUE_ID', queue_id)
28
28
 
29
+ expect(KnapsackPro::Config::Env).to receive(:set_test_runner_adapter).with(KnapsackPro::Adapters::RSpecAdapter)
30
+
29
31
  expect(described_class).to receive(:new).with(KnapsackPro::Adapters::RSpecAdapter).and_return(runner)
30
32
  end
31
33
 
@@ -133,31 +135,16 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
133
135
  context 'when RSpec split by test examples feature is enabled' do
134
136
  before do
135
137
  expect(KnapsackPro::Config::Env).to receive(:rspec_split_by_test_examples?).and_return(true)
138
+ expect(KnapsackPro::Adapters::RSpecAdapter).to receive(:ensure_no_tag_option_when_rspec_split_by_test_examples_enabled!).and_call_original
136
139
  end
137
140
 
138
- context 'when tag option is provided as --tag' do
141
+ context 'when tag option is provided' do
139
142
  let(:args) { '--tag example-value' }
140
143
 
141
144
  it do
142
145
  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
146
  end
144
147
  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
148
  end
162
149
  end
163
150
 
@@ -18,23 +18,32 @@ describe KnapsackPro::Runners::RSpecRunner do
18
18
  expect(ENV).to receive(:[]=).with('KNAPSACK_PRO_TEST_SUITE_TOKEN', test_suite_token_rspec)
19
19
  expect(ENV).to receive(:[]=).with('KNAPSACK_PRO_RECORDING_ENABLED', 'true')
20
20
 
21
+ expect(KnapsackPro::Config::Env).to receive(:set_test_runner_adapter).with(KnapsackPro::Adapters::RSpecAdapter)
22
+
21
23
  expect(described_class).to receive(:new)
22
24
  .with(KnapsackPro::Adapters::RSpecAdapter).and_return(runner)
23
25
  end
24
26
 
25
27
  context 'when test files were returned by Knapsack Pro API' do
26
28
  let(:test_dir) { 'fake-test-dir' }
27
- let(:stringify_test_file_paths) { "spec/a_spec.rb spec/b_spec.rb[1:1]" }
29
+ let(:test_file_paths) { ['spec/a_spec.rb', 'spec/b_spec.rb[1:1]'] }
30
+ let(:stringify_test_file_paths) { test_file_paths.join(' ') }
28
31
  let(:runner) do
29
32
  instance_double(described_class,
30
33
  test_dir: test_dir,
34
+ test_file_paths: test_file_paths,
31
35
  stringify_test_file_paths: stringify_test_file_paths,
32
36
  test_files_to_execute_exist?: true)
33
37
  end
34
38
  let(:task) { double }
35
39
 
36
40
  before do
37
- expect(KnapsackPro::Adapters::RSpecAdapter).to receive(:verify_bind_method_called)
41
+ expect(KnapsackPro::Adapters::RSpecAdapter).to receive(:verify_bind_method_called).ordered
42
+ expect(KnapsackPro::Adapters::RSpecAdapter).to receive(:ensure_no_tag_option_when_rspec_split_by_test_examples_enabled!).with(['--profile', '--color']).ordered
43
+
44
+ tracker = instance_double(KnapsackPro::Tracker)
45
+ expect(KnapsackPro).to receive(:tracker).and_return(tracker)
46
+ expect(tracker).to receive(:set_prerun_tests).with(test_file_paths)
38
47
 
39
48
  expect(Rake::Task).to receive(:[]).with('knapsack_pro:rspec_run').at_least(1).and_return(task)
40
49
 
@@ -44,7 +53,7 @@ describe KnapsackPro::Runners::RSpecRunner do
44
53
  expect(t).to receive(:pattern=).with([])
45
54
  end
46
55
 
47
- context 'when task already exists' do
56
+ context 'when rake task already exists' do
48
57
  before do
49
58
  expect(Rake::Task).to receive(:task_defined?).with('knapsack_pro:rspec_run').and_return(true)
50
59
  expect(task).to receive(:clear)
@@ -57,7 +66,7 @@ describe KnapsackPro::Runners::RSpecRunner do
57
66
  end
58
67
  end
59
68
 
60
- context "when task doesn't exist" do
69
+ context "when rake task doesn't exist" do
61
70
  before do
62
71
  expect(Rake::Task).to receive(:task_defined?).with('knapsack_pro:rspec_run').and_return(false)
63
72
  expect(task).not_to receive(:clear)
@@ -11,16 +11,20 @@ describe KnapsackPro::Runners::SpinachRunner do
11
11
  before do
12
12
  stub_const("ENV", { 'KNAPSACK_PRO_TEST_SUITE_TOKEN_SPINACH' => 'spinach-token' })
13
13
 
14
+ expect(KnapsackPro::Config::Env).to receive(:set_test_runner_adapter).with(KnapsackPro::Adapters::SpinachAdapter)
15
+
14
16
  expect(described_class).to receive(:new)
15
17
  .with(KnapsackPro::Adapters::SpinachAdapter).and_return(runner)
16
18
  end
17
19
 
18
20
  context 'when test files were returned by Knapsack Pro API' do
19
- let(:stringify_test_file_paths) { 'features/a.feature features/b.feature' }
21
+ let(:test_file_paths) { ['features/a.feature', 'features/b.feature'] }
22
+ let(:stringify_test_file_paths) { test_file_paths.join(' ') }
20
23
  let(:test_dir) { 'fake-test-dir' }
21
24
  let(:runner) do
22
25
  instance_double(described_class,
23
26
  test_dir: test_dir,
27
+ test_file_paths: test_file_paths,
24
28
  stringify_test_file_paths: stringify_test_file_paths,
25
29
  test_files_to_execute_exist?: true)
26
30
  end
@@ -29,6 +33,10 @@ describe KnapsackPro::Runners::SpinachRunner do
29
33
  before do
30
34
  expect(KnapsackPro::Adapters::SpinachAdapter).to receive(:verify_bind_method_called)
31
35
 
36
+ tracker = instance_double(KnapsackPro::Tracker)
37
+ expect(KnapsackPro).to receive(:tracker).and_return(tracker)
38
+ expect(tracker).to receive(:set_prerun_tests).with(test_file_paths)
39
+
32
40
  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')
33
41
 
34
42
  allow(described_class).to receive(:child_status).and_return(child_status)
@@ -13,10 +13,15 @@ describe KnapsackPro::Runners::TestUnitRunner do
13
13
  end
14
14
 
15
15
  context 'when test files were returned by Knapsack Pro API' do
16
+ let(:test_file_paths) { ['test-unit_fake/a_test.rb', 'test-unit_fake/b_test.rb'] }
17
+
16
18
  it 'runs tests' do
17
19
  expect(KnapsackPro::Adapters::TestUnitAdapter).to receive(:verify_bind_method_called)
18
20
 
19
- test_file_paths = ['test-unit_fake/a_test.rb', 'test-unit_fake/b_test.rb']
21
+ tracker = instance_double(KnapsackPro::Tracker)
22
+ expect(KnapsackPro).to receive(:tracker).and_return(tracker)
23
+ expect(tracker).to receive(:set_prerun_tests).with(test_file_paths)
24
+
20
25
  runner = instance_double(described_class,
21
26
  test_dir: 'test-unit_fake',
22
27
  test_file_paths: test_file_paths,
@@ -1,11 +1,18 @@
1
1
  shared_examples 'default trakcer attributes' do
2
2
  it { expect(tracker.global_time).to eql 0 }
3
3
  it { expect(tracker.test_files_with_time).to eql({}) }
4
+ it { expect(tracker.prerun_tests_loaded).to be false }
4
5
  end
5
6
 
6
7
  describe KnapsackPro::Tracker do
8
+ let(:adapter) { 'RSpecAdapter' }
7
9
  let(:tracker) { described_class.send(:new) }
8
10
 
11
+ before do
12
+ allow(KnapsackPro::Config::Env).to receive(:test_runner_adapter).and_return(adapter)
13
+ allow(KnapsackPro::Config::Env).to receive(:ci_node_index).and_return(0)
14
+ end
15
+
9
16
  it_behaves_like 'default trakcer attributes'
10
17
 
11
18
  describe '#current_test_path' do
@@ -34,6 +41,10 @@ describe KnapsackPro::Tracker do
34
41
  let(:test_paths) { ['a_spec.rb', 'b_spec.rb'] }
35
42
  let(:delta) { 0.02 }
36
43
 
44
+ before do
45
+ tracker.set_prerun_tests(test_paths)
46
+ end
47
+
37
48
  shared_examples '#to_a' do
38
49
  subject { tracker.to_a }
39
50
 
@@ -55,13 +66,14 @@ describe KnapsackPro::Tracker do
55
66
  end
56
67
 
57
68
  it { expect(tracker.global_time).to be_within(delta).of(0.3) }
69
+ it { expect(tracker.prerun_tests_loaded).to be true }
58
70
  it { expect(tracker.test_files_with_time.keys.size).to eql 2 }
59
71
  it { expect(tracker.test_files_with_time['a_spec.rb'][:time_execution]).to be_within(delta).of(0.1) }
60
72
  it { expect(tracker.test_files_with_time['b_spec.rb'][:time_execution]).to be_within(delta).of(0.2) }
61
73
  it_behaves_like '#to_a'
62
74
  end
63
75
 
64
- context "with Timecop - Timecop shouldn't have impact on measured test time" do
76
+ context "with Timecop - Timecop shouldn't have impact on the measured test time" do
65
77
  let(:now) { Time.now }
66
78
 
67
79
  before do
@@ -80,6 +92,7 @@ describe KnapsackPro::Tracker do
80
92
 
81
93
  it { expect(tracker.global_time).to be > 0 }
82
94
  it { expect(tracker.global_time).to be_within(delta).of(0) }
95
+ it { expect(tracker.prerun_tests_loaded).to be true }
83
96
  it { expect(tracker.test_files_with_time.keys.size).to eql 2 }
84
97
  it { expect(tracker.test_files_with_time['a_spec.rb'][:time_execution]).to be_within(delta).of(0) }
85
98
  it { expect(tracker.test_files_with_time['b_spec.rb'][:time_execution]).to be_within(delta).of(0) }
@@ -96,6 +109,7 @@ describe KnapsackPro::Tracker do
96
109
  end
97
110
 
98
111
  it { expect(tracker.global_time).to be > 0 }
112
+ it { expect(tracker.prerun_tests_loaded).to be true }
99
113
  it { expect(tracker.test_files_with_time.keys.size).to eql 2 }
100
114
  it { expect(tracker.test_files_with_time['a_spec.rb'][:time_execution]).to eq 0 }
101
115
  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
@@ -103,15 +117,62 @@ describe KnapsackPro::Tracker do
103
117
  end
104
118
  it_behaves_like '#to_a'
105
119
  end
120
+
121
+ context 'when a new tracker instance is created' do
122
+ let(:non_pending_test_paths) { ['a_spec.rb', 'b_spec.rb'] }
123
+ let(:test_paths) { non_pending_test_paths + ['pending_spec.rb'] }
124
+
125
+ before do
126
+ # measure tests only for non pending tests
127
+ non_pending_test_paths.each_with_index do |test_path, index|
128
+ tracker.current_test_path = test_path
129
+ tracker.start_timer
130
+ sleep index.to_f / 10 + 0.1
131
+ tracker.stop_timer
132
+ end
133
+ end
134
+
135
+ it '2nd tracker instance loads prerun tests from the disk' do
136
+ expect(tracker.prerun_tests_loaded).to be true
137
+ expect(tracker.to_a.size).to eq 3
138
+ expect(tracker.to_a[0][:path]).to eq 'a_spec.rb'
139
+ expect(tracker.to_a[0][:time_execution]).to be >= 0
140
+ expect(tracker.to_a[1][:path]).to eq 'b_spec.rb'
141
+ expect(tracker.to_a[1][:time_execution]).to be >= 0
142
+ expect(tracker.to_a[2][:path]).to eq 'pending_spec.rb'
143
+ expect(tracker.to_a[2][:time_execution]).to eq 0
144
+
145
+ tracker2 = described_class.send(:new)
146
+ expect(tracker2.prerun_tests_loaded).to be false
147
+ expect(tracker2.to_a.size).to eq 3
148
+ expect(tracker2.to_a[0][:path]).to eq 'a_spec.rb'
149
+ expect(tracker2.to_a[0][:time_execution]).to be >= 0
150
+ expect(tracker2.to_a[1][:path]).to eq 'b_spec.rb'
151
+ expect(tracker2.to_a[1][:time_execution]).to be >= 0
152
+ expect(tracker2.to_a[2][:path]).to eq 'pending_spec.rb'
153
+ expect(tracker2.to_a[2][:time_execution]).to eq 0
154
+ expect(tracker2.prerun_tests_loaded).to be true
155
+ end
156
+ end
106
157
  end
107
158
 
108
159
  describe '#reset!' do
160
+ let(:test_file_path) { 'a_spec.rb' }
161
+
109
162
  before do
110
- tracker.current_test_path = 'a_spec.rb'
163
+ tracker.set_prerun_tests([test_file_path])
164
+ end
165
+
166
+ before do
167
+ expect(tracker.prerun_tests_loaded).to be true
168
+
169
+ tracker.current_test_path = test_file_path
111
170
  tracker.start_timer
112
171
  sleep 0.1
113
172
  tracker.stop_timer
173
+
114
174
  expect(tracker.global_time).not_to eql 0
175
+
115
176
  tracker.reset!
116
177
  end
117
178
 
@@ -120,5 +181,9 @@ describe KnapsackPro::Tracker do
120
181
  it "global time since beginning won't be reset" do
121
182
  expect(tracker.global_time_since_beginning).to be >= 0.1
122
183
  end
184
+
185
+ it 'resets prerun_tests_loaded to false' do
186
+ expect(tracker.prerun_tests_loaded).to be false
187
+ end
123
188
  end
124
189
  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.17.0
4
+ version: 3.0.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-05-25 00:00:00.000000000 Z
11
+ date: 2021-08-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -45,9 +45,6 @@ dependencies:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
47
  version: '3.0'
48
- - - ">="
49
- - !ruby/object:Gem::Version
50
- version: 2.10.0
51
48
  type: :development
52
49
  prerelease: false
53
50
  version_requirements: !ruby/object:Gem::Requirement
@@ -55,9 +52,6 @@ dependencies:
55
52
  - - "~>"
56
53
  - !ruby/object:Gem::Version
57
54
  version: '3.0'
58
- - - ">="
59
- - !ruby/object:Gem::Version
60
- version: 2.10.0
61
55
  - !ruby/object:Gem::Dependency
62
56
  name: rspec-its
63
57
  requirement: !ruby/object:Gem::Requirement
@@ -409,7 +403,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
409
403
  - !ruby/object:Gem::Version
410
404
  version: '0'
411
405
  requirements: []
412
- rubygems_version: 3.2.15
406
+ rubygems_version: 3.2.22
413
407
  signing_key:
414
408
  specification_version: 4
415
409
  summary: Knapsack Pro splits tests across parallel CI nodes and ensures each parallel