knapsack 1.21.0 → 3.1.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: 620ac5f634996f21d32b1c65ac8609a61c47ac6f07b773fe1fa2bf6487f41d88
4
- data.tar.gz: e5851433f161642429b11bea40e28ad37a0bd5f7008f34b641750afc7168e8e5
3
+ metadata.gz: d27f3b6225aefe7c7a2ff1a4071961e65c5e087a5256d7294bca73398ce2c997
4
+ data.tar.gz: 38f324e2d35800297e8c071caef06100688d1e1617bb8f3339076b9c9c1de828
5
5
  SHA512:
6
- metadata.gz: edf2dbf2877aa04107e8a62e6ea91426df85288a87954d28068d3bb49dc31006bf61094bff3b564eb7d9b302b5966d2656e418bd83cd5a7ab751f9e2d33763b5
7
- data.tar.gz: 14d9e941b65ffad0d5ec9d5120d56a77be8dc30ba4e2bb463a8621fe04947c804e1db41e7b10ae5a9ff87439acda309e1accb0076683e62ab1e25ca86f33718d
6
+ metadata.gz: 0d635a77401b2d65914edab41f2ac726901d38b937869fb408cc2548d6547114a0d968c06a8c9adfe4f5a2c3d3d7c11bea5bb0c8161d706e17870ea3682b5be0
7
+ data.tar.gz: b5aa3601e1d7cbdffdfa33a4de64d562782c74371f9e3c58b0754b262a86554c8320e7fb0aff1c84cd6e05755b66c29b61b87f83ffb3a44d4f06eb9c38c8dfd6
@@ -0,0 +1,117 @@
1
+ name: Ruby
2
+
3
+ on:
4
+ push:
5
+ branches: [master]
6
+ pull_request:
7
+ branches: [master]
8
+
9
+ jobs:
10
+ test:
11
+
12
+ runs-on: ubuntu-latest
13
+ strategy:
14
+ fail-fast: false
15
+ matrix:
16
+ # Due to https://github.com/actions/runner/issues/849, we have to use quotes for '3.0'
17
+ ruby: [2.2, 2.3, 2.4, 2.5, 2.6, 2.7, '3.0', truffleruby-head]
18
+
19
+ steps:
20
+ - uses: actions/checkout@v2
21
+ - name: Set up Ruby
22
+ uses: ruby/setup-ruby@v1
23
+ with:
24
+ ruby-version: ${{ matrix.ruby }}
25
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
26
+
27
+ # Test for knapsack gem
28
+ - name: Run specs for Knapsack gem
29
+ run: bundle exec rspec spec
30
+
31
+ # Tests for example rspec test suite
32
+ - name: Generate knapsack report
33
+ run: KNAPSACK_GENERATE_REPORT=true bundle exec rspec --default-path spec_examples --tag focus
34
+
35
+ - name: Run specs with enabled time offset warning
36
+ run: bundle exec rspec --default-path spec_examples
37
+
38
+ - name: Run rake task for the first CI node
39
+ run: CI_NODE_TOTAL=2 CI_NODE_INDEX=0 KNAPSACK_TEST_FILE_PATTERN="spec_examples/**{,/*/**}/*_spec.rb" bundle exec rake knapsack:rspec
40
+ - name: Run rake task for the second CI node
41
+ run: CI_NODE_TOTAL=2 CI_NODE_INDEX=1 KNAPSACK_TEST_FILE_PATTERN="spec_examples/**{,/*/**}/*_spec.rb" bundle exec rake knapsack:rspec
42
+
43
+ - name: Check passing arguments to rspec. Run only specs with custom_focus tag (1/2)
44
+ run: KNAPSACK_TEST_FILE_PATTERN="spec_examples/**{,/*/**}/*_spec.rb" bundle exec rake "knapsack:rspec[--tag custom_focus]"
45
+ - name: Check passing arguments to rspec. Run only specs with custom_focus tag (2/2)
46
+ run: KNAPSACK_TEST_FILE_PATTERN="spec_examples/**{,/*/**}/*_spec.rb" bin/knapsack rspec "--tag custom_focus --profile"
47
+
48
+ - name: Run specs with custom knapsack logger
49
+ run: CUSTOM_LOGGER=true KNAPSACK_TEST_FILE_PATTERN="spec_examples/**{,/*/**}/*_spec.rb" bundle exec rake knapsack:rspec
50
+
51
+ - name: Run specs for custom knapsack report path
52
+ run: |
53
+ cp knapsack_rspec_report.json knapsack_custom_rspec_report.json
54
+ KNAPSACK_REPORT_PATH="knapsack_custom_rspec_report.json" KNAPSACK_TEST_FILE_PATTERN="spec_examples/**{,/*/**}/*_spec.rb" bundle exec rake knapsack:rspec
55
+
56
+ - name: Run specs when spec file was removed and still exists in knapsack report json
57
+ run: |
58
+ rm spec_examples/fast/1_spec.rb
59
+ KNAPSACK_TEST_FILE_PATTERN="spec_examples/**{,/*/**}/*_spec.rb" bundle exec rake knapsack:rspec
60
+
61
+ - name: Run specs from multiple directories with manually specified test_dir
62
+ run: KNAPSACK_TEST_DIR=spec_examples KNAPSACK_TEST_FILE_PATTERN="{spec_examples,spec_engine_examples}/**{,/*/**}/*_spec.rb" bundle exec rake knapsack:rspec
63
+
64
+ # Tests for example minitest test suite
65
+ - name: Generate knapsack report
66
+ run: KNAPSACK_GENERATE_REPORT=true bundle exec rake test
67
+
68
+ - name: Run tests with enabled time offset warning
69
+ run: bundle exec rake test
70
+
71
+ - name: Run rake task for the first CI node
72
+ run: CI_NODE_TOTAL=2 CI_NODE_INDEX=0 KNAPSACK_TEST_FILE_PATTERN="test_examples/**{,/*/**}/*_test.rb" bundle exec rake knapsack:minitest
73
+ - name: Run rake task for the second CI node
74
+ run: CI_NODE_TOTAL=2 CI_NODE_INDEX=1 KNAPSACK_TEST_FILE_PATTERN="test_examples/**{,/*/**}/*_test.rb" bundle exec rake knapsack:minitest
75
+
76
+ - name: Check passing arguments to minitest. Run verbose tests
77
+ run: |
78
+ KNAPSACK_TEST_FILE_PATTERN="test_examples/**{,/*/**}/*_test.rb" bundle exec rake "knapsack:minitest[--verbose]"
79
+ KNAPSACK_TEST_FILE_PATTERN="test_examples/**{,/*/**}/*_test.rb" bin/knapsack minitest "--verbose --pride"
80
+
81
+ - name: Run tests with custom knapsack logger
82
+ run: CUSTOM_LOGGER=true KNAPSACK_TEST_FILE_PATTERN="test_examples/**{,/*/**}/*_test.rb" bundle exec rake knapsack:minitest
83
+
84
+ - name: Run tests for custom knapsack report path
85
+ run: |
86
+ cp knapsack_minitest_report.json knapsack_custom_minitest_report.json
87
+ KNAPSACK_REPORT_PATH="knapsack_custom_minitest_report.json" KNAPSACK_TEST_FILE_PATTERN="test_examples/**{,/*/**}/*_test.rb" bundle exec rake knapsack:minitest
88
+
89
+ - name: Run tests when test file was removed and still exists in knapsack report json
90
+ run: |
91
+ rm test_examples/fast/unit_test.rb
92
+ KNAPSACK_TEST_FILE_PATTERN="test_examples/**{,/*/**}/*_test.rb" bundle exec rake knapsack:minitest
93
+
94
+ # Tests for example spinach test suite
95
+ - name: Generate knapsack report
96
+ run: KNAPSACK_GENERATE_REPORT=true bundle exec spinach -f spinach_examples
97
+
98
+ - name: Run tests with enabled time offset warning
99
+ run: bundle exec spinach -f spinach_examples
100
+
101
+ - name: Run rake task for the first CI node
102
+ run: CI_NODE_TOTAL=2 CI_NODE_INDEX=0 KNAPSACK_TEST_FILE_PATTERN="spinach_examples/**{,/*/**}/*.feature" bundle exec rake "knapsack:spinach[-f spinach_examples]"
103
+ - name: Run rake task for the second CI node
104
+ run: CI_NODE_TOTAL=2 CI_NODE_INDEX=1 KNAPSACK_TEST_FILE_PATTERN="spinach_examples/**{,/*/**}/*.feature" bundle exec rake "knapsack:spinach[-f spinach_examples]"
105
+
106
+ - name: Run tests with custom knapsack logger
107
+ run: CUSTOM_LOGGER=true KNAPSACK_TEST_FILE_PATTERN="spinach_examples/**{,/*/**}/*.feature" bundle exec rake "knapsack:spinach[-f spinach_examples]"
108
+
109
+ - name: Run tests for custom knapsack report path
110
+ run: |
111
+ cp knapsack_spinach_report.json knapsack_custom_spinach_report.json
112
+ KNAPSACK_REPORT_PATH="knapsack_custom_spinach_report.json" KNAPSACK_TEST_FILE_PATTERN="spinach_examples/**{,/*/**}/*.feature" bundle exec rake "knapsack:spinach[-f spinach_examples]"
113
+
114
+ - name: Run tests when test file was removed and still exists in knapsack report json
115
+ run: |
116
+ rm spinach_examples/scenario1.feature
117
+ KNAPSACK_TEST_FILE_PATTERN="spinach_examples/**{,/*/**}/*.feature" bundle exec rake "knapsack:spinach[-f spinach_examples]"
data/CHANGELOG.md CHANGED
@@ -2,6 +2,58 @@
2
2
 
3
3
  * TODO
4
4
 
5
+ ### 3.1.0
6
+
7
+ * Sorting Algorithm: round robin to least connections
8
+
9
+ https://github.com/KnapsackPro/knapsack/pull/99
10
+
11
+ https://github.com/KnapsackPro/knapsack/compare/v3.0.0...v3.1.0
12
+
13
+ ### 3.0.0
14
+
15
+ * __(breaking change)__ Require minimum Ruby 2.2 version
16
+
17
+ https://github.com/KnapsackPro/knapsack/pull/115
18
+
19
+ * __(breaking change)__ Drop support for Minitest 4.x. Force to use minitest 5.x even on CI.
20
+
21
+ https://github.com/KnapsackPro/knapsack/pull/114
22
+
23
+ * Replace Travis CI with GitHub Actions
24
+
25
+ https://github.com/KnapsackPro/knapsack/pull/112
26
+
27
+ https://github.com/KnapsackPro/knapsack/compare/v2.0.0...v3.0.0
28
+
29
+ ### 2.0.0
30
+
31
+ * __(breaking change)__ Ruby 2.1 is a minimum required version
32
+
33
+ https://github.com/KnapsackPro/knapsack/pull/113
34
+
35
+ * Use Ruby 3 and add small development adjustments in codebase
36
+
37
+ https://github.com/KnapsackPro/knapsack/pull/110
38
+
39
+ https://github.com/KnapsackPro/knapsack/compare/v1.22.0...v2.0.0
40
+
41
+ ### 1.22.0
42
+
43
+ * Update time offset warning
44
+
45
+ https://github.com/KnapsackPro/knapsack/pull/105
46
+
47
+ https://github.com/KnapsackPro/knapsack/compare/v1.21.1...v1.22.0
48
+
49
+ ### 1.21.1
50
+
51
+ * Fix a bug with tracking time for pending specs in RSpec
52
+
53
+ https://github.com/KnapsackPro/knapsack/pull/109
54
+
55
+ https://github.com/KnapsackPro/knapsack/compare/v1.21.0...v1.21.1
56
+
5
57
  ### 1.21.0
