Skip to content

Instantly share code, notes, and snippets.

@pmarreck pmarreck/teststack.rb
Last active Dec 19, 2015

Embed
What would you like to do?
TestStack, a cheap zeus-like bit of code to preload your stack for your iterative test running. Based on ideas from Jesse Storimer.
#!/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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.