Created
February 9, 2012 02:29
-
-
Save jrun/1776613 to your computer and use it in GitHub Desktop.
Hack up guard-minitest to support sub-projects.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'guard' | |
require 'guard/guard' | |
module Guard | |
# This MiniTest guard is a hacked up version of guard-minitest | |
# which supports guards scoped by sub-directories. Think one | |
# Guardfile at the root of rails which has a minitest guard for | |
# each (active|action)* project. | |
# | |
# ## Example Guardfile | |
# | |
# guard 'multiminitest', root: 'a' do | |
# watch %r|^test/(.*)test_(.*)\.rb| | |
# end | |
# | |
# guard 'multiminitest', root: 'b' do | |
# watch %r|^test/(.*)test_(.*)\.rb| | |
# end | |
# | |
class MultiMiniTest < Guard | |
class Inspector | |
def initialize(root = nil) | |
@root = root || Dir.pwd | |
end | |
def clean(paths) | |
cleaned = paths.uniq | |
cleaned.compact! | |
Dir.chdir @root do | |
cleaned.map! &method(:strip_root) | |
cleaned.keep_if &method(:test_path?) | |
cleaned.map! &method(:expand_test_path) | |
cleaned.flatten! | |
clear_test_files | |
cleaned | |
end | |
end | |
private | |
def test_path?(path) | |
test_file?(path) || test_directory?(path) | |
end | |
def test_file?(path) | |
test_files.include?(path) | |
end | |
def test_directory?(path) | |
path.match(/^\/?test/) && !path.match(/\..+$/) && File.directory?(path) | |
end | |
def test_files | |
@test_files ||= Dir.glob('test/**/{test_*,*_test}.rb') | |
end | |
def strip_root(path) | |
path.split("#{@root}/").last | |
end | |
def expand_test_path(path) | |
File.directory?(path) ? Dir.glob("#{path}/**/{test_*,*_test}.rb") : path | |
end | |
def clear_test_files | |
@test_files = nil | |
end | |
end | |
def start | |
prepend_root_to_watchers | |
true | |
end | |
def stop | |
true | |
end | |
def reload | |
true | |
end | |
def run_all | |
run_on_change ['test'] | |
end | |
def run_on_change(paths = []) | |
cleaned = clean_paths paths | |
UI.info "\nRunning: %s" % cleaned.join(' '), reset: true | |
cleaned.empty? ? true : run_minitest(cleaned) | |
end | |
private | |
def run_minitest(paths) | |
cmd_parts = ['ruby'] | |
cmd_parts << "-C#{root}" if root | |
cmd_parts << "-I#{rubylib}" | |
cmd_parts.concat paths.map {|path| "-r ./#{path}" } | |
cmd_parts << '-e "MiniTest::Unit.autorun"' | |
cmd_parts << '--' | |
if seed = options[:seed] | |
cmd_parts << "--seed #{seed}" | |
end | |
if verbose = options[:verbose] | |
cmd_parts << '--verbose' | |
end | |
system cmd_parts.join(' ') | |
end | |
def root | |
options[:root] | |
end | |
def clean_paths(paths) | |
(@inspector ||= Inspector.new root).clean paths | |
end | |
# When set, prepend root to the watcher regular expression. | |
# | |
# This hack sucks but after digging into Guard this appears | |
# to be the "best" solution which avoids all sorts of | |
# monkey patching. | |
# | |
# Append root to the regexp. Note the insert index of 1 | |
# which assumes the regexp starts with ^. Yeah, that's | |
# lame just like the rest of this hack. This exercise | |
# has been time boxed and it serves the purpose for now. | |
# | |
# If there is a better way please let me know. Thank you. | |
def prepend_root_to_watchers | |
return unless root | |
watchers.each do |watcher| | |
watcher.pattern = Regexp.compile watcher.pattern.source.insert(1, "#{root}/") | |
end | |
end | |
# The RUBYLIB to use for test runs. | |
# | |
# Use RUBYLIB (no, not bundler) to add local libraries to | |
# the load path. When the sub-project has a .rubylib file | |
# add it's contents to RUBYLIB along with the standard | |
# test:lib. | |
# | |
# NOTE: It's debatable whether or not this belongs here. | |
def rubylib | |
@rubylib ||= begin | |
rblib = 'test:lib' | |
if root | |
dot_rblib = File.join root, '.rubylib' | |
rblib << ':' << File.read(dot_rblib).chomp if File.exist?(dot_rblib) | |
end | |
rblib | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment