Skip to content

Instantly share code, notes, and snippets.

@jrun
Created February 9, 2012 02:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jrun/1776613 to your computer and use it in GitHub Desktop.
Save jrun/1776613 to your computer and use it in GitHub Desktop.
Hack up guard-minitest to support sub-projects.
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