#!/usr/bin/env ruby # Teststack: A way to preload your Rails app stack for your iterative test running # Based on ideas from Jesse Storimer here: # http://www.jstorimer.com/blogs/workingwithcode/8136295-screencast-faster-rails-test-runs-with-unix # https://gist.github.com/jstorimer/5862436 # Usage: Run this file without args to run the server; run it with test file args to connect to the server and run tests require 'socket' # Monkeypatch IO to make streaming socket IO API nicer... # Based on ideas from http://coderrr.wordpress.com/2008/10/21/when-to-use-readpartial-instead-of-read-in-ruby/ class IO def drain(data = nil) while !self.closed? && buf = readpartial_rescued(1024) data << buf if data && buf yield buf if block_given? end data end private def readpartial_rescued(size) readpartial(size) rescue EOFError nil end end class TestClient def initialize(test_files = ARGV) socket = UNIXSocket.new('.testing.sock') ARGV.each do |test_file| socket.write(test_file + "\n") end socket.close_write socket.drain do |buf| print buf end end end class TestServer def initialize ENV['RAILS_ENV'] = 'test' %w[test lib .].each{ |p| $:.unshift(p) unless $:.include? p } rails_boot = time { require 'config/application' require 'test/test_helper' } puts "Rails, config/application, and test/test_helper loaded after #{'%.2f' % rails_boot}s..." puts "You may now run '#{File.basename __FILE__}' with test file arguments in another terminal window." server = UNIXServer.new('.testing.sock') parent_process_id = Process.pid at_exit { if Process.pid == parent_process_id File.unlink('.testing.sock') end } trap('INT') { exit } loop do client = server.accept test_files = client.read.split("\n") pid = fork do $stdout.reopen(client) test_files.each do |test_file| require test_file $stdout.flush end end Process.wait(pid) client.close end end private def time t = Time.now yield Time.now - t end end if ARGV.empty? TestServer.new else TestClient.new end