6
58
 
7
59
  * Track time in before and after `:context` hooks
data/knapsack.gemspec CHANGED
@@ -18,17 +18,16 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.required_ruby_version = '>= 1.9.3'
21
+ spec.required_ruby_version = '>= 2.2'
22
22
 
23
23
  spec.add_dependency 'rake', '>= 0'
24
24
 
25
25
  spec.add_development_dependency 'bundler', '>= 1.6'
26
26
  spec.add_development_dependency 'rspec', '~> 3.0', '>= 2.10.0'
27
- spec.add_development_dependency 'rspec-its', '~> 1.2'
27
+ spec.add_development_dependency 'rspec-its', '~> 1.3'
28
28
  spec.add_development_dependency 'cucumber', '>= 0'
29
29
  spec.add_development_dependency 'spinach', '>= 0.8'
30
30
  spec.add_development_dependency 'minitest', '>= 5.0.0'
31
- spec.add_development_dependency 'codeclimate-test-reporter', '~> 0'
32
31
  spec.add_development_dependency 'pry', '~> 0'
33
- spec.add_development_dependency 'timecop', '>= 0.1.0'
32
+ spec.add_development_dependency 'timecop', '>= 0.9.4'
34
33
  end
@@ -23,20 +23,20 @@ module Knapsack
23
23
  def bind_time_tracker
24
24
  ::Minitest::Test.send(:include, BindTimeTrackerMinitestPlugin)
25
25
 
26
- add_post_run_callback do
26
+ Minitest.after_run do
27
27
  Knapsack.logger.info(Presenter.global_time)
28
28
  end
29
29
  end
30
30
 
31
31
  def bind_report_generator
32
- add_post_run_callback do
32
+ Minitest.after_run do
33
33
  Knapsack.report.save
34
34
  Knapsack.logger.info(Presenter.report_details)
35
35
  end
36
36
  end
37
37
 
38
38
  def bind_time_offset_warning
39
- add_post_run_callback do
39
+ Minitest.after_run do
40
40
  Knapsack.logger.log(
41
41
  Presenter.time_offset_log_level,
42
42
  Presenter.time_offset_warning
@@ -64,16 +64,6 @@ module Knapsack
64
64
  # test_path will look like ./test/dir/unit_test.rb
65
65
  test_path
66
66
  end
67
-
68
- private
69
-
70
- def add_post_run_callback(&block)
71
- if Minitest.respond_to?(:after_run)
72
- Minitest.after_run { block.call }
73
- else
74
- Minitest::Unit.after_tests { block.call }
75
- end
76
- end
77
67
  end
78
68
  end
79
69
  end
@@ -2,7 +2,7 @@ module Knapsack
2
2
  module Distributors
3
3
  class ReportDistributor < BaseDistributor
4
4
  def sorted_report
5
- @sorted_report ||= report.sort_by { |test_path, time| time }.reverse
5
+ @sorted_report ||= report.sort_by { |_test_path, time| -time }
6
6
  end
7
7
 
8
8
  def sorted_report_with_existing_tests
@@ -10,7 +10,7 @@ module Knapsack
10
10
  end
11
11
 
12
12
  def total_time_execution
13
- @total_time_execution ||= sorted_report_with_existing_tests.map(&:last).reduce(0, :+).to_f
13
+ @total_time_execution ||= sorted_report_with_existing_tests.map { |_test_path, time| time }.reduce(0, :+).to_f
14
14
  end
15
15
 
16
16
  def node_time_execution
@@ -20,73 +20,52 @@ module Knapsack
20
20
  private
21
21
 
22
22
  def post_assign_test_files_to_node
23
- assign_slow_test_files
24
- assign_remaining_test_files
23
+ assign_test_files
25
24
  sort_assigned_test_files
26
25
  end
27
26
 
28
27
  def sort_assigned_test_files
29
- ci_node_total.times do |index|
30
- # sort by first key (file name)
31
- # reverse it and then sort by second key (time) in reverse order
32
- node_tests[index][:test_files_with_time].sort!.reverse!.sort! do |x, y|
33
- y[1] <=> x[1]
34
- end
28
+ node_tests.map do |node|
29
+ node[:test_files_with_time]
30
+ .sort_by! { |file_name, _time| file_name }
31
+ .reverse!
32
+ .sort_by! { |_file_name, time| time }
33
+ .reverse!
35
34
  end
36
35
  end
37
36
 
38
37
  def post_tests_for_node(node_index)
39
38
  node_test = node_tests[node_index]
40
39
  return unless node_test
41
- node_test[:test_files_with_time].map(&:first)
40
+ node_test[:test_files_with_time].map { |file_name, _time| file_name }
42
41
  end
43
42
 
44
43
  def default_node_tests
45
- @node_tests = []
46
- ci_node_total.times do |index|
47
- @node_tests << {
44
+ @node_tests = Array.new(ci_node_total) do |index|
45
+ {
48
46
  node_index: index,
49
47
  time_left: node_time_execution,
50
- test_files_with_time: []
48
+ test_files_with_time: [],
49
+ weight: 0
51
50
  }
52
51
  end
53
52
  end
54
53
 
55
- def assign_slow_test_files
56
- @not_assigned_test_files = []
57
- node_index = 0
58
- sorted_report_with_existing_tests.each do |test_file_with_time|
59
- assign_slow_test_file(node_index, test_file_with_time)
60
- node_index += 1
61
- node_index %= ci_node_total
62
- end
63
- end
54
+ def assign_test_files
55
+ sorted_report_with_existing_tests.map do |test_file_with_time|
56
+ test_execution_time = test_file_with_time.last
64
57
 
65
- def assign_slow_test_file(node_index, test_file_with_time)
66
- time = test_file_with_time[1]
67
- time_left = node_tests[node_index][:time_left] - time
58
+ current_lightest_node = node_tests.min_by { |node| node[:weight] }
68
59
 
69
- if time_left >= 0 or node_tests[node_index][:test_files_with_time].empty?
70
- node_tests[node_index][:time_left] -= time
71
- node_tests[node_index][:test_files_with_time] << test_file_with_time
72
- else
73
- @not_assigned_test_files << test_file_with_time
74
- end
75
- end
60
+ updated_node_data = {
61
+ time_left: current_lightest_node[:time_left] - test_execution_time,
62
+ weight: current_lightest_node[:weight] + test_execution_time,
63
+ test_files_with_time: current_lightest_node[:test_files_with_time] << test_file_with_time
64
+ }
76
65
 
77
- def assign_remaining_test_files
78
- @not_assigned_test_files.each do |test_file_with_time|
79
- index = node_with_max_time_left
80
- time = test_file_with_time[1]
81
- node_tests[index][:time_left] -= time
82
- node_tests[index][:test_files_with_time] << test_file_with_time
66
+ current_lightest_node.merge!(updated_node_data)
83
67
  end
84
68
  end
85
-
86
- def node_with_max_time_left
87
- node_test = node_tests.max { |a,b| a[:time_left] <=> b[:time_left] }
88
- node_test[:node_index]
89
- end
90
69
  end
91
70
  end
92
71
  end
@@ -51,10 +51,14 @@ module Knapsack
51
51
  }
52
52
  if Knapsack.tracker.time_exceeded?
53
53
  str << %{
54
- Tests on this CI node took more than max allowed node time execution.
54
+ Test on this CI node ran for longer than the max allowed node time execution.
55
55
  Please regenerate your knapsack report.
56
- If that didn't help then split your heavy test file
57
- or bump time_offset_in_seconds setting.}
56
+
57
+ If that doesn't help, you can split your slowest test files into smaller files, or bump up the time_offset_in_seconds setting.
58
+
59
+ You can also allow the knapsack_pro gem to automatically divide your slow test files across parallel CI nodes.
60
+ https://knapsackpro.com/faq/question/how-to-auto-split-test-files-by-test-cases-on-parallel-jobs-ci-nodes?utm_source=knapsack_gem&utm_medium=knapsack_gem_output&utm_campaign=knapsack_gem_time_offset_warning
61
+ }
58
62
  else
59
63
  str << %{
60
64
  Global time execution for this CI node is fine.
@@ -63,9 +67,8 @@ Happy testing!}
63
67
  str << "\n\nNeed explanation? See FAQ:"
64
68
  str << "\nhttps://docs.knapsackpro.com/ruby/knapsack#faq"
65
69
  str << "\n=================================================\n"
