Skip to content

Instantly share code, notes, and snippets.

@ymendel
Created August 22, 2008 20:35
Show Gist options
  • Save ymendel/6850 to your computer and use it in GitHub Desktop.
Save ymendel/6850 to your computer and use it in GitHub Desktop.
require 'autotest/redgreen'
require 'autotest/timestamp'
USE_FSEVENTS = false
Autotest.send(:alias_method, :real_find_files, :find_files)
Autotest.send(:define_method, :find_files) do |*args|
pattern = ENV['AUTOTEST']
files = real_find_files
if pattern and !pattern.empty?
files = files.reject { |k, v| !Regexp.new(pattern).match(k) }
end
files
end
TEST_THRESHOLD = 10
RATIO_THRESHOLD = 0.5
module Autotest::Growl
def self.growl title, msg, img, pri=0, sticky=""
system "growlnotify -n autotest --image #{img} -p #{pri} -m #{msg.inspect} #{title} #{sticky}"
end
Autotest.add_hook :ran_command do |at|
image_root = File.expand_path('~/.autotest_images')
results = [at.results].flatten.join("\n")
output = results.slice(/(\d+)\stests?,\s(\d+)\sassertions?,\s(\d+)\sfailures?,\s(\d+)\serrors?/)
if output
tests = {}
tests[:total] = $~[1].to_i
tests[:bad] = $~[3].to_i + $~[4].to_i
if tests[:bad] > 0
message = 'FAIL'
image = 'fail'
if tests[:bad] >= TEST_THRESHOLD and (tests[:bad] / tests[:total].to_f) >= RATIO_THRESHOLD
message = 'EPIC FAIL'
image = 'epic_fail' if File.exist?("#{image_root}/current/epic_fail.png")
end
growl message, output, "#{image_root}/current/#{image}.png", 2
else
growl 'WIN', output, "#{image_root}/current/pass.png"
end
end
output = results.slice(/(\d+)\sexamples?,\s(\d+)\sfailures?(?:,\s+(\d+)\s+pending)?/)
if output
tests = {}
tests[:examples] = $~[1].to_i
tests[:bad] = $~[2].to_i
tests[:pending] = $~[3].to_i
tests[:running] = tests[:examples] - tests[:pending]
if tests[:bad] > 0
message = 'FAIL'
image = 'fail'
if tests[:bad] >= TEST_THRESHOLD and (tests[:bad] / tests[:running].to_f) >= RATIO_THRESHOLD
message = 'EPIC FAIL'
image = 'epic_fail' if File.exist?("#{image_root}/current/epic_fail.png")
end
growl message, output, "#{image_root}/current/#{image}.png", 2
elsif tests[:pending] > 0
image = 'pending'
message = 'Pending'
if tests[:pending] >= TEST_THRESHOLD and (tests[:pending] / tests[:examples].to_f) >= RATIO_THRESHOLD
message = 'Get to work!'
image = 'slacker' if File.exist?("#{image_root}/current/slacker.png")
end
growl message, output, "#{image_root}/current/#{image}.png"
else
growl 'WIN', output, "#{image_root}/current/pass.png"
end
end
end
end
if USE_FSEVENTS
begin
require 'osx/foundation'
class Autotest
def run
hook :run
reset
run_tests
OSX.require_framework '/System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework'
callback = proc do |stream, ctx, numEvents, paths, marks, eventIDs|
paths.regard_as('*')
rpaths = []
numEvents.times { |i| rpaths << paths[i] }
run_tests_in_paths(*rpaths)
end
allocator = OSX::KCFAllocatorDefault
context = nil
path = [Dir.pwd]
sinceWhen = OSX::KFSEventStreamEventIdSinceNow
latency = 1.0
flags = 0
stream = OSX::FSEventStreamCreate(allocator, callback, context, path, sinceWhen, latency, flags)
unless stream
puts "Failed to create stream"
exit
end
OSX::FSEventStreamScheduleWithRunLoop(stream, OSX::CFRunLoopGetCurrent(), OSX::KCFRunLoopDefaultMode)
unless OSX::FSEventStreamStart(stream)
puts "Failed to start stream"
exit
end
OSX::CFRunLoopRun()
rescue Interrupt
OSX::FSEventStreamStop(stream)
OSX::FSEventStreamInvalidate(stream)
OSX::FSEventStreamRelease(stream)
end
def find_files_in_paths(*paths)
current_dir = Dir.pwd
result = {}
paths.each do |path|
# Largely copied from autotest
Find.find path do |f|
Find.prune if @exceptions and f =~ @exceptions and test ?d, f
next if test ?d, f
next if f =~ /(swp|~|rej|orig)$/
next if f =~ /\/\.?#/
filename = f[(Dir.pwd.length + 1)..-1]
result[filename] = File.stat(filename).mtime rescue next
end
end
return result
end
def run_tests_in_paths(*paths)
find_files_to_test(find_files_in_paths(*paths))
return if @files_to_test.empty?
# Copied from autotest
cmd = make_test_cmd @files_to_test
hook :run_command
puts cmd
old_sync = $stdout.sync
$stdout.sync = true
@results = []
line = []
begin
open("| #{cmd}", "r") do |f|
until f.eof? do
c = f.getc
putc c
line << c
if c == ?\n then
@results << line.pack("c*")
line.clear
end
end
end
ensure
$stdout.sync = old_sync
end
hook :ran_command
@results = @results.join
handle_results(@results)
end
end
Autotest.send(:alias_method, :real_find_files_in_paths, :find_files_in_paths)
Autotest.send(:define_method, :find_files_in_paths) do |*args|
real_find_filesin_paths(*args).reject do |k, v|
if (ENV['AUTOTEST'] and !ENV['AUTOTEST'].empty?)
!Regexp.new(ENV['AUTOTEST']).match(k)
end
end
end
rescue LoadError => e
puts "Failed to use FSEvents instead of polling files"
p e
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment