Skip to content

Instantly share code, notes, and snippets.

@pmarreck
Last active December 19, 2015 01:48
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pmarreck/5878023 to your computer and use it in GitHub Desktop.
Save pmarreck/5878023 to your computer and use it in GitHub Desktop.
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