test-queue 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) 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 +23 -15
  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 +15 -4
  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 +93 -103
  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 -42
  25. data/.github/workflows/test.yml +0 -93
  26. data/.gitignore +0 -6
  27. data/Appraisals +0 -35
  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/testunit.gemfile +0 -7
  37. data/script/bootstrap +0 -13
  38. data/spec/stats_spec.rb +0 -79
  39. data/test/cucumber.bats +0 -57
  40. data/test/minitest4.bats +0 -34
  41. data/test/minitest5.bats +0 -194
  42. data/test/rspec2.bats +0 -46
  43. data/test/rspec3.bats +0 -56
  44. data/test/samples/features/bad.feature +0 -5
  45. data/test/samples/features/sample.feature +0 -25
  46. data/test/samples/features/sample2.feature +0 -29
  47. data/test/samples/features/step_definitions/common.rb +0 -19
  48. data/test/samples/sample_minispec.rb +0 -37
  49. data/test/samples/sample_minitest4.rb +0 -25
  50. data/test/samples/sample_minitest5.rb +0 -33
  51. data/test/samples/sample_rspec_helper.rb +0 -1
  52. data/test/samples/sample_shared_examples_for_spec.rb +0 -5
  53. data/test/samples/sample_spec.rb +0 -25
  54. data/test/samples/sample_split_spec.rb +0 -17
  55. data/test/samples/sample_testunit.rb +0 -25
  56. data/test/samples/sample_use_shared_example1_spec.rb +0 -8
  57. data/test/samples/sample_use_shared_example2_spec.rb +0 -8
  58. data/test/sleepy_runner.rb +0 -16
  59. data/test/testlib.bash +0 -89
  60. data/test/testunit.bats +0 -20
  61. data/test-queue.gemspec +0 -21
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f689a4cffa234a32b4e3919fe2f263258cd32682925c29d59e26fdd0a8218236
4
- data.tar.gz: 5e2f51214fa2dfcc184386fc588767f7ce15ac9738de0a3c8a730aed33995669
3
+ metadata.gz: b99d05b99bd64f0b8efb578d5641077984fae57a6cef805f3ed92beb0fadb56b
4
+ data.tar.gz: dec70c7bef1dd759350333fa913ee780494dab07575342baa9e6545a9808c42a
5
5
  SHA512:
6
- metadata.gz: 1f76dbac0466294ffca4a780f7c411611cba1c55006a22343bdc11d789e400b135d4457c889d591498ede4ec92dd12ce615239f3569667b061117729e2e61fbc
7
- data.tar.gz: a9666ce78f35e7d1a4cf3f877782ef86b7909396fb12f27c6df883f483ff07907db6b3a9ced68c2f36eae55b2d3f28c9ed3699df3b4ed9a1fc9151b9147306a8
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,14 +1,18 @@
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 = []
9
13
  @sock = sock
10
14
  @filter = filter
11
- if @sock =~ /^(.+):(\d+)$/
15
+ if @sock =~ /\A(.+):(\d+)\z/
12
16
  @tcp_address = $1
13
17
  @tcp_port = $2.to_i
14
18
  end
@@ -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
- when 3
9
+ when 3, 4
8
10
  require_relative 'rspec3'
9
11
  else
10
- fail 'requires rspec version 2 or 3'
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