Created
December 26, 2010 08:52
-
-
Save paukul/755304 to your computer and use it in GitHub Desktop.
hydra, deeptest and others were a little heavyweight for my needs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ENV['RAILS_ENV'] = "test" | |
require 'test/unit/testsuite' | |
require 'test/unit/collector/objectspace' | |
require 'test/unit/ui/testrunnermediator' | |
require 'test/unit/ui/console/testrunner' | |
require 'test/unit/testresult' | |
require 'config/environment' | |
require 'drb' | |
no_workers = 4 | |
Test::Unit.run = true # avoid running the autorunner | |
# SafeFork taken from hydra: https://github.com/ngauthier/hydra/blob/master/lib/hydra/safe_fork.rb | |
class SafeFork | |
def self.fork | |
begin | |
# remove our connection so it doesn't get cloned | |
connection = ActiveRecord::Base.remove_connection if defined?(ActiveRecord) | |
# fork a process | |
child = Process.fork do | |
begin | |
# create a new connection and perform the action | |
begin | |
ActiveRecord::Base.establish_connection((connection || {}).merge({:allow_concurrency => true})) if defined?(ActiveRecord) | |
rescue ActiveRecord::AdapterNotSpecified | |
# AR was defined but we didn't have a connection | |
end | |
yield | |
ensure | |
# make sure we remove the connection before we're done | |
ActiveRecord::Base.remove_connection if defined?(ActiveRecord) | |
end | |
end | |
ensure | |
# make sure we re-establish the connection before returning to the main instance | |
begin | |
ActiveRecord::Base.establish_connection((connection || {}).merge({:allow_concurrency => true})) if defined?(ActiveRecord) | |
rescue ActiveRecord::AdapterNotSpecified | |
# AR was defined but we didn't have a connection | |
end | |
end | |
return child | |
end | |
end | |
class TestMonitor | |
def initialize | |
@runners = 0 | |
@finished_results = [] | |
@faults = [] | |
@first_testrun = nil | |
end | |
def next_engine | |
engines.pop | |
end | |
def say(something) | |
puts something | |
end | |
def engines | |
@engines ||= begin | |
e = %w(. best_offers core_tools xws) | |
# e = Dir[File.expand_path('../../engines', __FILE__) + "/*"].map{|f| "engines/" + File.basename(f)}.unshift(".") | |
@no_engines = e.size | |
e | |
end | |
end | |
def add_fault(fault) | |
$stdout.print fault.single_character_display | |
@faults << fault | |
# $stdout.flush | |
# $stdout.puts "\n-----------------------------------------" | |
# $stdout.puts fault.long_display | |
# $stdout.puts "-----------------------------------------" | |
end | |
def test_finished(name) | |
$stdout.print "." | |
$stdout.flush | |
end | |
def started | |
@first_testrun ||= Time.new | |
@runners += 1 | |
end | |
def finished(elapsed_time, result) | |
@runners -= 1 | |
@finished_results << result | |
# $stdout.puts "DONE in #{elapsed_time}" | |
if @finished_results.size == @no_engines | |
report_results | |
Thread.exit | |
end | |
end | |
def test_started(name) | |
end | |
def report_results | |
@faults.each do |fault| | |
puts fault.long_display | |
end | |
@finished_results.each do |res| | |
puts res | |
end | |
puts "Complete testrun in: #{Time.now - @first_testrun}" | |
end | |
end | |
class MonitoredRunner | |
include DRbUndumped | |
attr_reader :result | |
def initialize(suite, monitor) | |
@monitor = monitor | |
@suite = suite | |
end | |
def self.run(suite, monitor = TestMonitor.new) | |
new(suite, monitor).start | |
end | |
# Begins the test run. | |
def start | |
setup_mediator | |
attach_to_mediator | |
@mediator.run_suite | |
end | |
private | |
def setup_mediator | |
@mediator = create_mediator(@suite) | |
suite_name = @suite.to_s | |
if ( @suite.kind_of?(Module) ) | |
suite_name = @suite.name | |
end | |
end | |
def create_mediator(suite) | |
Test::Unit::UI::TestRunnerMediator.new(suite) | |
end | |
def attach_to_mediator | |
@mediator.add_listener(Test::Unit::TestResult::FAULT, &method(:add_fault)) | |
@mediator.add_listener(Test::Unit::UI::TestRunnerMediator::STARTED, &method(:started)) | |
@mediator.add_listener(Test::Unit::UI::TestRunnerMediator::FINISHED, &method(:finished)) | |
@mediator.add_listener(Test::Unit::TestCase::STARTED, &method(:test_started)) | |
@mediator.add_listener(Test::Unit::TestCase::FINISHED, &method(:test_finished)) | |
end | |
def add_fault(fault) | |
@monitor.add_fault(fault) | |
end | |
def started(result) | |
@result = result | |
@monitor.started | |
end | |
def finished(elapsed_time) | |
@monitor.finished(elapsed_time, @result) | |
end | |
def test_started(name) | |
@monitor.test_started(name) | |
end | |
def test_finished(name) | |
@monitor.test_finished(name) | |
end | |
end | |
DRb.start_service nil, TestMonitor.new | |
require 'drb/timeridconv' | |
DRb.install_id_conv(DRb::TimerIdConv.new) | |
uri = DRb.uri | |
def fork_me_baby(uri) | |
SafeFork.fork do | |
trap("INT") { } #dunno rly... | |
DRb.start_service | |
monitor = DRbObject.new nil, uri | |
$stdout = open("/dev/null", "w") | |
if e = monitor.next_engine | |
e = e == "." ? e : "engines/#{e}" | |
monitor.say "Loading for #{e}" | |
Dir[File.join(e, "test", "**", "*_test.rb")].each do |f| | |
load f | |
end | |
suite = Test::Unit::Collector::ObjectSpace.new.collect | |
MonitoredRunner.run(suite, monitor) | |
fork_me_baby(uri) | |
end | |
end | |
end | |
no_workers.times { fork_me_baby(uri) } | |
trap("INT") { | |
monitor = DRbObject.new nil, uri | |
monitor.report_results | |
} | |
DRb.thread.join |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment