test-queue-split 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +3 -0
- data/Gemfile-minitest4 +3 -0
- data/Gemfile-minitest4.lock +38 -0
- data/Gemfile-rspec3-0 +3 -0
- data/Gemfile-rspec3-0.lock +40 -0
- data/Gemfile-rspec3-1 +3 -0
- data/Gemfile-rspec3-1.lock +40 -0
- data/Gemfile-rspec3-2 +3 -0
- data/Gemfile-rspec3-2.lock +41 -0
- data/Gemfile-testunit +3 -0
- data/Gemfile-testunit.lock +44 -0
- data/Gemfile.lock +54 -0
- data/README.md +114 -0
- data/Thorfile +9 -0
- data/bin/cucumber-queue +4 -0
- data/bin/minitest-queue +5 -0
- data/bin/rspec-queue +4 -0
- data/bin/testunit-queue +5 -0
- data/features/bad.feature +5 -0
- data/features/sample.feature +25 -0
- data/features/sample2.feature +29 -0
- data/features/step_definitions/common.rb +15 -0
- data/lib/test-queue.rb +1 -0
- data/lib/test_queue/iterator.rb +72 -0
- data/lib/test_queue/runner/cucumber.rb +46 -0
- data/lib/test_queue/runner/minitest.rb +25 -0
- data/lib/test_queue/runner/minitest4.rb +65 -0
- data/lib/test_queue/runner/minitest5.rb +62 -0
- data/lib/test_queue/runner/puppet_lint.rb +31 -0
- data/lib/test_queue/runner/rspec.rb +35 -0
- data/lib/test_queue/runner/rspec2.rb +35 -0
- data/lib/test_queue/runner/rspec3.rb +45 -0
- data/lib/test_queue/runner/sample.rb +76 -0
- data/lib/test_queue/runner/testunit.rb +56 -0
- data/lib/test_queue/runner.rb +395 -0
- data/lib/test_queue/version.rb +4 -0
- data/lib/test_queue.rb +8 -0
- data/test/sample_minispec.rb +31 -0
- data/test/sample_minitest4.rb +23 -0
- data/test/sample_minitest5.rb +23 -0
- data/test/sample_spec.rb +23 -0
- data/test/sample_testunit.rb +23 -0
- data/test-multi.sh +8 -0
- data/test-queue-split.gemspec +28 -0
- data/test.sh +23 -0
- metadata +141 -0
@@ -0,0 +1,395 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'securerandom'
|
4
|
+
|
5
|
+
module TestQueue
|
6
|
+
class Worker
|
7
|
+
attr_accessor :pid, :status, :output, :stats, :num, :host
|
8
|
+
attr_accessor :start_time, :end_time
|
9
|
+
attr_accessor :summary, :failure_output
|
10
|
+
|
11
|
+
def initialize(pid, num)
|
12
|
+
@pid = pid
|
13
|
+
@num = num
|
14
|
+
@start_time = Time.now
|
15
|
+
@output = ''
|
16
|
+
@stats = {}
|
17
|
+
end
|
18
|
+
|
19
|
+
def lines
|
20
|
+
@output.split("\n")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Runner
|
25
|
+
attr_accessor :concurrency
|
26
|
+
|
27
|
+
def initialize(queue, concurrency=nil, socket=nil, relay=nil)
|
28
|
+
raise ArgumentError, 'array required' unless Array === queue
|
29
|
+
|
30
|
+
if forced = ENV['TEST_QUEUE_FORCE']
|
31
|
+
forced = forced.split(/\s*,\s*/)
|
32
|
+
whitelist = Set.new(forced)
|
33
|
+
queue = queue.select{ |s| whitelist.include?(s.to_s) }
|
34
|
+
queue.sort_by!{ |s| forced.index(s.to_s) }
|
35
|
+
end
|
36
|
+
|
37
|
+
@procline = $0
|
38
|
+
@queue = queue
|
39
|
+
@suites = queue.inject(Hash.new){ |hash, suite| hash.update suite.to_s => suite }
|
40
|
+
|
41
|
+
@workers = {}
|
42
|
+
@completed = []
|
43
|
+
|
44
|
+
@concurrency =
|
45
|
+
concurrency ||
|
46
|
+
(ENV['TEST_QUEUE_WORKERS'] && ENV['TEST_QUEUE_WORKERS'].to_i) ||
|
47
|
+
if File.exists?('/proc/cpuinfo')
|
48
|
+
File.read('/proc/cpuinfo').split("\n").grep(/processor/).size
|
49
|
+
elsif RUBY_PLATFORM =~ /darwin/
|
50
|
+
`/usr/sbin/sysctl -n hw.activecpu`.to_i
|
51
|
+
else
|
52
|
+
2
|
53
|
+
end
|
54
|
+
|
55
|
+
@slave_connection_timeout =
|
56
|
+
(ENV['TEST_QUEUE_RELAY_TIMEOUT'] && ENV['TEST_QUEUE_RELAY_TIMEOUT'].to_i) ||
|
57
|
+
30
|
58
|
+
|
59
|
+
@run_token = ENV['TEST_QUEUE_RELAY_TOKEN'] || SecureRandom.hex(8)
|
60
|
+
|
61
|
+
@socket =
|
62
|
+
socket ||
|
63
|
+
ENV['TEST_QUEUE_SOCKET'] ||
|
64
|
+
"/tmp/test_queue_#{$$}_#{object_id}.sock"
|
65
|
+
|
66
|
+
@relay =
|
67
|
+
relay ||
|
68
|
+
ENV['TEST_QUEUE_RELAY']
|
69
|
+
|
70
|
+
@slave_message = ENV["TEST_QUEUE_SLAVE_MESSAGE"] if ENV.has_key?("TEST_QUEUE_SLAVE_MESSAGE")
|
71
|
+
|
72
|
+
if @relay == @socket
|
73
|
+
STDERR.puts "*** Detected TEST_QUEUE_RELAY == TEST_QUEUE_SOCKET. Disabling relay mode."
|
74
|
+
@relay = nil
|
75
|
+
elsif @relay
|
76
|
+
@queue = []
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def stats
|
81
|
+
@stats ||=
|
82
|
+
if File.exists?(file = stats_file)
|
83
|
+
Marshal.load(IO.binread(file)) || {}
|
84
|
+
else
|
85
|
+
{}
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def execute
|
90
|
+
$stdout.sync = $stderr.sync = true
|
91
|
+
@start_time = Time.now
|
92
|
+
|
93
|
+
@concurrency > 0 ?
|
94
|
+
execute_parallel :
|
95
|
+
execute_sequential
|
96
|
+
ensure
|
97
|
+
summarize_internal unless $!
|
98
|
+
end
|
99
|
+
|
100
|
+
def summarize_internal
|
101
|
+
puts
|
102
|
+
puts "==> Summary (#{@completed.size} workers in %.4fs)" % (Time.now-@start_time)
|
103
|
+
puts
|
104
|
+
|
105
|
+
@failures = ''
|
106
|
+
@completed.each do |worker|
|
107
|
+
summarize_worker(worker)
|
108
|
+
@failures << worker.failure_output if worker.failure_output
|
109
|
+
|
110
|
+
puts " [%2d] %60s %4d suites in %.4fs (pid %d exit %d%s)" % [
|
111
|
+
worker.num,
|
112
|
+
worker.summary,
|
113
|
+
worker.stats.size,
|
114
|
+
worker.end_time - worker.start_time,
|
115
|
+
worker.pid,
|
116
|
+
worker.status.exitstatus,
|
117
|
+
worker.host && " on #{worker.host.split('.').first}"
|
118
|
+
]
|
119
|
+
end
|
120
|
+
|
121
|
+
unless @failures.empty?
|
122
|
+
puts
|
123
|
+
puts "==> Failures"
|
124
|
+
puts
|
125
|
+
puts @failures
|
126
|
+
end
|
127
|
+
|
128
|
+
puts
|
129
|
+
|
130
|
+
if @stats
|
131
|
+
File.open(stats_file, 'wb') do |f|
|
132
|
+
f.write Marshal.dump(stats)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
summarize
|
137
|
+
|
138
|
+
estatus = @completed.inject(0){ |s, worker| s + worker.status.exitstatus }
|
139
|
+
estatus = 255 if estatus > 255
|
140
|
+
exit!(estatus)
|
141
|
+
end
|
142
|
+
|
143
|
+
def summarize
|
144
|
+
end
|
145
|
+
|
146
|
+
def stats_file
|
147
|
+
ENV['TEST_QUEUE_STATS'] ||
|
148
|
+
'.test_queue_stats'
|
149
|
+
end
|
150
|
+
|
151
|
+
def execute_sequential
|
152
|
+
exit! run_worker(@queue)
|
153
|
+
end
|
154
|
+
|
155
|
+
def execute_parallel
|
156
|
+
start_master
|
157
|
+
prepare(@concurrency)
|
158
|
+
@prepared_time = Time.now
|
159
|
+
start_relay if relay?
|
160
|
+
spawn_workers
|
161
|
+
distribute_queue
|
162
|
+
ensure
|
163
|
+
stop_master
|
164
|
+
|
165
|
+
@workers.each do |pid, worker|
|
166
|
+
Process.kill 'KILL', pid
|
167
|
+
end
|
168
|
+
|
169
|
+
until @workers.empty?
|
170
|
+
reap_worker
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def start_master
|
175
|
+
if !relay?
|
176
|
+
if @socket =~ /^(?:(.+):)?(\d+)$/
|
177
|
+
address = $1 || '0.0.0.0'
|
178
|
+
port = $2.to_i
|
179
|
+
@socket = "#$1:#$2"
|
180
|
+
@server = TCPServer.new(address, port)
|
181
|
+
else
|
182
|
+
FileUtils.rm(@socket) if File.exists?(@socket)
|
183
|
+
@server = UNIXServer.new(@socket)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
desc = "test-queue master (#{relay?? "relaying to #{@relay}" : @socket})"
|
188
|
+
puts "Starting #{desc}"
|
189
|
+
$0 = "#{desc} - #{@procline}"
|
190
|
+
end
|
191
|
+
|
192
|
+
def start_relay
|
193
|
+
return unless relay?
|
194
|
+
|
195
|
+
sock = connect_to_relay
|
196
|
+
message = @slave_message ? " #{@slave_message}" : ""
|
197
|
+
message.gsub!(/(\r|\n)/, "") # Our "protocol" is newline-separated
|
198
|
+
sock.puts("SLAVE #{@concurrency} #{Socket.gethostname} #{@run_token}#{message}")
|
199
|
+
response = sock.gets.strip
|
200
|
+
unless response == "OK"
|
201
|
+
STDERR.puts "*** Got non-OK response from master: #{response}"
|
202
|
+
sock.close
|
203
|
+
exit! 1
|
204
|
+
end
|
205
|
+
sock.close
|
206
|
+
rescue Errno::ECONNREFUSED
|
207
|
+
STDERR.puts "*** Unable to connect to relay #{@relay}. Aborting.."
|
208
|
+
exit! 1
|
209
|
+
end
|
210
|
+
|
211
|
+
def stop_master
|
212
|
+
return if relay?
|
213
|
+
|
214
|
+
FileUtils.rm_f(@socket) if @socket && @server.is_a?(UNIXServer)
|
215
|
+
@server.close rescue nil if @server
|
216
|
+
@socket = @server = nil
|
217
|
+
end
|
218
|
+
|
219
|
+
def spawn_workers
|
220
|
+
@concurrency.times do |i|
|
221
|
+
num = i+1
|
222
|
+
|
223
|
+
pid = fork do
|
224
|
+
@server.close if @server
|
225
|
+
|
226
|
+
iterator = Iterator.new(relay?? @relay : @socket, @suites, method(:around_filter))
|
227
|
+
after_fork_internal(num, iterator)
|
228
|
+
ret = run_worker(iterator) || 0
|
229
|
+
cleanup_worker
|
230
|
+
Kernel.exit! ret
|
231
|
+
end
|
232
|
+
|
233
|
+
@workers[pid] = Worker.new(pid, num)
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
def after_fork_internal(num, iterator)
|
238
|
+
srand
|
239
|
+
|
240
|
+
output = File.open("/tmp/test_queue_worker_#{$$}_output", 'w')
|
241
|
+
|
242
|
+
$stdout.reopen(output)
|
243
|
+
$stderr.reopen($stdout)
|
244
|
+
$stdout.sync = $stderr.sync = true
|
245
|
+
|
246
|
+
$0 = "test-queue worker [#{num}]"
|
247
|
+
puts
|
248
|
+
puts "==> Starting #$0 (#{Process.pid} on #{Socket.gethostname}) - iterating over #{iterator.sock}"
|
249
|
+
puts
|
250
|
+
|
251
|
+
after_fork(num)
|
252
|
+
end
|
253
|
+
|
254
|
+
# Run in the master before the fork. Used to create
|
255
|
+
# concurrency copies of any databases required by the
|
256
|
+
# test workers.
|
257
|
+
def prepare(concurrency)
|
258
|
+
end
|
259
|
+
|
260
|
+
def around_filter(suite)
|
261
|
+
yield
|
262
|
+
end
|
263
|
+
|
264
|
+
# Prepare a worker for executing jobs after a fork.
|
265
|
+
def after_fork(num)
|
266
|
+
end
|
267
|
+
|
268
|
+
# Entry point for internal runner implementations. The iterator will yield
|
269
|
+
# jobs from the shared queue on the master.
|
270
|
+
#
|
271
|
+
# Returns nothing. exits 0 on success.
|
272
|
+
# exits N on error, where N is the number of failures.
|
273
|
+
def run_worker(iterator)
|
274
|
+
iterator.each do |item|
|
275
|
+
puts " #{item.inspect}"
|
276
|
+
end
|
277
|
+
|
278
|
+
return 0 # exit status
|
279
|
+
end
|
280
|
+
|
281
|
+
def cleanup_worker
|
282
|
+
end
|
283
|
+
|
284
|
+
def summarize_worker(worker)
|
285
|
+
worker.summary = ''
|
286
|
+
worker.failure_output = ''
|
287
|
+
end
|
288
|
+
|
289
|
+
def reap_worker(blocking=true)
|
290
|
+
if pid = Process.waitpid(-1, blocking ? 0 : Process::WNOHANG) and worker = @workers.delete(pid)
|
291
|
+
worker.status = $?
|
292
|
+
worker.end_time = Time.now
|
293
|
+
|
294
|
+
if File.exists?(file = "/tmp/test_queue_worker_#{pid}_output")
|
295
|
+
worker.output = IO.binread(file)
|
296
|
+
FileUtils.rm(file)
|
297
|
+
end
|
298
|
+
|
299
|
+
if File.exists?(file = "/tmp/test_queue_worker_#{pid}_stats")
|
300
|
+
worker.stats = Marshal.load(IO.binread(file))
|
301
|
+
FileUtils.rm(file)
|
302
|
+
end
|
303
|
+
|
304
|
+
relay_to_master(worker) if relay?
|
305
|
+
worker_completed(worker)
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
def worker_completed(worker)
|
310
|
+
@completed << worker
|
311
|
+
puts worker.output if ENV['TEST_QUEUE_VERBOSE'] || worker.status.exitstatus != 0
|
312
|
+
end
|
313
|
+
|
314
|
+
def distribute_queue
|
315
|
+
return if relay?
|
316
|
+
remote_workers = 0
|
317
|
+
|
318
|
+
until @queue.empty? && remote_workers == 0
|
319
|
+
if IO.select([@server], nil, nil, 0.1).nil?
|
320
|
+
reap_worker(false) if @workers.any? # check for worker deaths
|
321
|
+
else
|
322
|
+
sock = @server.accept
|
323
|
+
cmd = sock.gets.strip
|
324
|
+
case cmd
|
325
|
+
when /^POP/
|
326
|
+
# If we have a slave from a different test run, don't respond, and it will consider the test run done.
|
327
|
+
if obj = @queue.shift
|
328
|
+
data = Marshal.dump(obj.to_s)
|
329
|
+
sock.write(data)
|
330
|
+
end
|
331
|
+
when /^SLAVE (\d+) ([\w\.-]+) (\w+)(?: (.+))?/
|
332
|
+
num = $1.to_i
|
333
|
+
slave = $2
|
334
|
+
run_token = $3
|
335
|
+
slave_message = $4
|
336
|
+
if run_token == @run_token
|
337
|
+
# If we have a slave from a different test run, don't respond, and it will consider the test run done.
|
338
|
+
sock.write("OK\n")
|
339
|
+
remote_workers += num
|
340
|
+
else
|
341
|
+
STDERR.puts "*** Worker from run #{run_token} connected to master for run #{@run_token}; ignoring."
|
342
|
+
sock.write("WRONG RUN\n")
|
343
|
+
end
|
344
|
+
message = "*** #{num} workers connected from #{slave} after #{Time.now-@start_time}s"
|
345
|
+
message << " " + slave_message if slave_message
|
346
|
+
STDERR.puts message
|
347
|
+
when /^WORKER (\d+)/
|
348
|
+
data = sock.read($1.to_i)
|
349
|
+
worker = Marshal.load(data)
|
350
|
+
worker_completed(worker)
|
351
|
+
remote_workers -= 1
|
352
|
+
end
|
353
|
+
sock.close
|
354
|
+
end
|
355
|
+
end
|
356
|
+
ensure
|
357
|
+
stop_master
|
358
|
+
|
359
|
+
until @workers.empty?
|
360
|
+
reap_worker
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
def relay?
|
365
|
+
!!@relay
|
366
|
+
end
|
367
|
+
|
368
|
+
def connect_to_relay
|
369
|
+
sock = nil
|
370
|
+
start = Time.now
|
371
|
+
puts "Attempting to connect for #{@slave_connection_timeout}s..."
|
372
|
+
while sock.nil?
|
373
|
+
begin
|
374
|
+
sock = TCPSocket.new(*@relay.split(':'))
|
375
|
+
rescue Errno::ECONNREFUSED => e
|
376
|
+
raise e if Time.now - start > @slave_connection_timeout
|
377
|
+
puts "Master not yet available, sleeping..."
|
378
|
+
sleep 0.5
|
379
|
+
end
|
380
|
+
end
|
381
|
+
sock
|
382
|
+
end
|
383
|
+
|
384
|
+
def relay_to_master(worker)
|
385
|
+
worker.host = Socket.gethostname
|
386
|
+
data = Marshal.dump(worker)
|
387
|
+
|
388
|
+
sock = connect_to_relay
|
389
|
+
sock.puts("WORKER #{data.bytesize}")
|
390
|
+
sock.write(data)
|
391
|
+
ensure
|
392
|
+
sock.close if sock
|
393
|
+
end
|
394
|
+
end
|
395
|
+
end
|
data/lib/test_queue.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'minitest/spec'
|
2
|
+
|
3
|
+
class Meme
|
4
|
+
def i_can_has_cheezburger?
|
5
|
+
"OHAI!"
|
6
|
+
end
|
7
|
+
|
8
|
+
def will_it_blend?
|
9
|
+
"YES!"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe Meme do
|
14
|
+
before do
|
15
|
+
@meme = Meme.new
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "when asked about cheeseburgers" do
|
19
|
+
it "must respond positively" do
|
20
|
+
sleep 0.1
|
21
|
+
@meme.i_can_has_cheezburger?.must_equal "OHAI!"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "when asked about blending possibilities" do
|
26
|
+
it "won't say no" do
|
27
|
+
sleep 0.1
|
28
|
+
@meme.will_it_blend?.wont_match /^no/i
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'minitest/unit'
|
2
|
+
|
3
|
+
class MiniTestEqual < MiniTest::Unit::TestCase
|
4
|
+
def test_equal
|
5
|
+
assert_equal 1, 1
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
30.times do |i|
|
10
|
+
Object.const_set("MiniTestSleep#{i}", Class.new(MiniTest::Unit::TestCase) do
|
11
|
+
define_method('test_sleep') do
|
12
|
+
start = Time.now
|
13
|
+
sleep(0.25)
|
14
|
+
assert_in_delta Time.now-start, 0.25, 0.02
|
15
|
+
end
|
16
|
+
end)
|
17
|
+
end
|
18
|
+
|
19
|
+
class MiniTestFailure < MiniTest::Unit::TestCase
|
20
|
+
def test_fail
|
21
|
+
assert_equal 0, 1
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
|
3
|
+
class MiniTestEqual < MiniTest::Test
|
4
|
+
def test_equal
|
5
|
+
assert_equal 1, 1
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
30.times do |i|
|
10
|
+
Object.const_set("MiniTestSleep#{i}", Class.new(MiniTest::Test) do
|
11
|
+
define_method('test_sleep') do
|
12
|
+
start = Time.now
|
13
|
+
sleep(0.25)
|
14
|
+
assert_in_delta Time.now-start, 0.25, 0.02
|
15
|
+
end
|
16
|
+
end)
|
17
|
+
end
|
18
|
+
|
19
|
+
class MiniTestFailure < MiniTest::Test
|
20
|
+
def test_fail
|
21
|
+
assert_equal 0, 1
|
22
|
+
end
|
23
|
+
end
|
data/test/sample_spec.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
|
3
|
+
describe 'RSpecEqual' do
|
4
|
+
it 'checks equality' do
|
5
|
+
expect(1).to eq 1
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
30.times do |i|
|
10
|
+
describe "RSpecSleep(#{i})" do
|
11
|
+
it "sleeps" do
|
12
|
+
start = Time.now
|
13
|
+
sleep(0.25)
|
14
|
+
expect(Time.now-start).to be_within(0.02).of(0.25)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'RSpecFailure' do
|
20
|
+
it 'fails' do
|
21
|
+
expect(:foo).to eq :bar
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
class TestUnitEqual < Test::Unit::TestCase
|
4
|
+
def test_equal
|
5
|
+
assert_equal 1, 1
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
30.times do |i|
|
10
|
+
Object.const_set("TestUnitSleep#{i}", Class.new(Test::Unit::TestCase) do
|
11
|
+
define_method('test_sleep') do
|
12
|
+
start = Time.now
|
13
|
+
sleep(0.25)
|
14
|
+
assert_in_delta Time.now-start, 0.25, 0.02
|
15
|
+
end
|
16
|
+
end)
|
17
|
+
end
|
18
|
+
|
19
|
+
class TestUnitFailure < Test::Unit::TestCase
|
20
|
+
def test_fail
|
21
|
+
assert_equal 0, 1
|
22
|
+
end
|
23
|
+
end
|
data/test-multi.sh
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require_relative 'lib/test_queue/version'
|
2
|
+
|
3
|
+
spec = Gem::Specification.new do |s|
|
4
|
+
s.name = 'test-queue-split'
|
5
|
+
s.version = TestQueue::VERSION
|
6
|
+
s.date = TestQueue::DATE
|
7
|
+
s.summary = 'parallel test runner'
|
8
|
+
s.description = 'minitest/rspec parallel test runner for CI environments'
|
9
|
+
|
10
|
+
s.homepage = 'http://github.com/tmm1/test-queue'
|
11
|
+
|
12
|
+
s.authors = ['Aman Gupta']
|
13
|
+
s.email = 'ruby@tmm1.net'
|
14
|
+
s.license = 'MIT'
|
15
|
+
|
16
|
+
s.has_rdoc = false
|
17
|
+
s.bindir = 'bin'
|
18
|
+
s.executables << 'rspec-queue'
|
19
|
+
s.executables << 'minitest-queue'
|
20
|
+
s.executables << 'testunit-queue'
|
21
|
+
s.executables << 'cucumber-queue'
|
22
|
+
|
23
|
+
s.add_development_dependency 'rspec', '>= 2.13', '< 4.0'
|
24
|
+
s.add_development_dependency 'cucumber', '~> 1.3.10'
|
25
|
+
s.add_development_dependency 'appium_thor', '~> 1.0.1'
|
26
|
+
|
27
|
+
s.files = `git ls-files`.split("\n")
|
28
|
+
end
|
data/test.sh
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
set -x
|
3
|
+
|
4
|
+
export TEST_QUEUE_WORKERS=2 TEST_QUEUE_VERBOSE=1
|
5
|
+
|
6
|
+
export BUNDLE_GEMFILE=Gemfile-testunit
|
7
|
+
bundle install
|
8
|
+
bundle exec testunit-queue ./test/*_testunit.rb
|
9
|
+
|
10
|
+
export BUNDLE_GEMFILE=Gemfile-minitest4
|
11
|
+
bundle install
|
12
|
+
bundle exec minitest-queue ./test/*_minitest4.rb
|
13
|
+
bundle exec minitest-queue ./test/*_minispec.rb
|
14
|
+
|
15
|
+
export BUNDLE_GEMFILE=Gemfile
|
16
|
+
bundle install
|
17
|
+
bundle exec minitest-queue ./test/*_minitest4.rb
|
18
|
+
bundle exec minitest-queue ./test/*_minitest5.rb
|
19
|
+
bundle exec minitest-queue ./test/*_minispec.rb
|
20
|
+
bundle exec rspec-queue test
|
21
|
+
bundle exec cucumber-queue
|
22
|
+
|
23
|
+
TEST_QUEUE_WORKERS=1 TEST_QUEUE_FORCE="MiniTestSleep21,MiniTestSleep8,MiniTestFailure" bundle exec minitest-queue ./test/*_minitest5.rb
|