maxim (owner)

Revisions

gist: 133425 Download_button fork
public
Public Clone URL: git://gist.github.com/133425.git
tester_elf.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#!/usr/bin/env ruby
 
# tester_elf simply autoruns a ruby test file when you save it.
# As dumb as it gets, but sometimes convenient.
#
# Usage:
# 1) Place it in your "script" dir
# 2) chmod +x script/tester_elf
# 3) script/tester_elf
# Stop using Ctrl/Cmd + C
#
# Based on restarter script by Jonathan Penn (http://www.wavethenavel.com).
# Tweaked around by Maxim Chernyak (http://mediumexposure.com)
 
POLL_DIRECTORIES = %w(test/unit test/functional)
POLL_TIME = 0.9
RUN_WITH = "ruby -Itest"
 
class TesterElf
  def initialize(options = {})
    @dirs = options[:dirs] || %w(test/unit test/functional)
    @interval = options[:interval] || 0.9
    @command = options[:command] || 'ruby -Itest'
    @states = {}
  end
  
  def work!
    Dir.chdir(File.join(File.dirname(__FILE__), '..'))
    $stderr.puts "Tester Elf is at your service... Checking files in #{@dirs.join(', ')} every #{@interval} seconds."
    
    processes = []
    Signal.trap(0) do
      processes.map{|p| Process.kill("INT", p)}
    end
    
    Signal.trap("INT") do
      $stderr.puts "Shutting down tester_elf"
      exit
    end
    
    check_for_changes
    
    loop do
      sleep @interval
      changes = check_for_changes
      unless changes.empty?
        $stderr.puts emphasized("Running test...#{changes.inspect}")
        processes.map{|p| Process.kill("INT", p)}
        processes = changes.collect do |path|
          fork { exec("#{@command} #{path}") }
        end
      end
    end
  end
  
  
  private
  def emphasized(m)
    "\e[1;1m\e[41m \e[0m \e[1;1m\e[1m #{m} \e[0m"
  end
  
  def check_for_changes
    changes = []
    Dir[*@dirs.map{|i|i+"/**/*"}].each do |file|
      unless File.symlink?(file)
        new_time = File.stat(file).mtime
        if @states[file] != new_time
          @states[file] = new_time
          changes << file
        end
      end
    end
    changes
  end
end
 
elf = TesterElf.new(:dirs => POLL_DIRECTORIES, :interval => POLL_TIME, :command => RUN_WITH)
elf.work!