knapsack_pro 2.13.0 → 2.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1e1ee6f214c79d86f5ae94658f147e5f3060a77460e1e26109752e57fdd92bed
4
- data.tar.gz: 3bde2c1578bd8e3d3e3ae39880eac80b598464cb57d8c6698440088ab7c552e0
3
+ metadata.gz: b2e5ae3f380ffe2e210417898e30fc7091abcc4fbcacab97b340e9e5ea5e700b
4
+ data.tar.gz: 481dda7a93c2ba5964fa3c20cf60bf2666432311c9a7f1bf59b3be1c905939bb
5
5
  SHA512:
6
- metadata.gz: 197ea0eeff47c4ed54d3baee9f94b9f00cf2c24b61ecb9ae1aaab4c9c8bca3bb247affb26db99e5fcfc3a172be83fefb765e0d4763f48eab4e243b84e262dddf
7
- data.tar.gz: 681cfbb090e0152190fcf54266ef3b9eb70bca40c17494a7f0679846241a3612a8b9b2e2fa37e624deec7e474352cd0b39ac206add49fc48c31185f4cfe4cd30
6
+ metadata.gz: 185add13dfe335fb6b83c1d4a0121f7e097535459c10356401176e1acea5722764554e8f44a2db2ccf806e9a3f4f0a77ca3f701b5b1bc65881d1771722992e67
7
+ data.tar.gz: a267ddf7469e2affd5e472661dbd2a4fdd17c7f58543dc2c40e305d905004ff7d85808f3e7705892cb4da7ea2dd6fac447ca4a30fc15f296abfafb4668f0f001
data/.circleci/config.yml CHANGED
@@ -8,7 +8,7 @@ jobs:
8
8
  parallelism: 1
9
9
  docker:
10
10
  # specify the version you desire here
11
- - image: circleci/ruby:2.7.0
11
+ - image: circleci/ruby:3.0.1
12
12
  environment:
13
13
  CODECLIMATE_REPO_TOKEN: b6626e682a8e97e0c5978febc92c3526792a2d018b41b8e1b52689da37fb7d92
14
14
 
data/CHANGELOG.md CHANGED
@@ -1,5 +1,45 @@
1
1
  # Change Log
2
2
 
3
+ ### 2.18.0
4
+
5
+ * 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
6
+
7
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/148
8
+
9
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v2.17.0...v2.18.0
10
+
11
+ ### 2.17.0
12
+
13
+ * Use Ruby 3 in development and add small improvements
14
+
15
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/147
16
+
17
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v2.16.0...v2.17.0
18
+
19
+ ### 2.16.0
20
+
21
+ * Improve test time execution tracking for RSpec
22
+
23
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/145
24
+
25
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v2.15.0...v2.16.0
26
+
27
+ ### 2.15.0
28
+
29
+ * Do not allow to use the RSpec tag option together with the RSpec split by test examples feature
30
+
31
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/139
32
+
33
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v2.14.0...v2.15.0
34
+
35
+ ### 2.14.0
36
+
37
+ * Track time spend in RSpec context hook
38
+
39
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/143
40
+
41
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v2.13.0...v2.14.0
42
+
3
43
  ### 2.13.0
4
44
 
5
45
  * Update FAQ links in `knapsack_pro` warnings and remove FAQ from readme