66
- str << %{See how to split tests in a dynamic way using Queue Mode to ensure all parallel nodes
67
- finish work at a similar time even when your CI or random test execution is a bottleneck:
68
- https://youtu.be/hUEB1XDKEFY
70
+ str << %{Read up on the benefits of a dynamic test split with Knapsack Pro Queue Mode:
71
+ https://docs.knapsackpro.com/2020/how-to-speed-up-ruby-and-javascript-tests-with-ci-parallelisation
69
72
 
70
73
  Sign up for Knapsack Pro here:
71
74
  https://knapsackpro.com}
@@ -23,15 +23,19 @@ module Knapsack
23
23
  end
24
24
 
25
25
  def stop_timer
26
- @execution_time = now_without_mock_time.to_f - @start_time
27
- update_global_time
28
- update_test_file_time
29
- @execution_time
26
+ execution_time = now_without_mock_time.to_f - @start_time
27
+
28
+ if test_path
29
+ update_global_time(execution_time)
30
+ update_test_file_time(execution_time)
31
+ @test_path = nil
32
+ end
33
+
34
+ execution_time
30
35
  end
31
36
 
32
37
  def test_path
33
- raise("test_path needs to be set by Knapsack Adapter's bind method") unless @test_path
34
- @test_path.sub(/^\.\//, '')
38
+ @test_path.sub(/^\.\//, '') if @test_path
35
39
  end
36
40
 
37
41
  def time_exceeded?
@@ -62,13 +66,13 @@ module Knapsack
62
66
  @test_path = nil
63
67
  end
64
68
 
65
- def update_global_time
66
- @global_time += @execution_time
69
+ def update_global_time(execution_time)
70
+ @global_time += execution_time
67
71
  end
68
72
 
69
- def update_test_file_time
73
+ def update_test_file_time(execution_time)
70
74
  @test_files_with_time[test_path] ||= 0
71
- @test_files_with_time[test_path] += @execution_time
75
+ @test_files_with_time[test_path] += execution_time
72
76
  end
73
77
 
74
78
  def report_distributor
@@ -1,3 +1,3 @@
1
1
  module Knapsack
2
- VERSION = '1.21.0'
2
+ VERSION = '3.1.0'
3
3
  end
@@ -118,7 +118,7 @@ describe Knapsack::Distributors::ReportDistributor do
118
118
  'c_spec.rb' => 2.0,
119
119
  'd_spec.rb' => 2.5,
120
120
  'a_spec.rb' => 1.0,
121
- 'b_spec.rb' => 1.5,
121
+ 'b_spec.rb' => 1.5
122
122
  }
123
123
  end
124
124
  let(:custom_args) { { ci_node_total: 3 } }
@@ -134,6 +134,7 @@ describe Knapsack::Distributors::ReportDistributor do
134
134
  expect(distributor.node_tests[0]).to eql({
135
135
  :node_index => 0,
136
136
  :time_left => -0.5,
137
+ :weight => 9.0,
137
138
  :test_files_with_time => [
138
139
  ["g_spec.rb", 9.0]
139
140
  ]
@@ -143,12 +144,12 @@ describe Knapsack::Distributors::ReportDistributor do
143
144
  it do
144
145
  expect(distributor.node_tests[1]).to eql({
145
146
  :node_index => 1,
146
- :time_left => 0.0,
147
+ :time_left => 0.5,
148
+ :weight => 8.0,
147
149
  :test_files_with_time => [
148
150
  ["f_spec.rb", 3.5],
149
151
  ["d_spec.rb", 2.5],
150
- ["b_spec.rb", 1.5],
151
- ["a_spec.rb", 1.0]
152
+ ["c_spec.rb", 2.0]
152
153
  ]
153
154
  })
154
155
  end
@@ -156,11 +157,13 @@ describe Knapsack::Distributors::ReportDistributor do
156
157
  it do
157
158
  expect(distributor.node_tests[2]).to eql({
158
159
  :node_index => 2,
159
- :time_left => 0.5,
160
+ :time_left => 0.0,
161
+ :weight => 8.5,
160
162
  :test_files_with_time => [
161
- ["i_spec.rb", 3.0],
162
163
  ["h_spec.rb", 3.0],
163
- ["c_spec.rb", 2.0]
164
+ ["i_spec.rb", 3.0],
165
+ ["b_spec.rb", 1.5],
166
+ ["a_spec.rb", 1.0]
164
167
  ]
165
168
  })
166
169
  end
@@ -170,10 +173,9 @@ describe Knapsack::Distributors::ReportDistributor do
170
173
  context 'when node exists' do
171
174
  it do
172
175
  expect(distributor.tests_for_node(1)).to eql([
173
- 'f_spec.rb',
174
- 'd_spec.rb',
175
- 'b_spec.rb',
176
- 'a_spec.rb'
176
+ "f_spec.rb",
177
+ "d_spec.rb",
178
+ "c_spec.rb"
177
179
  ])
178
180
  end
179
181
  end
@@ -183,4 +185,78 @@ describe Knapsack::Distributors::ReportDistributor do
183
185
  end
184
186
  end
185
187
  end
188
+
189
+ describe 'algorithmic efficiency' do
190
+ subject(:node_weights) do
191
+ distro = distributor
192
+ distro.assign_test_files_to_node
193
+ distro.node_tests.map { |node| node[:weight] }
194
+ end
195
+
196
+ before do
197
+ allow(distributor).to receive(:all_tests).and_return(report.keys)
198
+ end
199
+
200
+ let(:custom_args) { { ci_node_total: 3 } }
201
+
202
+ context 'with the most simple example' do
203
+ let(:report) do
204
+ {
205
+ 'a_spec.rb' => 1.0,
206
+ 'b_spec.rb' => 1.0,
207
+ 'c_spec.rb' => 1.0,
208
+ 'd_spec.rb' => 1.0,
209
+ 'e_spec.rb' => 1.0,
210
+ 'f_spec.rb' => 1.0,
211
+ 'g_spec.rb' => 1.0,
212
+ 'h_spec.rb' => 1.0,
213
+ 'i_spec.rb' => 1.0
214
+ }
215
+ end
216
+
217
+ it 'assigns all nodes equally' do
218
+ expect(node_weights.uniq).to contain_exactly 3.0
219
+ end
220
+ end
221
+
222
+ context 'with a medium difficulty example' do
223
+ let(:report) do
224
+ {
225
+ 'a_spec.rb' => 1.0,
226
+ 'b_spec.rb' => 2.0,
227
+ 'c_spec.rb' => 3.0,
228
+ 'd_spec.rb' => 1.0,
229
+ 'e_spec.rb' => 2.0,
230
+ 'f_spec.rb' => 3.0,
231
+ 'g_spec.rb' => 1.0,
232
+ 'h_spec.rb' => 2.0,
233
+ 'i_spec.rb' => 3.0
234
+ }
235
+ end
236
+
237
+ it 'assigns all nodes equally' do
238
+ expect(node_weights.uniq).to contain_exactly 6.0
239
+ end
240
+ end
241
+
242
+ context 'with a difficult example' do
243
+ let(:report) do
244
+ {
245
+ 'a_spec.rb' => 2.0,
246
+ 'b_spec.rb' => 2.0,
247
+ 'c_spec.rb' => 3.0,
248
+ 'd_spec.rb' => 1.0,
249
+ 'e_spec.rb' => 1.0,
250
+ 'f_spec.rb' => 1.0,
251
+ 'g_spec.rb' => 9.0,
252
+ 'h_spec.rb' => 1.0,
253
+ 'i_spec.rb' => 10.0
254
+ }
255
+ end
256
+
257
+ it 'assigns all nodes equally' do
258
+ expect(node_weights.uniq).to contain_exactly 10.0
259
+ end
260
+ end
261
+ end
186
262
  end
@@ -48,7 +48,7 @@ describe Knapsack::Tracker do
48
48
 
49
49
  context 'when test_path not set' do
50
50
  it do
51
- expect { subject }.to raise_error("test_path needs to be set by Knapsack Adapter's bind method")
51
+ expect(subject).to be_nil
52
52
  end
53
53
  end
54
54
 
@@ -133,6 +133,9 @@ describe Knapsack::Tracker do
133
133
  it { expect(tracker.test_files_with_time.keys.size).to eql 2 }
134
134
  it { expect(tracker.test_files_with_time['a_spec.rb']).to be_within(delta).of(0.1) }
135
135
  it { expect(tracker.test_files_with_time['b_spec.rb']).to be_within(delta).of(0.2) }
136
+ it 'resets test_path after time is measured' do
137
+ expect(tracker.test_path).to be_nil
138
+ end
136
139
  end
137
140
 
138
141
  context "with Timecop - Timecop shouldn't have impact on measured test time" do
@@ -157,6 +160,9 @@ describe Knapsack::Tracker do
157
160
  it { expect(tracker.test_files_with_time.keys.size).to eql 2 }
158
161
  it { expect(tracker.test_files_with_time['a_spec.rb']).to be_within(delta).of(0) }
159
162
  it { expect(tracker.test_files_with_time['b_spec.rb']).to be_within(delta).of(0) }
163
+ it 'resets test_path after time is measured' do
164
+ expect(tracker.test_path).to be_nil
165
+ end
160
166
  end
161
167
  end
162
168
 
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 'knapsack'
11
8
 
12
9
  Dir["#{Knapsack.root}/spec/support/**/*.rb"].each { |f| require f }
@@ -1,7 +1,7 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class Minitest::SharedExamples < Module
4
- include Minitest::Spec::DSL if RUBY_VERSION != "1.9.3"
4
+ include Minitest::Spec::DSL
5
5
  end
6
6
 
7
7
  SharedExampleSpec = Minitest::SharedExamples.new do
@@ -16,10 +16,22 @@ describe FakeCalculator do
16
16
  end
17
17
 
18
18
  it '#add' do
19
- @calc.add(2, 3).must_equal 5
19
+ result = @calc.add(2, 3)
20
+
21
+ if self.respond_to?(:_)
22
+ _(result).must_equal 5
23
+ else
24
+ result.must_equal 5
25
+ end
20
26
  end
21
27
 
22
28
  it '#mal' do
23
- @calc.mal(2, 3).must_equal 6
29
+ result = @calc.mal(2, 3)
30
+
31
+ if self.respond_to?(:_)
32
+ _(result).must_equal 6
33
+ else
34
+ result.must_equal 6
35
+ end
24
36
  end
25
37
  end
@@ -2,15 +2,6 @@ require 'minitest/autorun'
2
2
 
3
3
  require 'knapsack'
4
4
 
5
- if RUBY_VERSION == "1.9.3"
6
- unless defined? Minitest
7
- Minitest = MiniTest
8
- end
9
- unless defined? Minitest::Test
10
- Minitest::Test = MiniTest::Unit::TestCase
11
- end
12
- end
13
-
14
5
  Knapsack.tracker.config({
15
6
  enable_time_offset_warning: true,
16
7
  time_offset_in_seconds: 3
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: knapsack
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.21.0
4
+ version: 3.1.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-15 00:00:00.000000000 Z
11
+ date: 2021-06-23 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
@@ -114,20 +114,6 @@ dependencies:
114
114
  - - ">="
115
115
  - !ruby/object:Gem::Version
116
116
  version: 5.0.0
117
- - !ruby/object:Gem::Dependency
118
- name: codeclimate-test-reporter
119
- requirement: !ruby/object:Gem::Requirement
120
- requirements:
121
- - - "~>"
122
- - !ruby/object:Gem::Version
123
- version: '0'
124
- type: :development
125
- prerelease: false
126
- version_requirements: !ruby/object:Gem::Requirement
127
- requirements:
128
- - - "~>"
129
- - !ruby/object:Gem::Version
130
- version: '0'
131
117
  - !ruby/object:Gem::Dependency
132
118
  name: pry
133
119
  requirement: !ruby/object:Gem::Requirement
@@ -148,14 +134,14 @@ dependencies:
148
134
  requirements:
149
135
  - - ">="
150
136
  - !ruby/object:Gem::Version
151
- version: 0.1.0
137
+ version: 0.9.4
152
138
  type: :development
153
139
  prerelease: false
154
140
  version_requirements: !ruby/object:Gem::Requirement
155
141
  requirements:
156
142
  - - ">="
157
143
  - !ruby/object:Gem::Version
158
- version: 0.1.0
144
+ version: 0.9.4
159
145
  description: Parallel tests across CI server nodes based on each test file's time
160
146
  execution. It generates a test time execution report and uses it for future test
161
147
  runs.
@@ -163,20 +149,18 @@ email:
163
149
  - arturtrzop@gmail.com
164
150
  executables:
165
151
  - knapsack
166
- - print_header.sh
167
152
  extensions: []
168
153
  extra_rdoc_files: []
169
154
  files:
155
+ - ".github/workflows/ruby.yml"
170
156
  - ".gitignore"
171
157
  - ".rspec"
172
- - ".travis.yml"
173
158
  - CHANGELOG.md
174
159
  - Gemfile
175
160
  - LICENSE.txt
176
161
  - README.md
177
162
  - Rakefile
178
163
  - bin/knapsack
179
- - bin/print_header.sh
180
164
  - docs/images/logos/knapsack-@2.png
181
165
  - docs/images/logos/knapsack-big.png
182
166
  - docs/images/logos/knapsack-logo-@2.png
@@ -278,14 +262,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
278
262
  requirements:
279
263
  - - ">="
280
264
  - !ruby/object:Gem::Version
281
- version: 1.9.3
265
+ version: '2.2'
282
266
  required_rubygems_version: !ruby/object:Gem::Requirement
283
267
  requirements:
284
268
  - - ">="
285
269
  - !ruby/object:Gem::Version
286
270
  version: '0'
287
271
  requirements: []
288
- rubygems_version: 3.0.6
272
+ rubygems_version: 3.2.15
289
273
  signing_key:
290
274
  specification_version: 4
291
275
  summary: Knapsack splits tests across CI nodes and makes sure that tests will run
data/.travis.yml DELETED
@@ -1,116 +0,0 @@
1
- ---
2
- sudo: false
3
- language: ruby
4
- rvm:
5
- - 2.1
6
- - 2.2
7
- - 2.3
8
- - 2.4
9
- - 2.5
10
- - 2.6
11
- - 2.7
12
- - truffleruby-head
13
- addons:
14
- code_climate:
15
- repo_token: 38686058eed480dd0fcf8bce9015733e0bae88e44e30f4a1ac63df8aec2f86d8
16
- before_install:
17
- - "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc"
18
- script:
19
- # Test for knapsack gem
20
- - bin/print_header.sh "Run specs for Knapsack gem"
21
- - bundle exec rspec spec
22
-
23
-
24
- - bin/print_header.sh "------------------------------------------------------"
25
-
26
-
27
- # Tests for example rspec test suite
28
- - bin/print_header.sh "Generate knapsack report"
29
- - KNAPSACK_GENERATE_REPORT=true bundle exec rspec --default-path spec_examples --tag focus
30
-
31
- - bin/print_header.sh "Run specs with enabled time offset warning"
32
- - bundle exec rspec --default-path spec_examples
33
-
34
- - bin/print_header.sh "Run rake task for the first CI node"
35
- - CI_NODE_TOTAL=2 CI_NODE_INDEX=0 KNAPSACK_TEST_FILE_PATTERN="spec_examples/**{,/*/**}/*_spec.rb" bundle exec rake knapsack:rspec
36
- - bin/print_header.sh "Run rake task for the second CI node"
37
- - CI_NODE_TOTAL=2 CI_NODE_INDEX=1 KNAPSACK_TEST_FILE_PATTERN="spec_examples/**{,/*/**}/*_spec.rb" bundle exec rake knapsack:rspec
38
-
39
- - bin/print_header.sh "Check passing arguments to rspec. Run only specs with custom_focus tag"
40
- - KNAPSACK_TEST_FILE_PATTERN="spec_examples/**{,/*/**}/*_spec.rb" bundle exec rake "knapsack:rspec[--tag custom_focus]"
41
- - KNAPSACK_TEST_FILE_PATTERN="spec_examples/**{,/*/**}/*_spec.rb" bin/knapsack rspec "--tag custom_focus --profile"
42
-
43
- - bin/print_header.sh "Run specs with custom knapsack logger"
44
- - CUSTOM_LOGGER=true KNAPSACK_TEST_FILE_PATTERN="spec_examples/**{,/*/**}/*_spec.rb" bundle exec rake knapsack:rspec
45
-
46
- - bin/print_header.sh "Run specs for custom knapsack report path"
47
- - cp knapsack_rspec_report.json knapsack_custom_rspec_report.json
48
- - KNAPSACK_REPORT_PATH="knapsack_custom_rspec_report.json" KNAPSACK_TEST_FILE_PATTERN="spec_examples/**{,/*/**}/*_spec.rb" bundle exec rake knapsack:rspec
49
-
50
- - bin/print_header.sh "Run specs when spec file was removed and still exists in knapsack report json"
51
- - rm spec_examples/fast/1_spec.rb
52
- - KNAPSACK_TEST_FILE_PATTERN="spec_examples/**{,/*/**}/*_spec.rb" bundle exec rake knapsack:rspec
53
-
54
- - bin/print_header.sh "Run specs from multiple directories with manually specified test_dir"
55
- - KNAPSACK_TEST_DIR=spec_examples KNAPSACK_TEST_FILE_PATTERN="{spec_examples,spec_engine_examples}/**{,/*/**}/*_spec.rb" bundle exec rake knapsack:rspec
56
-
57
-
58
- - bin/print_header.sh "------------------------------------------------------"
59
-
60
-
61
- # Tests for example minitest test suite
62
- - bin/print_header.sh "Generate knapsack report"
63
- - KNAPSACK_GENERATE_REPORT=true bundle exec rake test
64
-
65
- - bin/print_header.sh "Run tests with enabled time offset warning"
66
- - bundle exec rake test
67
-
68
- - bin/print_header.sh "Run rake task for the first CI node"
69
- - CI_NODE_TOTAL=2 CI_NODE_INDEX=0 KNAPSACK_TEST_FILE_PATTERN="test_examples/**{,/*/**}/*_test.rb" bundle exec rake knapsack:minitest
70
- - bin/print_header.sh "Run rake task for the second CI node"
71
- - CI_NODE_TOTAL=2 CI_NODE_INDEX=1 KNAPSACK_TEST_FILE_PATTERN="test_examples/**{,/*/**}/*_test.rb" bundle exec rake knapsack:minitest
72
-
73
- - bin/print_header.sh "Check passing arguments to minitest. Run verbose tests"
74
- - KNAPSACK_TEST_FILE_PATTERN="test_examples/**{,/*/**}/*_test.rb" bundle exec rake "knapsack:minitest[--verbose]"
75
- - if [ "$TRAVIS_RUBY_VERSION" == "1.9.3" ]; then KNAPSACK_TEST_FILE_PATTERN="test_examples/**{,/*/**}/*_test.rb" bin/knapsack minitest "--verbose"; fi
76
- - if [ "$TRAVIS_RUBY_VERSION" != "1.9.3" ]; then KNAPSACK_TEST_FILE_PATTERN="test_examples/**{,/*/**}/*_test.rb" bin/knapsack minitest "--verbose --pride"; fi
77
-
78
- - bin/print_header.sh "Run tests with custom knapsack logger"
79
- - CUSTOM_LOGGER=true KNAPSACK_TEST_FILE_PATTERN="test_examples/**{,/*/**}/*_test.rb" bundle exec rake knapsack:minitest
80
-
81
- - bin/print_header.sh "Run tests for custom knapsack report path"
82
- - cp knapsack_minitest_report.json knapsack_custom_minitest_report.json
83
- - KNAPSACK_REPORT_PATH="knapsack_custom_minitest_report.json" KNAPSACK_TEST_FILE_PATTERN="test_examples/**{,/*/**}/*_test.rb" bundle exec rake knapsack:minitest
84
-
85
- - bin/print_header.sh "Run tests when test file was removed and still exists in knapsack report json"
86
- - rm test_examples/fast/unit_test.rb
87
- - KNAPSACK_TEST_FILE_PATTERN="test_examples/**{,/*/**}/*_test.rb" bundle exec rake knapsack:minitest
88
-
89
-
90
- - bin/print_header.sh "------------------------------------------------------"
91
-
92
-
93
- # Tests for example spinach test suite
94
- - bin/print_header.sh "Generate knapsack report"
95
- - KNAPSACK_GENERATE_REPORT=true bundle exec spinach -f spinach_examples
96
-
97
- - bin/print_header.sh "Run tests with enabled time offset warning"
98
- - bundle exec spinach -f spinach_examples
99
-
100
- - bin/print_header.sh "Run rake task for the first CI node"
101
- - CI_NODE_TOTAL=2 CI_NODE_INDEX=0 KNAPSACK_TEST_FILE_PATTERN="spinach_examples/**{,/*/**}/*.feature" bundle exec rake "knapsack:spinach[-f spinach_examples]"
102
- - bin/print_header.sh "Run rake task for the second CI node"
103
- - CI_NODE_TOTAL=2 CI_NODE_INDEX=1 KNAPSACK_TEST_FILE_PATTERN="spinach_examples/**{,/*/**}/*.feature" bundle exec rake "knapsack:spinach[-f spinach_examples]"
104
-
105
- - bin/print_header.sh "Run tests with custom knapsack logger"
106
- - CUSTOM_LOGGER=true KNAPSACK_TEST_FILE_PATTERN="spinach_examples/**{,/*/**}/*.feature" bundle exec rake "knapsack:spinach[-f spinach_examples]"
107
-
108
- - bin/print_header.sh "Run tests for custom knapsack report path"
109
- - cp knapsack_spinach_report.json knapsack_custom_spinach_report.json
110
- - KNAPSACK_REPORT_PATH="knapsack_custom_spinach_report.json" KNAPSACK_TEST_FILE_PATTERN="spinach_examples/**{,/*/**}/*.feature" bundle exec rake "knapsack:spinach[-f spinach_examples]"
111
-
112
- - bin/print_header.sh "Run tests when test file was removed and still exists in knapsack report json"
113
- - rm spinach_examples/scenario1.feature
114
- - KNAPSACK_TEST_FILE_PATTERN="spinach_examples/**{,/*/**}/*.feature" bundle exec rake "knapsack:spinach[-f spinach_examples]"
115
- notifications:
116
- email: false
data/bin/print_header.sh DELETED
@@ -1,5 +0,0 @@
1
- #!/bin/bash
2
-
3
- echo ==========================================================================================================================
4
- echo $1
5
- echo ==========================================================================================================================