Skip to content

Instantly share code, notes, and snippets.

@palexander
Last active December 30, 2015 05:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save palexander/7780189 to your computer and use it in GitHub Desktop.
Save palexander/7780189 to your computer and use it in GitHub Desktop.
namespace :docker do
desc "Run tasks in parallel using docker"
task :test do
forks = 4
begin
# Start docker containers (serially, docker seems to have problems with concurrency)
ports = {}
forks.times do |i|
# Start redis and get the mapped port
`docker run -d -p 6379 -name redis#{i} yourdockeruser/redis`
ports["redis#{i}"] = `docker port redis#{i} 6379`.split(":").last.to_i
# Start solr and get the mapped port
`docker run -d -p 8983 -name solr#{i} yourdockeruser/solr`
ports["solr#{i}"] = `docker port solr#{i} 8983`.split(":").last.to_i
end
# Wait for services in the docker container to start
sleep(15)
# Randomize which forks get which tests
test_files = FileList['test/**/test*.rb'].shuffle
# Slice the test files to evenly distribute amongst forks
test_files_sliced = test_files.each_slice(test_files.length / forks).to_a
pids = []
forks.times do |i|
pids << fork do
begin
##
# Configure your environment
# You'll want to do something here to make the environment
# use the redis_port and solr_port variables from above.
# This may be calling something like Rails::Initializer.run().
# You can access the ports by using the ports hash:
# config.redis_port = ports["redis#{i}"]
# If you use a base test class, require that first
require_relative "test/test_case"
# Require the test files for this particular fork
test_files_sliced[i].each {|f| require_relative f}
# redirect stdout
require 'stringio'
sio = StringIO.new
$stdout = sio
$stderr = sio
# Run the tests
MiniTest::Unit.runner.run
rescue => e
sio << "\n#{e.message}\n#{e.backtrace.join("\t\n")}"
ensure
# reset stdout
$stdout = STDOUT
sio.rewind
# Output the test results
puts "Fork #{i} completed, output:"
puts "Testing:\n#{test_files_sliced[i].join(", ")}\n"
puts sio.read
# Force the fork to end without running at_exit bindings
Kernel.exit!
end
end
end
# Wait for the forks to finish the tests
pids.each {|pid| Process.wait(pid)}
rescue Exception => e
puts e.message
puts e.backtrace.join("\n\t")
ensure
puts "Stopping docker containers"
forks.times {|i| `docker kill redis#{i} && docker rm redis#{i}`}
forks.times {|i| `docker kill solr#{i} && docker rm solr#{i}`}
Kernel.exit! # force the process to quit without minitest's autorun (triggered on at_exit)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment