test-queue 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +42 -42
  3. data/exe/cucumber-queue +2 -1
  4. data/exe/minitest-queue +3 -2
  5. data/exe/rspec-queue +2 -1
  6. data/exe/testunit-queue +2 -1
  7. data/lib/test-queue.rb +2 -0
  8. data/lib/test_queue/iterator.rb +22 -14
  9. data/lib/test_queue/runner/cucumber.rb +3 -0
  10. data/lib/test_queue/runner/{sample.rb → example.rb} +30 -9
  11. data/lib/test_queue/runner/minitest.rb +5 -3
  12. data/lib/test_queue/runner/minitest4.rb +12 -7
  13. data/lib/test_queue/runner/minitest5.rb +37 -22
  14. data/lib/test_queue/runner/puppet_lint.rb +6 -4
  15. data/lib/test_queue/runner/rspec.rb +14 -3
  16. data/lib/test_queue/runner/rspec2.rb +24 -24
  17. data/lib/test_queue/runner/rspec3.rb +11 -11
  18. data/lib/test_queue/runner/testunit.rb +6 -3
  19. data/lib/test_queue/runner.rb +87 -97
  20. data/lib/test_queue/stats.rb +17 -13
  21. data/lib/test_queue/test_framework.rb +2 -0
  22. data/lib/test_queue/version.rb +5 -0
  23. data/lib/test_queue.rb +1 -5
  24. metadata +7 -44
  25. data/.github/workflows/test.yml +0 -94
  26. data/.gitignore +0 -7
  27. data/Appraisals +0 -43
  28. data/Gemfile +0 -7
  29. data/Rakefile +0 -14
  30. data/gemfiles/cucumber1_3.gemfile +0 -9
  31. data/gemfiles/cucumber2_4.gemfile +0 -9
  32. data/gemfiles/minitest4.gemfile +0 -7
  33. data/gemfiles/minitest5.gemfile +0 -7
  34. data/gemfiles/rspec2.gemfile +0 -8
  35. data/gemfiles/rspec3.gemfile +0 -7
  36. data/gemfiles/rspec4.gemfile +0 -11
  37. data/gemfiles/testunit.gemfile +0 -7
  38. data/script/bootstrap +0 -13
  39. data/spec/stats_spec.rb +0 -79
  40. data/test/cucumber.bats +0 -57
  41. data/test/minitest4.bats +0 -34
  42. data/test/minitest5.bats +0 -194
  43. data/test/rspec2.bats +0 -46
  44. data/test/rspec3.bats +0 -56
  45. data/test/rspec4.bats +0 -56
  46. data/test/samples/features/bad.feature +0 -5
  47. data/test/samples/features/sample.feature +0 -25
  48. data/test/samples/features/sample2.feature +0 -29
  49. data/test/samples/features/step_definitions/common.rb +0 -19
  50. data/test/samples/sample_minispec.rb +0 -37
  51. data/test/samples/sample_minitest4.rb +0 -25
  52. data/test/samples/sample_minitest5.rb +0 -33
  53. data/test/samples/sample_rspec_helper.rb +0 -1
  54. data/test/samples/sample_shared_examples_for_spec.rb +0 -3
  55. data/test/samples/sample_spec.rb +0 -25
  56. data/test/samples/sample_split_spec.rb +0 -17
  57. data/test/samples/sample_testunit.rb +0 -25
  58. data/test/samples/sample_use_shared_example1_spec.rb +0 -7
  59. data/test/samples/sample_use_shared_example2_spec.rb +0 -7
  60. data/test/sleepy_runner.rb +0 -16
  61. data/test/testlib.bash +0 -89
  62. data/test/testunit.bats +0 -20
  63. data/test-queue.gemspec +0 -21
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a84d8eb24f2cdebe31f18be510d2ba28c8633e963beb62e498ef32674df3f761
4
- data.tar.gz: 9869e95d639d312876faa0264b238ee8702ec21f5e5bc0bfe0d149ea1d83df31
3
+ metadata.gz: b99d05b99bd64f0b8efb578d5641077984fae57a6cef805f3ed92beb0fadb56b
4
+ data.tar.gz: dec70c7bef1dd759350333fa913ee780494dab07575342baa9e6545a9808c42a
5
5
  SHA512:
6
- metadata.gz: 7a33f1567709b2fda5670cac096733d0ab1e029fe4db18aec6e1a449b00dd919e979167febe5a249b875d28e536224f0680dfb9810f2b585ea6064fcdb500dcf
7
- data.tar.gz: 2486c1c8a85b4fe9fbe87eb98b7aa76ea97e01951f7e66d6db64e91dae57f8692f8354d036a7d57c342a46ab2833c6aac9fb7263b138fdb802d6993765a2e9b4
6
+ metadata.gz: 8ac80e29b3b5f7ac78db7f4167a8d75de63e3e5295f00139182257b99991003abd801f38c9c216310ab21566fba1ac216585c3621204d59df1a58f917e2cbf30
7
+ data.tar.gz: caf10f2498bd05f890dad0cc4feb45c5b0d2824d4ef3a3a00c9e1255fdbdf777437eee4ea9a4543752125c90f5cea7361778bec0b1eb64527ce895bdea93ec5b
data/README.md CHANGED
@@ -10,46 +10,16 @@ Specifically optimized for CI environments: build statistics from each run
10
10
  are stored locally and used to sort the queue at the beginning of the
11
11
  next run.
12
12
 
13
- ## Design
14
-
15
- test-queue uses a simple master + pre-fork worker model. The master
16
- exposes a unix domain socket server which workers use to grab tests off
17
- the queue.
18
-
19
- ```console
20
- ─┬─ 21232 minitest-queue master
21
- ├─── 21571 minitest-queue worker [3] - AuthenticationTest
22
- ├─── 21568 minitest-queue worker [2] - ApiTest
23
- ├─── 21565 minitest-queue worker [1] - UsersControllerTest
24
- └─── 21562 minitest-queue worker [0] - UserTest
25
- ```
26
-
27
- test-queue also has a distributed mode, where additional masters can share
28
- the workload and relay results back to a central master.
29
-
30
- ## Environment variables
31
-
32
- - `TEST_QUEUE_WORKERS`: number of workers to use per master (default: all available cores)
33
- - `TEST_QUEUE_VERBOSE`: show results as they are available (default: `0`)
34
- - `TEST_QUEUE_SOCKET`: unix socket `path` (or tcp `address:port` pair) used for communication (default: `/tmp/test_queue_XXXXX.sock`)
35
- - `TEST_QUEUE_RELAY`: relay results back to a central master, specified as tcp `address:port`
36
- - `TEST_QUEUE_STATS`: `path` to cache build stats in-build CI runs (default: `.test_queue_stats`)
37
- - `TEST_QUEUE_FORCE`: comma separated list of suites to run
38
- - `TEST_QUEUE_RELAY_TIMEOUT`: when using distributed builds, the amount of time a remote master will try to reconnect to start work
39
- - `TEST_QUEUE_RELAY_TOKEN`: when using distributed builds, this must be the same on remote masters and the central master for remote masters to be able to connect.
40
- - `TEST_QUEUE_REMOTE_MASTER_MESSAGE`: when using distributed builds, set this on a remote master and it will appear in that master's connection message on the central master.
41
- - `TEST_QUEUE_SPLIT_GROUPS`: split tests up by example rather than example group. Faster for tests with short setup time such as selenium. RSpec only. Add the :no_split tag to ExampleGroups you don't want split.
42
-
43
13
  ## Usage
44
14
 
45
- test-queue bundles `testunit-queue`, `minitest-queue` and `rspec-queue` binaries which can be used directly:
15
+ test-queue bundles `testunit-queue`, `minitest-queue`, and `rspec-queue` binaries which can be used directly:
46
16
 
47
17
  ```console
48
18
  $ minitest-queue $(find test/ -name \*_test.rb)
49
19
  $ rspec-queue --format progress spec
50
20
  ```
51
21
 
52
- But the underlying `TestQueue::Runner::TestUnit`, `TestQueue::Runner::MiniTest` and `TestQueue::Runner::RSpec` are
22
+ But the underlying `TestQueue::Runner::TestUnit`, `TestQueue::Runner::Minitest`, and `TestQueue::Runner::RSpec` are
53
23
  built to be subclassed by your application. I recommend checking a new
54
24
  executable into your project using one of these superclasses.
55
25
 
@@ -66,19 +36,19 @@ runner to reset any global state.
66
36
  ``` ruby
67
37
  #!/usr/bin/env ruby
68
38
 
69
- class MyAppTestRunner < TestQueue::Runner::MiniTest
39
+ class MyAppTestRunner < TestQueue::Runner::Minitest
70
40
  def after_fork(num)
71
- # use separate mysql database (we assume it exists and has the right schema already)
41
+ # Use separate mysql database (we assume it exists and has the right schema already)
72
42
  ActiveRecord::Base.configurations.configs_for(env_name: 'test', name: 'primary').database << num.to_s
73
43
  ActiveRecord::Base.establish_connection(:test)
74
44
 
75
- # use separate redis database
45
+ # Use separate redis database
76
46
  $redis.client.db = num
77
47
  $redis.client.reconnect
78
48
  end
79
49
 
80
50
  def prepare(concurrency)
81
- # create mysql databases exists with correct schema
51
+ # Create mysql databases exists with correct schema
82
52
  concurrency.times do |i|
83
53
  # ...
84
54
  end
@@ -97,22 +67,52 @@ end
97
67
  MyAppTestRunner.new.execute
98
68
  ```
99
69
 
70
+ ## Environment variables
71
+
72
+ - `TEST_QUEUE_WORKERS`: Number of workers to use per master (default: all available cores)
73
+ - `TEST_QUEUE_VERBOSE`: Show results as they are available (default: `0`)
74
+ - `TEST_QUEUE_SOCKET`: Unix socket `path` (or TCP `address:port` pair) used for communication (default: `/tmp/test_queue_XXXXX.sock`)
75
+ - `TEST_QUEUE_RELAY`: Relay results back to a central master, specified as TCP `address:port`
76
+ - `TEST_QUEUE_STATS`: `path` to cache build stats in-build CI runs (default: `.test_queue_stats`)
77
+ - `TEST_QUEUE_FORCE`: Comma separated list of suites to run
78
+ - `TEST_QUEUE_RELAY_TIMEOUT`: When using distributed builds, the amount of time a remote master will try to reconnect to start work
79
+ - `TEST_QUEUE_RELAY_TOKEN`: When using distributed builds, this must be the same on remote masters and the central master for remote masters to be able to connect.
80
+ - `TEST_QUEUE_REMOTE_MASTER_MESSAGE`: When using distributed builds, set this on a remote master and it will appear in that master's connection message on the central master.
81
+ - `TEST_QUEUE_SPLIT_GROUPS`: Split tests up by example rather than example group. Faster for tests with short setup time such as selenium. RSpec only. Add the `:no_split` tag to `ExampleGroups` you don't want split.
82
+
83
+ ## Design
84
+
85
+ test-queue uses a simple master + pre-fork worker model. The master
86
+ exposes a Unix domain socket server which workers use to grab tests off
87
+ the queue.
88
+
89
+ ```console
90
+ ─┬─ 21232 minitest-queue master
91
+ ├─── 21571 minitest-queue worker [3] - AuthenticationTest
92
+ ├─── 21568 minitest-queue worker [2] - ApiTest
93
+ ├─── 21565 minitest-queue worker [1] - UsersControllerTest
94
+ └─── 21562 minitest-queue worker [0] - UserTest
95
+ ```
96
+
97
+ test-queue also has a distributed mode, where additional masters can share
98
+ the workload and relay results back to a central master.
99
+
100
100
  ## Distributed mode
101
101
 
