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.
- checksums.yaml +4 -4
- data/README.md +42 -42
- data/exe/cucumber-queue +2 -1
- data/exe/minitest-queue +3 -2
- data/exe/rspec-queue +2 -1
- data/exe/testunit-queue +2 -1
- data/lib/test-queue.rb +2 -0
- data/lib/test_queue/iterator.rb +22 -14
- data/lib/test_queue/runner/cucumber.rb +3 -0
- data/lib/test_queue/runner/{sample.rb → example.rb} +30 -9
- data/lib/test_queue/runner/minitest.rb +5 -3
- data/lib/test_queue/runner/minitest4.rb +12 -7
- data/lib/test_queue/runner/minitest5.rb +37 -22
- data/lib/test_queue/runner/puppet_lint.rb +6 -4
- data/lib/test_queue/runner/rspec.rb +14 -3
- data/lib/test_queue/runner/rspec2.rb +24 -24
- data/lib/test_queue/runner/rspec3.rb +11 -11
- data/lib/test_queue/runner/testunit.rb +6 -3
- data/lib/test_queue/runner.rb +87 -97
- data/lib/test_queue/stats.rb +17 -13
- data/lib/test_queue/test_framework.rb +2 -0
- data/lib/test_queue/version.rb +5 -0
- data/lib/test_queue.rb +1 -5
- metadata +7 -44
- data/.github/workflows/test.yml +0 -94
- data/.gitignore +0 -7
- data/Appraisals +0 -43
- data/Gemfile +0 -7
- data/Rakefile +0 -14
- data/gemfiles/cucumber1_3.gemfile +0 -9
- data/gemfiles/cucumber2_4.gemfile +0 -9
- data/gemfiles/minitest4.gemfile +0 -7
- data/gemfiles/minitest5.gemfile +0 -7
- data/gemfiles/rspec2.gemfile +0 -8
- data/gemfiles/rspec3.gemfile +0 -7
- data/gemfiles/rspec4.gemfile +0 -11
- data/gemfiles/testunit.gemfile +0 -7
- data/script/bootstrap +0 -13
- data/spec/stats_spec.rb +0 -79
- data/test/cucumber.bats +0 -57
- data/test/minitest4.bats +0 -34
- data/test/minitest5.bats +0 -194
- data/test/rspec2.bats +0 -46
- data/test/rspec3.bats +0 -56
- data/test/rspec4.bats +0 -56
- data/test/samples/features/bad.feature +0 -5
- data/test/samples/features/sample.feature +0 -25
- data/test/samples/features/sample2.feature +0 -29
- data/test/samples/features/step_definitions/common.rb +0 -19
- data/test/samples/sample_minispec.rb +0 -37
- data/test/samples/sample_minitest4.rb +0 -25
- data/test/samples/sample_minitest5.rb +0 -33
- data/test/samples/sample_rspec_helper.rb +0 -1
- data/test/samples/sample_shared_examples_for_spec.rb +0 -3
- data/test/samples/sample_spec.rb +0 -25
- data/test/samples/sample_split_spec.rb +0 -17
- data/test/samples/sample_testunit.rb +0 -25
- data/test/samples/sample_use_shared_example1_spec.rb +0 -7
- data/test/samples/sample_use_shared_example2_spec.rb +0 -7
- data/test/sleepy_runner.rb +0 -16
- data/test/testlib.bash +0 -89
- data/test/testunit.bats +0 -20
- data/test-queue.gemspec +0 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b99d05b99bd64f0b8efb578d5641077984fae57a6cef805f3ed92beb0fadb56b
|
4
|
+
data.tar.gz: dec70c7bef1dd759350333fa913ee780494dab07575342baa9e6545a9808c42a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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::
|
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::
|
39
|
+
class MyAppTestRunner < TestQueue::Runner::Minitest
|
70
40
|
def after_fork(num)
|
71
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
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/
|
108
|
-
$ TEST_QUEUE_RELAY_TOKEN=123 TEST_QUEUE_RELAY=0.0.0.0:12345 bundle exec minitest-queue ./test/
|
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
|
113
|
+
for a simple way to do this with Jenkins.
|
114
114
|
|
115
115
|
## See also
|
116
116
|
|
117
|
-
|
118
|
-
|
117
|
+
- https://github.com/Shopify/rails_parallel
|
118
|
+
- https://github.com/grosser/parallel_tests
|
data/exe/cucumber-queue
CHANGED
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(
|
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::
|
9
|
+
TestQueue::Runner::Minitest.new.execute
|
data/exe/rspec-queue
CHANGED
data/exe/testunit-queue
CHANGED
data/lib/test-queue.rb
CHANGED
data/lib/test_queue/iterator.rb
CHANGED
@@ -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
|
-
|
25
|
+
raise "already used this iterator. previous caller: #{@done}" if @done
|
22
26
|
|
23
27
|
procline = $0
|
24
28
|
|
25
|
-
|
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(
|
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
|
-
|
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
|
-
|
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",
|
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,
|
102
|
-
@loaded_suites[name] =
|
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
|
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
|
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
|
19
|
-
iterator.each do |item|
|
24
|
+
iterator.inject(0) do |sum, item|
|
20
25
|
puts " #{item.inspect}"
|
21
|
-
sum
|
26
|
+
sum + item.to_i
|
22
27
|
end
|
23
|
-
sum
|
24
28
|
end
|
25
29
|
|
26
30
|
def summarize_worker(worker)
|
27
|
-
worker.summary
|
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::
|
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
|
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
|
13
|
+
class Minitest < Runner
|
12
14
|
def summarize_worker(worker)
|
13
15
|
worker.summary = worker.lines.grep(/, \d+ errors?, /).first
|
14
|
-
failures
|
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(
|
36
|
+
output.puts(' <%.3f>' % diff)
|
35
37
|
ret
|
36
38
|
end
|
37
39
|
|
38
|
-
self.runner =
|
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
|
60
|
+
class Minitest < Runner
|
59
61
|
def initialize
|
60
62
|
if ::MiniTest::Unit::TestCase.original_test_suites.any?
|
61
|
-
|
63
|
+
raise 'Do not `require` test files. Pass them via ARGV instead and they will be required as needed.'
|
62
64
|
end
|
63
|
-
|
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
|
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
|
4
|
-
def self.__run
|
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=
|
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
|
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
|
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(
|
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
|
-
|
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
|
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 ::
|
67
|
-
|
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
|
-
|
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
|
-
::
|
74
|
-
::
|
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
|
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
|
-
::
|
100
|
+
::Minitest::Test.reset
|
87
101
|
require File.absolute_path(path)
|
88
|
-
::
|
89
|
-
|
90
|
-
|
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 =
|
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.
|
23
|
-
errors = lines.
|
24
|
-
warnings = lines.
|
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
|
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
|
-
|
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
|
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
|