knapsack 1.22.0 → 4.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: 3cd679c5843c5c9e43249da6da05bdfe304940b8e51a253dafe4eda8e1589524
4
- data.tar.gz: a24ed8bac83fa9ddb0d3ef1fe0e0381cc39403e9332bf019e0cede622d5e82c8
3
+ metadata.gz: 22056a9ce80fe227bf9a1a03c5dd700f6cf3445d5fc69203a42a0756f98c5ccf
4
+ data.tar.gz: 44bba135b5624b37c8f800b65c206a0552406c9a10499fdefb8d22e7cbfccfaf
5
5
  SHA512:
6
- metadata.gz: 4e1ae76d5393f45885c0121c812df6fe7cd233c71cc9102c0e47661d258b517e848971a62e272cc8306efff2d7b9cc6817524b6aa3b4cd05a31d81bf7bc8fdb9
7
- data.tar.gz: d2b0078d56fc9ecc42e177139a7a02295ea7ea270ae297dc662f0d96eea51270bce4d91ddbd034cf89720bba54d605369fdf6e7b378ed77f64928ee94e5f7222
6
+ metadata.gz: c07fbfb345373b82a0ad29aa5854d12285946725ceefb3dae95a67f53479af781beb1f90caea035ec66d6808c0f408c8f35df592f971f4a05f46545f10ed1d98
7
+ data.tar.gz: 197a4ba91a928c7202ab19105a1f8e65556d441a655532ccae96854de468a6de2eba8dfd7867aa4364d5b5a898f1a307cd4f53938e69bdbba39ac48022156bc2
@@ -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,51 @@
2
2
 
3
3
  * TODO
4
4
 
5
+ ### 4.0.0
6
+
7
+ * __(breaking change)__ Remove support for RSpec 2.x. This change was already done by accident in [the pull request](https://github.com/KnapsackPro/knapsack/pull/107) when we added the RSpec `context` hook, which is available only since RSpec 3.x.
8
+ * Use RSpec `example` block argument instead of the global `RSpec.current_example`. This allows to run tests with the `async-rspec` gem.
9
+
10
+ https://github.com/KnapsackPro/knapsack/pull/117
11
+
12
+ https://github.com/KnapsackPro/knapsack/compare/v3.1.0...v4.0.0
13
+
14
+ ### 3.1.0
15
+
16
+ * Sorting Algorithm: round robin to least connections
17
+
18
+ https://github.com/KnapsackPro/knapsack/pull/99
19
+
20
+ https://github.com/KnapsackPro/knapsack/compare/v3.0.0...v3.1.0
21
+
22
+ ### 3.0.0
23
+
24
+ * __(breaking change)__ Require minimum Ruby 2.2 version
25
+
26
+ https://github.com/KnapsackPro/knapsack/pull/115
27
+
28
+ * __(breaking change)__ Drop support for Minitest 4.x. Force to use minitest 5.x even on CI.
29
+
30
+ https://github.com/KnapsackPro/knapsack/pull/114
31
+
32
+ * Replace Travis CI with GitHub Actions
33
+
34
+ https://github.com/KnapsackPro/knapsack/pull/112
35
+
36
+ https://github.com/KnapsackPro/knapsack/compare/v2.0.0...v3.0.0
37
+
38
+ ### 2.0.0
39
+
40
+ * __(breaking change)__ Ruby 2.1 is a minimum required version
41
+
42
+ https://github.com/KnapsackPro/knapsack/pull/113
43
+
44
+ * Use Ruby 3 and add small development adjustments in codebase
45
+
46
+ https://github.com/KnapsackPro/knapsack/pull/110
47
+
48
+ https://github.com/KnapsackPro/knapsack/compare/v1.22.0...v2.0.0
49
+
5
50
  ### 1.22.0
6
51
 
7
52
  * Update time offset warning
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
- spec.add_development_dependency 'rspec', '~> 3.0', '>= 2.10.0'
27
- spec.add_development_dependency 'rspec-its', '~> 1.2'
26
+ spec.add_development_dependency 'rspec', '~> 3.0'
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
@@ -10,14 +10,8 @@ module Knapsack
10
10
  Knapsack.tracker.start_timer
11
11
  end
12
12
 
13
- config.prepend_before(:each) do
14
- current_example_group =
15
- if ::RSpec.respond_to?(:current_example)
16
- ::RSpec.current_example.metadata[:example_group]
17
- else
18
- example.metadata
19
- end
20
- Knapsack.tracker.test_path = RSpecAdapter.test_path(current_example_group)
13
+ config.prepend_before(:each) do |example|
14
+ Knapsack.tracker.test_path = RSpecAdapter.test_path(example)
21
15
  end
22
16
 
23
17
  config.append_after(:context) do
@@ -50,8 +44,10 @@ module Knapsack
50
44
  end
51
45
  end
52
46
 
53
- def self.test_path(example_group)
54
- if defined?(Turnip) && Turnip::VERSION.to_i < 2
47
+ def self.test_path(example)
48
+ example_group = example.metadata[:example_group]
49
+
50
+ if defined?(::Turnip) && Gem::Version.new(::Turnip::VERSION) < Gem::Version.new('2.0.0')
55
51
  unless example_group[:turnip]
56
52
  until example_group[:parent_example_group].nil?
57
53
  example_group = example_group[:parent_example_group]
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Knapsack
2
- VERSION = '1.22.0'
2
+ VERSION = '4.0.0'
3
3
  end
@@ -16,22 +16,16 @@ describe Knapsack::Adapters::RSpecAdapter do
16
16
  let(:tracker) { instance_double(Knapsack::Tracker) }
17
17
  let(:test_path) { 'spec/a_spec.rb' }
18
18
  let(:global_time) { 'Global time: 01m 05s' }
19
- let(:example_group) { double }
20
- let(:current_example) do
21
- OpenStruct.new(metadata: {
22
- example_group: example_group
23
- })
24
- end
19
+ let(:current_example) { double }
25
20
 
26
21
  it do
27
22
  expect(config).to receive(:prepend_before).with(:context).and_yield
28
- expect(config).to receive(:prepend_before).with(:each).and_yield
23
+ expect(config).to receive(:prepend_before).with(:each).and_yield(current_example)
29
24
  expect(config).to receive(:append_after).with(:context).and_yield
30
25
  expect(config).to receive(:after).with(:suite).and_yield
31
26
  expect(::RSpec).to receive(:configure).and_yield(config)
32
27
 
33
- expect(::RSpec).to receive(:current_example).twice.and_return(current_example)
34
- expect(described_class).to receive(:test_path).with(example_group).and_return(test_path)
28
+ expect(described_class).to receive(:test_path).with(current_example).and_return(test_path)
35
29
 
36
30
  allow(Knapsack).to receive(:tracker).and_return(tracker)
37
31
  expect(tracker).to receive(:start_timer).ordered
@@ -81,7 +75,7 @@ describe Knapsack::Adapters::RSpecAdapter do
81
75
  end
82
76
 
83
77
  describe '.test_path' do
84
- let(:current_example_metadata) do
78
+ let(:example_group) do
85
79
  {
86
80
  file_path: '1_shared_example.rb',
87
81
  parent_example_group: {
@@ -92,14 +86,19 @@ describe Knapsack::Adapters::RSpecAdapter do
92
86
  }
93
87
  }
94
88
  end
89
+ let(:current_example) do
90
+ OpenStruct.new(metadata: {
91
+ example_group: example_group
92
+ })
93
+ end
95
94
 
96
- subject { described_class.test_path(current_example_metadata) }
95
+ subject { described_class.test_path(current_example) }
97
96
 
98
97
  it { should eql 'a_spec.rb' }
99
98
 
100
99
  context 'with turnip features' do
101
100
  describe 'when the turnip version is less than 2' do
102
- let(:current_example_metadata) do
101
+ let(:example_group) do
103
102
  {
104
103
  file_path: "./spec/features/logging_in.feature",
105
104
  turnip: true,
@@ -115,7 +114,7 @@ describe Knapsack::Adapters::RSpecAdapter do
115
114
  end
116
115
 
117
116
  describe 'when turnip is version 2 or greater' do
118
- let(:current_example_metadata) do
117
+ let(:example_group) do
119
118
  {
120
119
  file_path: "gems/turnip-2.0.0/lib/turnip/rspec.rb",
121
120
  turnip: true,
@@ -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
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.22.0
4
+ version: 4.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-04-20 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
@@ -42,9 +42,6 @@ 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'
@@ -52,9 +49,6 @@ dependencies:
52
49
  prerelease: false
53
50
  version_requirements: !ruby/object:Gem::Requirement
54
51
  requirements:
55
- - - ">="
56
- - !ruby/object:Gem::Version
57
- version: 2.10.0
58
52
  - - "~>"
59
53
  - !ruby/object:Gem::Version
60
54
  version: '3.0'
@@ -64,14 +58,14 @@ dependencies:
64
58
  requirements:
65
59
  - - "~>"
66
60
  - !ruby/object:Gem::Version
67
- version: '1.2'
61
+ version: '1.3'
68
62
  type: :development
69
63
  prerelease: false
70
64
  version_requirements: !ruby/object:Gem::Requirement
71
65
  requirements:
72
66
  - - "~>"
73
67
  - !ruby/object:Gem::Version
74
- version: '1.2'
68
+ version: '1.3'
75
69
  - !ruby/object:Gem::Dependency
76
70
  name: cucumber
77
71
  requirement: !ruby/object:Gem::Requirement
@@ -114,20 +108,6 @@ dependencies:
114
108
  - - ">="
115
109
  - !ruby/object:Gem::Version
116
110
  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
111
  - !ruby/object:Gem::Dependency
132
112
  name: pry
133
113
  requirement: !ruby/object:Gem::Requirement
@@ -148,14 +128,14 @@ dependencies:
148
128
  requirements:
149
129
  - - ">="
150
130
  - !ruby/object:Gem::Version
151
- version: 0.1.0
131
+ version: 0.9.4
152
132
  type: :development
153
133
  prerelease: false
154
134
  version_requirements: !ruby/object:Gem::Requirement
155
135
  requirements:
156
136
  - - ">="
157
137
  - !ruby/object:Gem::Version
158
- version: 0.1.0
138
+ version: 0.9.4
159
139
  description: Parallel tests across CI server nodes based on each test file's time
160
140
  execution. It generates a test time execution report and uses it for future test
161
141
  runs.
@@ -163,20 +143,18 @@ email:
163
143
  - arturtrzop@gmail.com
164
144
  executables:
165
145
  - knapsack
166
- - print_header.sh
167
146
  extensions: []
168
147
  extra_rdoc_files: []
169
148
  files:
149
+ - ".github/workflows/ruby.yml"
170
150
  - ".gitignore"
171
151
  - ".rspec"
172
- - ".travis.yml"
173
152
  - CHANGELOG.md
174
153
  - Gemfile
175
154
  - LICENSE.txt
176
155
  - README.md
177
156
  - Rakefile
178
157
  - bin/knapsack
179
- - bin/print_header.sh
180
158
  - docs/images/logos/knapsack-@2.png
181
159
  - docs/images/logos/knapsack-big.png
182
160
  - docs/images/logos/knapsack-logo-@2.png
@@ -278,14 +256,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
278
256
  requirements:
279
257
  - - ">="
280
258
  - !ruby/object:Gem::Version
281
- version: 1.9.3
259
+ version: '2.2'
282
260
  required_rubygems_version: !ruby/object:Gem::Requirement
283
261
  requirements:
284
262
  - - ">="
285
263
  - !ruby/object:Gem::Version
286
264
  version: '0'
287
265
  requirements: []
288
- rubygems_version: 3.0.6
266
+ rubygems_version: 3.2.22
289
267
  signing_key:
290
268
  specification_version: 4
291
269
  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 ==========================================================================================================================