102
- To use distributed mode, the central master must listen on a tcp port. Additional masters can be booted
102
+ To use distributed mode, the central master must listen on a TCP port. Additional masters can be booted
103
103
  in relay mode to connect to the central master. Remote masters must provide a `TEST_QUEUE_RELAY_TOKEN`
104
104
  to match the central master's.
105
105
 
106
106
  ```console
107
- $ TEST_QUEUE_RELAY_TOKEN=123 TEST_QUEUE_SOCKET=0.0.0.0:12345 bundle exec minitest-queue ./test/sample_test.rb
108
- $ TEST_QUEUE_RELAY_TOKEN=123 TEST_QUEUE_RELAY=0.0.0.0:12345 bundle exec minitest-queue ./test/sample_test.rb
107
+ $ TEST_QUEUE_RELAY_TOKEN=123 TEST_QUEUE_SOCKET=0.0.0.0:12345 bundle exec minitest-queue ./test/example_test.rb
108
+ $ TEST_QUEUE_RELAY_TOKEN=123 TEST_QUEUE_RELAY=0.0.0.0:12345 bundle exec minitest-queue ./test/example_test.rb
109
109
  $ TEST_QUEUE_RELAY_TOKEN=123 ./test-multi.sh
110
110
  ```
111
111
 
112
112
  See the [Parameterized Trigger Plugin](https://wiki.jenkins-ci.org/display/JENKINS/Parameterized+Trigger+Plugin)
113
- for a simple way to do this with jenkins.
113
+ for a simple way to do this with Jenkins.
114
114
 
115
115
  ## See also
116
116
 
117
- * https://github.com/Shopify/rails_parallel
118
- * https://github.com/grosser/parallel_tests
117
+ - https://github.com/Shopify/rails_parallel
118
+ - https://github.com/grosser/parallel_tests
data/exe/cucumber-queue CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
4
+ $LOAD_PATH.unshift File.expand_path('../lib', __dir__)
4
5
 
5
6
  require 'test_queue'
6
7
  require 'test_queue/runner/cucumber'
data/exe/minitest-queue CHANGED
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
4
+ $LOAD_PATH.unshift File.expand_path('../lib', __dir__)
4
5
 
5
6
  require 'test_queue'
6
7
  require 'test_queue/runner/minitest'
7
8
 
8
- TestQueue::Runner::MiniTest.new.execute
9
+ TestQueue::Runner::Minitest.new.execute
data/exe/rspec-queue CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
4
+ $LOAD_PATH.unshift File.expand_path('../lib', __dir__)
4
5
 
5
6
  require 'test_queue'
6
7
  require 'test_queue/runner/rspec'
data/exe/testunit-queue CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
4
+ $LOAD_PATH.unshift File.expand_path('../lib', __dir__)
4
5
 
5
6
  require 'test_queue'
6
7
  require 'test_queue/runner/testunit'
data/lib/test-queue.rb CHANGED
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'test_queue'
@@ -1,8 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module TestQueue
2
4
  class Iterator
5
+ include Enumerable
6
+
3
7
  attr_reader :sock
4
8
 
5
- def initialize(test_framework, sock, filter=nil, run_token:, early_failure_limit: nil)
9
+ def initialize(test_framework, sock, filter = nil, run_token:, early_failure_limit: nil)
6
10
  @test_framework = test_framework
7
11
  @done = false
8
12
  @suite_stats = []
@@ -18,29 +22,34 @@ module TestQueue
18
22
  end
19
23
 
20
24
  def each
21
- fail "already used this iterator. previous caller: #@done" if @done
25
+ raise "already used this iterator. previous caller: #{@done}" if @done
22
26
 
23
27
  procline = $0
24
28
 
25
- while true
29
+ loop do
26
30
  # If we've hit too many failures in one worker, assume the entire
27
31
  # test suite is broken, and notify master so the run
28
32
  # can be immediately halted.
29
33
  if @early_failure_limit && @failures >= @early_failure_limit
30
- connect_to_master("KABOOM")
34
+ connect_to_master('KABOOM')
31
35
  break
32
36
  else
33
37
  client = connect_to_master("POP #{Socket.gethostname} #{Process.pid}")
34
38
  end
35
39
  break if client.nil?
40
+
41
+ # rubocop:disable Lint/IncompatibleIoSelectWithFiberScheduler
42
+ # This false positive will be resolved by https://github.com/rubocop/rubocop/pull/11830.
36
43
  _r, _w, e = IO.select([client], nil, [client], nil)
37
- break if !e.empty?
44
+ # rubocop:enable Lint/IncompatibleIoSelectWithFiberScheduler
45
+ break unless e.empty?
38
46
 
39
- if data = client.read(65536)
47
+ if (data = client.read(65536))
40
48
  client.close
41
49
  item = Marshal.load(data)
42
50
  break if item.nil? || item.empty?
43
- if item == "WAIT"
51
+
52
+ if item == 'WAIT'
44
53
  $0 = "#{procline} - Waiting for work"
45
54
  sleep 0.1
46
55
  next
@@ -54,7 +63,7 @@ module TestQueue
54
63
  $0 = "#{procline} - #{suite.respond_to?(:description) ? suite.description : suite}"
55
64
  start = Time.now
56
65
  if @filter
57
- @filter.call(suite){ yield suite }
66
+ @filter.call(suite) { yield suite }
58
67
  else
59
68
  yield suite
60
69
  end
@@ -65,10 +74,11 @@ module TestQueue
65
74
  end
66
75
  end
67
76
  rescue Errno::ENOENT, Errno::ECONNRESET, Errno::ECONNREFUSED
77
+ # noop
68
78
  ensure
69
79
  $0 = procline
70
- @done = caller.first
71
- File.open("/tmp/test_queue_worker_#{$$}_suites", "wb") do |f|
80
+ @done = caller(1..1).first
81
+ File.open("/tmp/test_queue_worker_#{$$}_suites", 'wb') do |f|
72
82
  Marshal.dump(@suite_stats, f)
73
83
  end
74
84
  end
@@ -87,8 +97,6 @@ module TestQueue
87
97
  nil
88
98
  end
89
99
 
90
- include Enumerable
91
-
92
100
  def empty?
93
101
  false
94
102
  end
@@ -98,8 +106,8 @@ module TestQueue
98
106
  suite = @loaded_suites[suite_name]
99
107
  return suite if suite
100
108
 
101
- @test_framework.suites_from_file(path).each do |name, suite|
102
- @loaded_suites[name] = suite
109
+ @test_framework.suites_from_file(path).each do |name, suite_from_file|
110
+ @loaded_suites[name] = suite_from_file
103
111
  end
104
112
  @loaded_suites[suite_name]
105
113
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'cucumber'
2
4
  require 'cucumber/rspec/disable_option_parser'
3
5
  require 'cucumber/cli/main'
@@ -24,6 +26,7 @@ module Cucumber
24
26
  module InjectableFeatures
25
27
  def features
26
28
  return @features if defined?(@features)
29
+
27
30
  super
28
31
  end
29
32
 
@@ -1,11 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../../test_queue'
2
4
  require_relative '../runner'
3
5
 
4
6
  module TestQueue
5
7
  class Runner
6
- class Sample < Runner
8
+ class Example < Runner
9
+ def initialize(args)
10
+ super(TestFramework::Example.new(args))
11
+ end
12
+
7
13
  def spawn_workers
8
- puts "Spawning #@concurrency workers"
14
+ puts "Spawning #{@concurrency} workers"
9
15
  super
10
16
  end
11
17
 
@@ -15,24 +21,40 @@ module TestQueue
15
21
  end
16
22
 
17
23
  def run_worker(iterator)
18
- sum = 0
19
- iterator.each do |item|
24
+ iterator.inject(0) do |sum, item|
20
25
  puts " #{item.inspect}"
21
- sum += item
26
+ sum + item.to_i
22
27
  end
23
- sum
24
28
  end
25
29
 
26
30
  def summarize_worker(worker)
27
- worker.summary = worker.output.scan(/^\s*(\d+)/).join(', ')
31
+ worker.summary = worker.output.scan(/^\s*(\d+)/).join(', ')
28
32
  worker.failure_output = ''
29
33
  end
30
34
  end
31
35
  end
36
+
37
+ class TestFramework
38
+ class Example < TestFramework
39
+ def initialize(args)
40
+ super()
41
+
42
+ @args = args.map(&:to_s)
43
+ end
44
+
45
+ def all_suite_files
46
+ @args
47
+ end
48
+
49
+ def suites_from_file(_path)
50
+ @args.map { |i| [i, i] }
51
+ end
52
+ end
53
+ end
32
54
  end
33
55
 
34
56
  if __FILE__ == $0
35
- TestQueue::Runner::Sample.new(Array(1..10)).execute
57
+ TestQueue::Runner::Example.new(Array(1..10)).execute
36
58
  end
37
59
 
38
60
  __END__
@@ -71,4 +93,3 @@ Spawning 4 workers
71
93
  [3] in 0.0036s (pid 40409 exit 0)
72
94
  [2] 3, 6, 9 in 0.0038s (pid 40408 exit 18)
73
95
  [0] 1, 4, 7, 10 in 0.0044s (pid 40406 exit 22)
74
-
@@ -1,17 +1,19 @@
1
+ # frozen_string_literal: true
2
+
1
3
  begin
2
4
  require 'minitest'
3
5
  require_relative '../runner/minitest5'
4
- rescue LoadError => e
6
+ rescue LoadError
5
7
  require 'minitest/unit'
6
8
  require_relative '../runner/minitest4'
7
9
  end
8
10
 
9
11
  module TestQueue
10
12
  class Runner
11
- class MiniTest < Runner
13
+ class Minitest < Runner
12
14
  def summarize_worker(worker)
13
15
  worker.summary = worker.lines.grep(/, \d+ errors?, /).first
14
- failures = worker.lines.select{ |line|
16
+ failures = worker.lines.select { |line|
15
17
  line if (line =~ /^Finished/) ... (line =~ /, \d+ errors?, /)
16
18
  }[1..-2]
17
19
  worker.failure_output = failures.join("\n") if failures
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../runner'
2
4
  require 'set'
3
5
  require 'stringio'
@@ -31,11 +33,11 @@ class MiniTestQueueRunner < MiniTest::Unit
31
33
  ret = super
32
34
  diff = Time.now - start
33
35
 
34
- output.puts(" <%.3f>" % diff)
36
+ output.puts(' <%.3f>' % diff)
35
37
  ret
36
38
  end
37
39
 
38
- self.runner = self.new
40
+ self.runner = new
39
41
  self.output = StringIO.new
40
42
  end
41
43
 
@@ -44,7 +46,7 @@ class MiniTest::Unit::TestCase
44
46
  attr_accessor :test_suites
45
47
 
46
48
  def original_test_suites
47
- @@test_suites.keys.reject{ |s| s.test_methods.empty? }
49
+ @@test_suites.keys.reject { |s| s.test_methods.empty? }
48
50
  end
49
51
  end
50
52
 
@@ -55,12 +57,13 @@ end
55
57
 
56
58
  module TestQueue
57
59
  class Runner
58
- class MiniTest < Runner
60
+ class Minitest < Runner
59
61
  def initialize
60
62
  if ::MiniTest::Unit::TestCase.original_test_suites.any?
61
- fail "Do not `require` test files. Pass them via ARGV instead and they will be required as needed."
63
+ raise 'Do not `require` test files. Pass them via ARGV instead and they will be required as needed.'
62
64
  end
63
- super(TestFramework::MiniTest.new)
65
+
66
+ super(TestFramework::Minitest.new)
64
67
  end
65
68
 
66
69
  def run_worker(iterator)
@@ -68,10 +71,11 @@ module TestQueue
68
71
  ::MiniTest::Unit.new.run
69
72
  end
70
73
  end
74
+ MiniTest = Minitest # For compatibility with test-queue 0.7.0 and earlier.
71
75
  end
72
76
 
73
77
  class TestFramework
74
- class MiniTest < TestFramework
78
+ class Minitest < TestFramework
75
79
  def all_suite_files
76
80
  ARGV
77
81
  end
@@ -84,5 +88,6 @@ module TestQueue
84
88
  }
85
89
  end
86
90
  end
91
+ MiniTest = Minitest # For compatibility with test-queue 0.7.0 and earlier.
87
92
  end
88
93
  end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../runner'
2
4
 
3
- module MiniTest
4
- def self.__run reporter, options
5
+ module Minitest
6
+ def self.__run(reporter, options)
5
7
  suites = Runnable.runnables
6
8
  suites.map { |suite| suite.run reporter, options }
7
9
  end
@@ -13,7 +15,7 @@ module MiniTest
13
15
  end
14
16
 
15
17
  class Test
16
- def self.runnables= runnables
18
+ def self.runnables=(runnables)
17
19
  @@runnables = runnables
18
20
  end
19
21
 
@@ -25,17 +27,19 @@ module MiniTest
25
27
  # code, there's no way to know which are parallel and which are serial.
26
28
  # Synchronizing serial tests does add some overhead, but hopefully this is
27
29
  # outweighed by the speed benefits of using test-queue.
28
- def _synchronize; Test.io_lock.synchronize { yield }; end
30
+ def _synchronize
31
+ Test.io_lock.synchronize { yield }
32
+ end
29
33
  end
30
34
 
31
35
  class ProgressReporter
32
36
  # Override original method to make test-queue specific output
33
- def record result
37
+ def record(result)
34
38
  io.print ' '
35
39
  io.print result.class
36
40
  io.print ': '
37
41
  io.print result.result_code
38
- io.puts(" <%.3f>" % result.time)
42
+ io.puts(' <%.3f>' % result.time)
39
43
  end
40
44
  end
41
45
 
@@ -44,51 +48,62 @@ module MiniTest
44
48
 
45
49
  class << self
46
50
  private
47
- def total_count(options)
51
+
52
+ def total_count(_options)
48
53
  0
49
54
  end
50
55
  end
51
56
  rescue LoadError
57
+ # noop
52
58
  end
53
59
  end
54
60
 
55
61
  module TestQueue
56
62
  class Runner
57
- class MiniTest < Runner
63
+ class Minitest < Runner
58
64
  def initialize
59
- options = Minitest.process_args ARGV
65
+ @options = ::Minitest.process_args ARGV
60
66
 
61
- if Minitest.respond_to?(:seed)
62
- Minitest.seed = options[:seed]
63
- srand Minitest.seed
67
+ if ::Minitest.respond_to?(:seed)
68
+ ::Minitest.seed = @options[:seed]
69
+ srand ::Minitest.seed
64
70
  end
65
71
 
66
- if ::MiniTest::Test.runnables.any? { |r| r.runnable_methods.any? }
67
- fail "Do not `require` test files. Pass them via ARGV instead and they will be required as needed."
72
+ if ::Minitest::Test.runnables.any? { |r| r.runnable_methods.any? }
73
+ raise 'Do not `require` test files. Pass them via ARGV instead and they will be required as needed.'
68
74
  end
69
- super(TestFramework::MiniTest.new)
75
+
76
+ super(TestFramework::Minitest.new)
77
+ end
78
+
79
+ def start_master
80
+ puts "Run options: #{@options[:args]}\n\n"
81
+
82
+ super
70
83
  end
71
84
 
72
85
  def run_worker(iterator)
73
- ::MiniTest::Test.runnables = iterator
74
- ::MiniTest.run ? 0 : 1
86
+ ::Minitest::Test.runnables = iterator
87
+ ::Minitest.run ? 0 : 1
75
88
  end
76
89
  end
90
+ MiniTest = Minitest # For compatibility with test-queue 0.7.0 and earlier.
77
91
  end
78
92
 
79
93
  class TestFramework
80
- class MiniTest < TestFramework
94
+ class Minitest < TestFramework
81
95
  def all_suite_files
82
96
  ARGV
83
97
  end
84
98
 
85
99
  def suites_from_file(path)
86
- ::MiniTest::Test.reset
100
+ ::Minitest::Test.reset
87
101
  require File.absolute_path(path)
88
- ::MiniTest::Test.runnables
89
- .reject { |s| s.runnable_methods.empty? }
90
- .map { |s| [s.name, s] }
102
+ ::Minitest::Test.runnables
103
+ .reject { |s| s.runnable_methods.empty? }
104
+ .map { |s| [s.name, s] }
91
105
  end
92
106
  end
107
+ MiniTest = Minitest # For compatibility with test-queue 0.7.0 and earlier.
93
108
  end
94
109
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../../test_queue'
2
4
  require 'puppet-lint'
3
5
 
@@ -6,7 +8,7 @@ module TestQueue
6
8
  class PuppetLint < Runner
7
9
  def run_worker(iterator)
8
10
  errors = 0
9
- linter = PuppetLint.new
11
+ linter = PuppetLint.new
10
12
  iterator.each do |file|
11
13
  puts "Evaluating #{file}"
12
14
  linter.file = file
@@ -19,9 +21,9 @@ module TestQueue
19
21
  def summarize_worker(worker)
20
22
  lines = worker.lines
21
23
 
22
- files = lines.select{ |line| line =~ /^Evaluating/ }
23
- errors = lines.select{ |line| line =~ /^ERROR/ }
24
- warnings = lines.select{ |line| line =~ /^WARNING/ }
24
+ files = lines.grep(/^Evaluating/)
25
+ errors = lines.grep(/^ERROR/)
26
+ warnings = lines.grep(/^WARNING/)
25
27
 
26
28
  worker.summary = "#{files.size} files, #{warnings.size} warnings, #{errors.size} errors"
27
29
  worker.failure_output = errors.join("\n")
@@ -1,13 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../runner'
2
4
  require 'rspec/core'
3
5
 
4
- case ::RSpec::Core::Version::STRING.to_i
6
+ case RSpec::Core::Version::STRING.to_i
5
7
  when 2
6
8
  require_relative 'rspec2'
7
9
  when 3, 4
8
10
  require_relative 'rspec3'
9
11
  else
10
- fail 'requires rspec version 2, 3, or 4'
12
+ raise 'requires rspec version 2, 3, or 4'
11
13
  end
12
14
 
13
15
  module TestQueue
@@ -23,7 +25,7 @@ module TestQueue
23
25
  end
24
26
 
25
27
  def summarize_worker(worker)
26
- worker.summary = worker.lines.grep(/ examples?, /).first
28
+ worker.summary = worker.lines.grep(/ examples?, /).first
27
29
  worker.failure_output = worker.output[/^Failures:\n\n(.*)\n^Finished/m, 1]
28
30
  end
29
31
  end
@@ -31,6 +33,14 @@ module TestQueue
31
33
 
32
34
  class TestFramework
33
35
  class RSpec < TestFramework
36
+ begin
37
+ require 'turnip/rspec'
38
+
39
+ include Turnip::RSpec::Loader
40
+ rescue LoadError
41
+ # noop
42
+ end
43
+
34
44
  def all_suite_files
35
45
  options = ::RSpec::Core::ConfigurationOptions.new(ARGV)
36
46
  options.parse_options if options.respond_to?(:parse_options)
@@ -77,6 +87,7 @@ module TestQueue
77
87
 
78
88
  def split_groups?
79
89
  return @split_groups if defined?(@split_groups)
90
+
80
91
  @split_groups = ENV['TEST_QUEUE_SPLIT_GROUPS'] && ENV['TEST_QUEUE_SPLIT_GROUPS'].strip.downcase == 'true'
81
92
  end
82
93
  end