data/README.md CHANGED
@@ -793,43 +793,7 @@ $ KNAPSACK_PRO_SALT=xxx bundle exec rake knapsack_pro:encrypted_branch_names[not
793
793
 
794
794
  If you are using circleci.com you can omit `KNAPSACK_PRO_CI_NODE_TOTAL` and `KNAPSACK_PRO_CI_NODE_INDEX`. Knapsack Pro will use `CIRCLE_NODE_TOTAL` and `CIRCLE_NODE_INDEX` provided by CircleCI.
795
795
 
796
- Here is an example for test configuration in your `circleci.yml` file.
797
-
798
- ```yaml
799
- # CircleCI 1.0
800
-
801
- machine:
802
- environment:
803
- # Tokens should be set in CircleCI settings to avoid expose tokens in build logs
804
- # KNAPSACK_PRO_TEST_SUITE_TOKEN_RSPEC: rspec-token
805
- # KNAPSACK_PRO_TEST_SUITE_TOKEN_CUCUMBER: cucumber-token
806
- # KNAPSACK_PRO_TEST_SUITE_TOKEN_MINITEST: minitest-token
807
- # KNAPSACK_PRO_TEST_SUITE_TOKEN_TEST_UNIT: test-unit-token
808
- # KNAPSACK_PRO_TEST_SUITE_TOKEN_SPINACH: spinach-token
809
- test:
810
- override:
811
- # Step for RSpec
812
- - bundle exec rake knapsack_pro:rspec:
813
- parallel: true # Caution: there are 8 spaces indentation!
814
-
815
- # Step for Cucumber
816
- - bundle exec rake knapsack_pro:cucumber:
817
- parallel: true # Caution: there are 8 spaces indentation!
818
-
819
- # Step for Minitest
820
- - bundle exec rake knapsack_pro:minitest:
821
- parallel: true # Caution: there are 8 spaces indentation!
822
-
823
- # Step for test-unit
824
- - bundle exec rake knapsack_pro:test_unit:
825
- parallel: true # Caution: there are 8 spaces indentation!
826
-
827
- # Step for Spinach
828
- - bundle exec rake knapsack_pro:spinach:
829
- parallel: true # Caution: there are 8 spaces indentation!
830
- ```
831
-
832
- Here is another example for CircleCI 2.0 platform.
796
+ Here is an example for test configuration in your `.circleci/config.yml` file.
833
797
 
834
798
  ```yaml
835
799
  # CircleCI 2.0
@@ -866,7 +830,7 @@ Please remember to add additional containers for your project in CircleCI settin
866
830
 
867
831
  ##### CircleCI and knapsack_pro Queue Mode
868
832
 
869
- If you use knapsack_pro Queue Mode with CircleCI you may want to [collect metadata](https://circleci.com/docs/1.0/test-metadata/#metadata-collection-in-custom-test-steps) like junit xml report about your RSpec test suite.
833
+ If you use knapsack_pro Queue Mode with CircleCI you may want to [collect metadata](https://circleci.com/docs/2.0/collect-test-data/#metadata-collection-in-custom-test-steps) like junit xml report about your RSpec test suite.
870
834
 
871
835
  Here you can read how to configure [junit formatter](https://knapsackpro.com/faq/question/how-to-use-junit-formatter#how-to-use-junit-formatter-with-knapsack_pro-queue-mode). Step for CircleCI is to copy the xml report to `$CIRCLE_TEST_REPORTS` directory. Below is full config for your `spec_helper.rb`:
872
836
 
@@ -874,7 +838,7 @@ Here you can read how to configure [junit formatter](https://knapsackpro.com/faq
874
838
  # spec_helper.rb or rails_helper.rb
875
839
 
876
840
  # TODO This must be the same path as value for rspec --out argument
877
- # 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.
878
842
  TMP_RSPEC_XML_REPORT = 'tmp/rspec.xml'
879
843
  # move results to FINAL_RSPEC_XML_REPORT so the results won't accumulate with duplicated xml tags in TMP_RSPEC_XML_REPORT
880
844
  FINAL_RSPEC_XML_REPORT = 'tmp/rspec_final_results.xml'
@@ -913,6 +877,8 @@ Ensure you have in CircleCI config yml
913
877
  destination: test-results
914
878
  ```
915
879
 
880
+ You can find a complete CircleCI YML config example in [the article](https://docs.knapsackpro.com/2021/rspec-testing-parallel-jobs-with-circleci-and-junit-xml-report).
881
+
916
882
  #### Info for Travis users
917
883
 
918
884
  You can parallelize your builds across virtual machines with [travis matrix feature](http://docs.travis-ci.com/user/speeding-up-the-build/#parallelizing-your-builds-across-virtual-machines). Edit `.travis.yml`
data/knapsack_pro.gemspec CHANGED
@@ -29,14 +29,13 @@ Gem::Specification.new do |spec|
29
29
 
30
30
  spec.add_development_dependency 'bundler', '>= 1.6'
31
31
  spec.add_development_dependency 'rspec', '~> 3.0', '>= 2.10.0'
32
- spec.add_development_dependency 'rspec-its', '~> 1.2'
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'
35
35
  spec.add_development_dependency 'minitest', '>= 5.0.0'
36
36
  spec.add_development_dependency 'test-unit', '>= 3.0.0'
37
- spec.add_development_dependency 'codeclimate-test-reporter', '~> 0'
38
37
  spec.add_development_dependency 'pry', '~> 0'
39
- spec.add_development_dependency 'vcr', '~> 2.9'
40
- spec.add_development_dependency 'webmock', '~> 1.21'
41
- spec.add_development_dependency 'timecop', '>= 0.1.0'
38
+ spec.add_development_dependency 'vcr', '>= 6.0'
39
+ spec.add_development_dependency 'webmock', '>= 3.13'
40
+ spec.add_development_dependency 'timecop', '>= 0.9.4'
42
41
  end
@@ -3,6 +3,27 @@ module KnapsackPro
3
3
  class RSpecAdapter < BaseAdapter
4
4
  TEST_DIR_PATTERN = 'spec/**{,/*/**}/*_spec.rb'
5
5
 
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
+
6
27
  def self.test_path(example_group)
7
28
  if defined?(::Turnip) && ::Turnip::VERSION.to_i < 2
8
29
  unless example_group[:turnip]
@@ -21,7 +42,15 @@ module KnapsackPro
21
42
 
22
43
  def bind_time_tracker
23
44
  ::RSpec.configure do |config|
45
+ config.prepend_before(:context) do
46
+ KnapsackPro.tracker.start_timer
47
+ end
48
+
24
49
  config.around(:each) do |example|
50
+ # stop timer to update time for a previously run test example
51
+ # this way we count time spend in runtime for the previous test example after around(:each) is already done
52
+ KnapsackPro.tracker.stop_timer
53
+
25
54
  current_example_group =
26
55
  if ::RSpec.respond_to?(:current_example)
27
56
  ::RSpec.current_example.metadata[:example_group]
@@ -38,10 +67,12 @@ module KnapsackPro
38
67
  current_test_path
39
68
  end
40
69
 
41
- KnapsackPro.tracker.start_timer
42
-
43
70
  example.run
71
+ end
44
72
 
73
+ config.append_after(:context) do
74
+ # after(:context) hook is run one time only, after all of the examples in a group
75
+ # stop timer to count time for the very last executed test example
45
76
  KnapsackPro.tracker.stop_timer
46
77
  end
47
78
 
@@ -23,8 +23,7 @@ module KnapsackPro
23
23
  end
24
24
 
25
25
  def project_dir
26
- project_repo_name = ENV['CIRCLE_PROJECT_REPONAME']
27
- "/home/ubuntu/#{project_repo_name}" if project_repo_name
26
+ ENV['CIRCLE_WORKING_DIRECTORY']
28
27
  end
29
28
  end
30
29
  end
@@ -17,7 +17,8 @@ module KnapsackPro
17
17
  private
18
18
 
19
19
  def working_dir
20
- KnapsackPro::Config::Env.project_dir
20
+ dir = KnapsackPro::Config::Env.project_dir
21
+ File.expand_path(dir)
21
22
  end
22
23
  end
23
24
  end
@@ -35,6 +35,10 @@ module KnapsackPro
35
35
 
36
36
  attr_reader :allocator_builder,
37
37
  :allocator
38
+
39
+ def self.child_status
40
+ $?
41
+ end
38
42
  end
39
43
  end
40
44
  end
@@ -29,6 +29,10 @@ module KnapsackPro
29
29
 
30
30
  attr_reader :allocator_builder,
31
31
  :allocator
32
+
33
+ def self.child_status
34
+ $?
35
+ end
32
36
  end
33
37
  end
34
38
  end
@@ -95,16 +95,14 @@ module KnapsackPro
95
95
  # which is defined in lib/knapsack_pro/adapters/cucumber_adapter.rb
96
96
  ENV['KNAPSACK_PRO_BEFORE_QUEUE_HOOK_CALLED'] = 'true'
97
97
 
98
- process_status = $?
99
-
100
- unless process_status.exited?
98
+ unless child_status.exited?
101
99
  raise "Cucumber process execution failed. It's likely that your CI server has exceeded"\
102
100
  " its available memory. Please try changing CI config or retrying the CI build.\n"\
103
101
  "Failed command: #{cmd}\n"\
104
- "Process status: #{process_status.inspect}"
102
+ "Process status: #{child_status.inspect}"
105
103
  end
106
104
 
107
- process_status.exitstatus
105
+ child_status.exitstatus
108
106
  end
109
107
  end
110
108
  end
@@ -11,15 +11,17 @@ 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
+ runner = new(adapter_class)
15
16
 
16
17
  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']
21
- end
18
+ adapter_class.ensure_no_tag_option_when_rspec_split_by_test_examples_enabled!(cli_args)
19
+
20
+ # when format option is not defined by user then use progress formatter to show tests execution progress
21
+ cli_args += ['--format', 'progress'] unless adapter_class.has_format_option?(cli_args)
22
+
22
23
  cli_args += [
24
+ # shows summary of all tests executed in Queue Mode at the very end
23
25
  '--format', KnapsackPro::Formatters::RSpecQueueSummaryFormatter.to_s,
24
26
  '--default-path', runner.test_dir,
25
27
  ]
@@ -11,6 +11,9 @@ module KnapsackPro
11
11
  if runner.test_files_to_execute_exist?
12
12
  adapter_class.verify_bind_method_called
13
13
 
14
+ cli_args = (args || '').split
15
+ adapter_class.ensure_no_tag_option_when_rspec_split_by_test_examples_enabled!(cli_args)
16
+
14
17
  require 'rspec/core/rake_task'
15
18
 
16
19
  task_name = 'knapsack_pro:rspec_run'
@@ -13,7 +13,7 @@ module KnapsackPro
13
13
  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
14
 
15
15
  Kernel.system(cmd)
16
- Kernel.exit($?.exitstatus) unless $?.exitstatus.zero?
16
+ Kernel.exit(child_status.exitstatus) unless child_status.exitstatus.zero?
17
17
  end
18
18
  end
19
19
  end
@@ -11,21 +11,32 @@ module KnapsackPro
11
11
  if runner.test_files_to_execute_exist?
12
12
  adapter_class.verify_bind_method_called
13
13
 
14
- require 'test/unit'
15
-
16
14
  cli_args =
17
15
  (args || '').split +
18
16
  runner.test_file_paths.map do |f|
19
17
  File.expand_path(f)
20
18
  end
21
19
 
22
- exit ::Test::Unit::AutoRunner.run(
20
+ exit test_unit_autorunner_run(
23
21
  true,
24
22
  runner.test_dir,
25
23
  cli_args
26
24
  )
27
25
  end
28
26
  end
27
+
28
+ private
29
+
30
+ # https://www.rubydoc.info/github/test-unit/test-unit/Test/Unit/AutoRunner#run-class_method
31
+ def self.test_unit_autorunner_run(force_standalone, default_dir, argv)
32
+ require 'test/unit'
33
+
34
+ ::Test::Unit::AutoRunner.run(
35
+ force_standalone,
36
+ default_dir,
37
+ argv
38
+ )
39
+ end
29
40
  end
30
41
  end
31
42
  end
@@ -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.13.0'
2
+ VERSION = '2.18.0'
3
3
  end
@@ -12,6 +12,104 @@ 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
114
  let(:current_example_metadata) do
17
115
  {
@@ -86,20 +184,26 @@ describe KnapsackPro::Adapters::RSpecAdapter do
86
184
  end
87
185
 
88
186
  it 'records time for current test path' do
187
+ expect(config).to receive(:prepend_before).with(:context).and_yield
188
+
189
+ allow(KnapsackPro).to receive(:tracker).and_return(tracker)
190
+ expect(tracker).to receive(:start_timer).ordered
191
+
89
192
  expect(config).to receive(:around).with(:each).and_yield(example)
193
+ expect(config).to receive(:append_after).with(:context).and_yield
90
194
  expect(config).to receive(:after).with(:suite).and_yield
91
195
  expect(::RSpec).to receive(:configure).and_yield(config)
92
196
 
197
+ expect(tracker).to receive(:stop_timer).ordered
198
+
93
199
  expect(::RSpec).to receive(:current_example).twice.and_return(current_example)
94
200
  expect(described_class).to receive(:test_path).with(example_group).and_return(test_path)
95
201
 
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)
202
+ expect(tracker).to receive(:current_test_path=).with(test_path).ordered
99
203
 
100
204
  expect(example).to receive(:run)
101
205
 
102
- expect(tracker).to receive(:stop_timer)
206
+ expect(tracker).to receive(:stop_timer).ordered
103
207
 
104
208
  expect(KnapsackPro::Presenter).to receive(:global_time).and_return(global_time)
105
209
  expect(KnapsackPro).to receive(:logger).and_return(logger)
@@ -124,20 +228,26 @@ describe KnapsackPro::Adapters::RSpecAdapter do
124
228
  it 'records time for example.id' do
125
229
  expect(example).to receive(:id).and_return(test_example_path)
126
230
 
231
+ expect(config).to receive(:prepend_before).with(:context).and_yield
232
+
233
+ allow(KnapsackPro).to receive(:tracker).and_return(tracker)
234
+ expect(tracker).to receive(:start_timer).ordered
235
+
127
236
  expect(config).to receive(:around).with(:each).and_yield(example)
237
+ expect(config).to receive(:append_after).with(:context).and_yield
128
238
  expect(config).to receive(:after).with(:suite).and_yield
129
239
  expect(::RSpec).to receive(:configure).and_yield(config)
130
240
 
241
+ expect(tracker).to receive(:stop_timer).ordered
242
+
131
243
  expect(::RSpec).to receive(:current_example).twice.and_return(current_example)
132
244
  expect(described_class).to receive(:test_path).with(example_group).and_return(test_path)
133
245
 
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)
246
+ expect(tracker).to receive(:current_test_path=).with(test_example_path).ordered
137
247
 
138
248
  expect(example).to receive(:run)
139
249
 
140
- expect(tracker).to receive(:stop_timer)
250
+ expect(tracker).to receive(:stop_timer).ordered
141
251
 
142
252
  expect(KnapsackPro::Presenter).to receive(:global_time).and_return(global_time)
143
253
  expect(KnapsackPro).to receive(:logger).and_return(logger)
@@ -153,20 +263,26 @@ describe KnapsackPro::Adapters::RSpecAdapter do
153
263
  end
154
264
 
155
265
  it 'records time for current test path' do
266
+ expect(config).to receive(:prepend_before).with(:context).and_yield
267
+
268
+ allow(KnapsackPro).to receive(:tracker).and_return(tracker)
269
+ expect(tracker).to receive(:start_timer).ordered
270
+
156
271
  expect(config).to receive(:around).with(:each).and_yield(example)
272
+ expect(config).to receive(:append_after).with(:context).and_yield
157
273
  expect(config).to receive(:after).with(:suite).and_yield
158
274
  expect(::RSpec).to receive(:configure).and_yield(config)
159
275
 
160
276
  expect(::RSpec).to receive(:current_example).twice.and_return(current_example)
161
277
  expect(described_class).to receive(:test_path).with(example_group).and_return(test_path)
162
278
 
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)
279
+ expect(tracker).to receive(:stop_timer).ordered
280
+
281
+ expect(tracker).to receive(:current_test_path=).with(test_path).ordered
166
282
 
167
283
  expect(example).to receive(:run)
168
284
 
169
- expect(tracker).to receive(:stop_timer)
285
+ expect(tracker).to receive(:stop_timer).ordered
170
286
 
171
287
  expect(KnapsackPro::Presenter).to receive(:global_time).and_return(global_time)
172
288
  expect(KnapsackPro).to receive(:logger).and_return(logger)
@@ -1,4 +1,11 @@
1
- require 'test/unit/testcase'
1
+ # fake class to make tests pass and to avoid require 'test/unit/testcase' to not break RSpec
2
+ # https://www.rubydoc.info/gems/test-unit/3.4.1/Test/Unit/TestSuite
3
+ module Test
4
+ module Unit
5
+ class TestSuite
6
+ end
7
+ end
8
+ end
2
9
 
3
10
  describe KnapsackPro::Adapters::TestUnitAdapter do
4
11
  it do
@@ -75,9 +75,9 @@ describe KnapsackPro::Config::CI::Circle do
75
75
  describe '#project_dir' do
76
76
  subject { described_class.new.project_dir }
77
77
 
78
- context 'when environment exists' do
79
- let(:env) { { 'CIRCLE_PROJECT_REPONAME' => 'knapsack_pro-ruby' } }
80
- it { should eql '/home/ubuntu/knapsack_pro-ruby' }
78
+ context 'when CIRCLE_WORKING_DIRECTORY environment variable exists' do
79
+ let(:env) { { 'CIRCLE_WORKING_DIRECTORY' => '~/knapsack_pro-ruby' } }
80
+ it { should eql '~/knapsack_pro-ruby' }
81
81
  end
82
82
 
83
83
  context "when environment doesn't exist" do
@@ -15,20 +15,20 @@ describe KnapsackPro::RepositoryAdapters::GitAdapter do
15
15
 
16
16
  it { should_not be_nil }
17
17
  its(:size) { should eq 40 }
18
- it { should eq circle_sha1 } if ENV['CIRCLE_SHA1']
18
+ it { should eq circle_sha1 } if ENV['CIRCLECI']
19
19
  end
20
20
 
21
21
  describe '#branch' do
22
22
  subject { described_class.new.branch }
23
23
 
24
24
  it { should_not be_nil }
25
- it { should eq circle_branch } if ENV['CIRCLE_BRANCH']
25
+ it { should eq circle_branch } if ENV['CIRCLECI']
26
26
  end
27
27
 
28
28
  describe '#branches' do
29
29
  subject { described_class.new.branches }
30
30
 
31
31
  it { expect(subject.include?('master')).to be true }
32
- it { expect(subject.include?(circle_branch)).to be true } if ENV['CIRCLE_BRANCH']
32
+ it { expect(subject.include?(circle_branch)).to be true } if ENV['CIRCLECI']
33
33
  end
34
34
  end
@@ -100,6 +100,7 @@ describe KnapsackPro::Runners::Queue::CucumberRunner do
100
100
 
101
101
  context 'when test files exist' do
102
102
  let(:test_file_paths) { ['features/a.feature', 'features/b.feature'] }
103
+ let(:child_status) { double }
103
104
 
104
105
  before do
105
106
  subset_queue_id = 'fake-subset-queue-id'
@@ -117,8 +118,9 @@ describe KnapsackPro::Runners::Queue::CucumberRunner do
117
118
 
118
119
  expect(ENV).to receive(:[]=).with('KNAPSACK_PRO_BEFORE_QUEUE_HOOK_CALLED', 'true')
119
120
 
120
- expect($?).to receive(:exited?).and_return(process_exited)
121
- allow($?).to receive(:exitstatus).and_return(exitstatus)
121
+ allow(described_class).to receive(:child_status).and_return(child_status)
122
+ expect(child_status).to receive(:exited?).and_return(process_exited)
123
+ allow(child_status).to receive(:exitstatus).and_return(exitstatus)
122
124
  end
123
125
 
124
126
  context 'when system process finished its work (exited)' do
@@ -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,21 @@ 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
+ expect(KnapsackPro::Adapters::RSpecAdapter).to receive(:ensure_no_tag_option_when_rspec_split_by_test_examples_enabled!).and_call_original
137
+ end
138
+
139
+ context 'when tag option is provided' do
140
+ let(:args) { '--tag example-value' }
141
+
142
+ it do
143
+ expect { subject }.to raise_error(/It is not allowed to use the RSpec tag option together with the RSpec split by test examples feature/)
144
+ end
145
+ end
146
+ end
132
147
  end
133
148
 
134
149
  context 'when args not provided' do
@@ -34,7 +34,8 @@ describe KnapsackPro::Runners::RSpecRunner do
34
34
  let(:task) { double }
35
35
 
36
36
  before do
37
- expect(KnapsackPro::Adapters::RSpecAdapter).to receive(:verify_bind_method_called)
37
+ expect(KnapsackPro::Adapters::RSpecAdapter).to receive(:verify_bind_method_called).ordered
38
+ expect(KnapsackPro::Adapters::RSpecAdapter).to receive(:ensure_no_tag_option_when_rspec_split_by_test_examples_enabled!).with(['--profile', '--color']).ordered
38
39
 
39
40
  expect(Rake::Task).to receive(:[]).with('knapsack_pro:rspec_run').at_least(1).and_return(task)
40
41
 
@@ -44,7 +45,7 @@ describe KnapsackPro::Runners::RSpecRunner do
44
45
  expect(t).to receive(:pattern=).with([])
45
46
  end
46
47
 
47
- context 'when task already exists' do
48
+ context 'when rake task already exists' do
48
49
  before do
49
50
  expect(Rake::Task).to receive(:task_defined?).with('knapsack_pro:rspec_run').and_return(true)
50
51
  expect(task).to receive(:clear)
@@ -57,7 +58,7 @@ describe KnapsackPro::Runners::RSpecRunner do
57
58
  end
58
59
  end
59
60
 
60
- context "when task doesn't exist" do
61
+ context "when rake task doesn't exist" do
61
62
  before do
62
63
  expect(Rake::Task).to receive(:task_defined?).with('knapsack_pro:rspec_run').and_return(false)
63
64
  expect(task).not_to receive(:clear)
@@ -24,11 +24,14 @@ describe KnapsackPro::Runners::SpinachRunner do
24
24
  stringify_test_file_paths: stringify_test_file_paths,
25
25
  test_files_to_execute_exist?: true)
26
26
  end
27
+ let(:child_status) { double }
27
28
 
28
29
  before do
29
30
  expect(KnapsackPro::Adapters::SpinachAdapter).to receive(:verify_bind_method_called)
30
31
 
31
32
  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
+
34
+ allow(described_class).to receive(:child_status).and_return(child_status)
32
35
  end
33
36
 
34
37
  after { subject }
@@ -37,7 +40,7 @@ describe KnapsackPro::Runners::SpinachRunner do
37
40
  let(:exitstatus) { 0 }
38
41
 
39
42
  before do
40
- expect($?).to receive(:exitstatus).and_return(exitstatus)
43
+ expect(child_status).to receive(:exitstatus).and_return(exitstatus)
41
44
  end
42
45
 
43
46
  it do
@@ -49,7 +52,7 @@ describe KnapsackPro::Runners::SpinachRunner do
49
52
  let(:exitstatus) { 1 }
50
53
 
51
54
  before do
52
- expect($?).to receive(:exitstatus).twice.and_return(exitstatus)
55
+ expect(child_status).to receive(:exitstatus).twice.and_return(exitstatus)
53
56
  end
54
57
 
55
58
  it do
@@ -1,5 +1,3 @@
1
- require 'test/unit'
2
-
3
1
  describe KnapsackPro::Runners::TestUnitRunner do
4
2
  subject { described_class.new(KnapsackPro::Adapters::TestUnitAdapter) }
5
3
 
@@ -27,7 +25,7 @@ describe KnapsackPro::Runners::TestUnitRunner do
27
25
  .with(KnapsackPro::Adapters::TestUnitAdapter).and_return(runner)
28
26
 
29
27
  auto_runner_exit_code = 0
30
- expect(Test::Unit::AutoRunner).to receive(:run) do |flag, test_dir, cli_args|
28
+ expect(described_class).to receive(:test_unit_autorunner_run) do |flag, test_dir, cli_args|
31
29
  expect(flag).to be true
32
30
  expect(test_dir).to eq 'test-unit_fake'
33
31
  expect(cli_args.size).to eq 4
@@ -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
data/spec/spec_helper.rb CHANGED
@@ -4,9 +4,6 @@ require 'spinach'
4
4
  require 'timecop'
5
5
  Timecop.safe_mode = true
6
6
 
7
- require 'codeclimate-test-reporter'
8
- CodeClimate::TestReporter.start
9
-
10
7
  require 'vcr'
11
8
  require 'webmock/rspec'
12
9
  VCR.configure do |config|
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.13.0
4
+ version: 2.18.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-04-13 00:00:00.000000000 Z
11
+ date: 2021-07-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -42,36 +42,36 @@ dependencies:
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: 2.10.0
48
45
  - - "~>"
49
46
  - !ruby/object:Gem::Version
50
47
  version: '3.0'
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: 2.10.0
51
51
  type: :development
52
52
  prerelease: false
53
53
  version_requirements: !ruby/object:Gem::Requirement
54
54
  requirements:
55
- - - ">="
56
- - !ruby/object:Gem::Version
57
- version: 2.10.0
58
55
  - - "~>"
59
56
  - !ruby/object:Gem::Version
60
57
  version: '3.0'
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: 2.10.0
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: rspec-its
63
63
  requirement: !ruby/object:Gem::Requirement
64
64
  requirements:
65
65
  - - "~>"
66
66
  - !ruby/object:Gem::Version
67
- version: '1.2'
67
+ version: '1.3'
68
68
  type: :development
69
69
  prerelease: false
70
70
  version_requirements: !ruby/object:Gem::Requirement
71
71
  requirements:
72
72
  - - "~>"
73
73
  - !ruby/object:Gem::Version
74
- version: '1.2'
74
+ version: '1.3'
75
75
  - !ruby/object:Gem::Dependency
76
76
  name: cucumber
77
77
  requirement: !ruby/object:Gem::Requirement
@@ -128,20 +128,6 @@ dependencies:
128
128
  - - ">="
129
129
  - !ruby/object:Gem::Version
130
130
  version: 3.0.0
131
- - !ruby/object:Gem::Dependency
132
- name: codeclimate-test-reporter
133
- requirement: !ruby/object:Gem::Requirement
134
- requirements:
135
- - - "~>"
136
- - !ruby/object:Gem::Version
137
- version: '0'
138
- type: :development
139
- prerelease: false
140
- version_requirements: !ruby/object:Gem::Requirement
141
- requirements:
142
- - - "~>"
143
- - !ruby/object:Gem::Version
144
- version: '0'
145
131
  - !ruby/object:Gem::Dependency
146
132
  name: pry
147
133
  requirement: !ruby/object:Gem::Requirement
@@ -160,44 +146,44 @@ dependencies:
160
146
  name: vcr
161
147
  requirement: !ruby/object:Gem::Requirement
162
148
  requirements:
163
- - - "~>"
149
+ - - ">="
164
150
  - !ruby/object:Gem::Version
165
- version: '2.9'
151
+ version: '6.0'
166
152
  type: :development
167
153
  prerelease: false
168
154
  version_requirements: !ruby/object:Gem::Requirement
169
155
  requirements:
170
- - - "~>"
156
+ - - ">="
171
157
  - !ruby/object:Gem::Version
172
- version: '2.9'
158
+ version: '6.0'
173
159
  - !ruby/object:Gem::Dependency
174
160
  name: webmock
175
161
  requirement: !ruby/object:Gem::Requirement
176
162
  requirements:
177
- - - "~>"
163
+ - - ">="
178
164
  - !ruby/object:Gem::Version
179
- version: '1.21'
165
+ version: '3.13'
180
166
  type: :development
181
167
  prerelease: false
182
168
  version_requirements: !ruby/object:Gem::Requirement
183
169
  requirements:
184
- - - "~>"
170
+ - - ">="
185
171
  - !ruby/object:Gem::Version
186
- version: '1.21'
172
+ version: '3.13'
187
173
  - !ruby/object:Gem::Dependency
188
174
  name: timecop
189
175
  requirement: !ruby/object:Gem::Requirement
190
176
  requirements:
191
177
  - - ">="
192
178
  - !ruby/object:Gem::Version
193
- version: 0.1.0
179
+ version: 0.9.4
194
180
  type: :development
195
181
  prerelease: false
196
182
  version_requirements: !ruby/object:Gem::Requirement
197
183
  requirements:
198
184
  - - ">="
199
185
  - !ruby/object:Gem::Version
200
- version: 0.1.0
186
+ version: 0.9.4
201
187
  description: Run tests in parallel across CI server nodes based on tests execution
202
188
  time. Split tests in a dynamic way to ensure parallel jobs are done at a similar
203
189
  time. Thanks to that your CI build time is as fast as possible. It works with many
@@ -423,7 +409,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
423
409
  - !ruby/object:Gem::Version
424
410
  version: '0'
425
411
  requirements: []
426
- rubygems_version: 3.0.6
412
+ rubygems_version: 3.2.15
427
413
  signing_key:
428
414
  specification_version: 4
429
415
  summary: Knapsack Pro splits tests across parallel CI nodes and ensures each parallel