Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

A different approach for Rake integration.

  • Loading branch information...
commit 1543c5b50a872d66902d76a6550dadb667a19262 1 parent 0b3c486
@jbarnette authored
View
55 README.markdown
@@ -37,33 +37,34 @@ If you want to mess with the polling interval:
require "rake/lathertask"
- Rake::LatherTask.new "lib/**/*.rb" do |task|
- task.target = :test # default
- task.globs << "test/**/*_test.rb"
+ Rake::LatherTask.new "lib/**/*.rb" do |l|
+ l.target = :something
+ l.globs << "ext/**/*.{c,h}"
end
This creates a `lather` task, which will call the `target` task any
-time the `globs` change. The block is optional.
+time the `globs` change. The block is optional: `target` defaults to
+`:test`.
-You can also use Lather's replacement for Rake's `TestTask` for even
-nicer integration:
+If `target` is set to an **instance** of `Rake::TestTask`, some
+special behavior is enabled: Lather will add the test task's file list
+to `globs`, and will set the `TEST` environment variable to the list
+of tests that need to be run.
- require "rake/lathertesttask"
-
- Rake::LatherTestTask.new do |test|
-
- # These are the defaults, you don't need to specify 'em.
+ require "rake/testtask"
+ require "rake/lathertask"
- test.files = %w(lib/**/*.rb)
- test.flags = %w(-w)
- test.libs = %w(lib test)
- test.options = { :force => true }
- test.tests = %w(test/**/*_test.rb)
- test.verbose = false
+ test = Rake::TestTask.new do |t|
+ t.libs << "test"
+ t.test_files = "test/**/*_test.rb"
end
-This creates `test` and `test:lather` tasks. The block is
-optional. See Lather's `Rakefile` for a working example.
+ Rake::LatherTask.new "lib/**/*.rb", :target => test
+
+The heuristic is really simple: If `lib/foo.rb` changes, any test
+whose path contains `foo` will be run. There's no tracking of failures
+or single test runs. If you want more than this, you should be using
+Autotest.
## Installing
@@ -71,28 +72,24 @@ optional. See Lather's `Rakefile` for a working example.
## Hacking
-`rake test:lather` will watch `lib` and `test` and re-run the tests when
-something changes. If you're looking for something to work on, chew on
-these:
+If you're looking for something to work on, chew on these:
- * A way to get at the list of changed files in a `-r` command and
- the Rake tasks.
+ * A way to get at the list of changed files in a `-r` command.
* Some default exclude (like backup/editor files, `.svn`, `.git`)
patterns, and an easy way to add new ones.
- * A `--sleep <secs>` switch for the command-line tool and the Rake
- task.
+ * A `--sleep <secs>` switch for the command-line tool.
## Thanks
Lather owes a huge debt to Ryan Davis' ZenTest library, specifically
-`autotest`. Use it. It'll change your life. See also Mike Clark and
-Geoffrey Grosenbach's `rstakeout`.
+`autotest`. Use it. See also Mike Clark and Geoffrey Grosenbach's
+`rstakeout`.
## License
-Copyright 2009 John Barnette [jbarnette@gmail.com]
+Copyright 2009 John Barnette, Seattle.rb.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
View
16 Rakefile
@@ -2,7 +2,12 @@ require "rubygems/specification"
require "rake/testtask"
require "./lib/lather"
-require "./lib/rake/lathertesttask"
+require "./lib/rake/lathertask"
+
+desc "Straighten up"
+task :clean do
+ rm_rf "*.gem"
+end
namespace :gem do
LATHER = Gem::Specification.new do |s|
@@ -33,13 +38,16 @@ namespace :gem do
end
desc "Build and install the gem"
- task :install => gemfile do
+ task :install => [gemfile, :clean] do
sh "sudo gem install #{LATHER.name}-#{LATHER.version}.gem"
end
end
-Rake::LatherTestTask.new do |test|
- test.flags << "-rhelper"
+test = Rake::TestTask.new do |t|
+ t.libs << "test"
+ t.ruby_opts << "-rhelper"
+ t.test_files = "test/**/*_test.rb"
end
task :default => :test
+Rake::LatherTask.new "lib/**/*.rb", :target => test
View
6 lather.gemspec
@@ -2,16 +2,16 @@
Gem::Specification.new do |s|
s.name = %q{lather}
- s.version = "1.2.1"
+ s.version = "1.3.0"
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["John Barnette"]
- s.date = %q{2009-02-06}
+ s.date = %q{2009-02-08}
s.default_executable = %q{lather}
s.description = %q{Lather rinses and repeats.}
s.email = %q{jbarnette@gmail.com}
s.executables = ["lather"]
- s.files = ["Rakefile", "README.markdown", "bin/lather", "lib/lather", "lib/lather/cli.rb", "lib/lather/version.rb", "lib/lather/watcher.rb", "lib/lather.rb", "lib/rake", "lib/rake/lathertask.rb", "lib/rake/lathertesttask.rb", "test/helper.rb", "test/lather", "test/lather/cli_test.rb", "test/lather/watcher_test.rb"]
+ s.files = ["Rakefile", "README.markdown", "bin/lather", "lib/lather", "lib/lather/cli.rb", "lib/lather/version.rb", "lib/lather/watcher.rb", "lib/lather.rb", "lib/rake", "lib/rake/lathertask.rb", "test/helper.rb", "test/lather", "test/lather/cli_test.rb", "test/lather/watcher_test.rb"]
s.homepage = %q{http://github.com/jbarnette/lather}
s.require_paths = ["lib"]
s.rubygems_version = %q{1.3.1}
View
2  lib/lather/version.rb
@@ -1,3 +1,3 @@
module Lather
- VERSION = "1.2.1"
+ VERSION = "1.3.0"
end
View
77 lib/rake/lathertask.rb
@@ -13,32 +13,91 @@ class LatherTask < TaskLib
attr_accessor :globs
- # The task to run when things change. Default is <tt>:test</tt>.
+ # A hash of options, most of which are passed on to
+ # <tt>Lather::Watcher</tt>.
+
+ attr_accessor :options
+
+ # The task to run when things change. Default is
+ # <tt>:test</tt>. If this is an instance of
+ # <tt>Rake::TestTask</tt>, the task's <tt>pattern</tt> will be
+ # added to <tt>globs</tt>, and the <tt>TEST</tt> environment
+ # variable will be set to a glob of changed tests before each
+ # invocation.
attr_accessor :target
def initialize *globs, &block
- @target = :test
- @globs = globs
+ @options = Hash === globs.last ? globs.pop : {}
+ @globs = globs
+ @target = @options.delete(:target) || :test
+
+ @changed = case @target
+ when Rake::TestTask then handle_rake_test_task
+ else lambda {}
+ end
yield self if block_given?
- desc "Rinse and repeat"
- Rake::Task.define_task :lather do
- watcher = Lather::Watcher.new @globs do
- target = Rake::Task[@target]
+ @target = Rake::Task[@target]
+ desc "Rinse and repeat"
+ task :lather do
+ watcher = Lather::Watcher.new @globs, @options do |changed|
begin
- target.invoke
+ @changed[changed]
+ @target.invoke
rescue StandardError => e
raise e unless e.to_s =~ /^Command failed/
ensure
- target.reenable
+ reenable @target
end
end
watcher.go!
end
end
+
+ # Get and set the block called each time a file matching one of
+ # the <tt>globs</tt> changes. Default is <tt>lambda {}</tt>.
+
+ def changed &block
+ return @changed unless block_given?
+ @changed = block
+ end
+
+ private
+
+ def reenable target
+ target.reenable
+ target.prerequisites.each { |p| reenable Rake::Task[p] }
+ end
+
+ # Special setup when <tt>target</tt> is a <tt>Rake::TestTask</tt>.
+
+ def handle_rake_test_task
+ test_task = @target
+ all_tests = test_task.file_list
+
+ @target = test_task.name
+ @globs << test_task.file_list
+ @options[:force] = true
+
+ @changed = lambda do |changed|
+ tests = all_tests & changed
+
+ basenames = (changed - tests).collect do |f|
+ File.basename(f).split(".").first
+ end
+
+ tests.concat all_tests.
+ select { |t| basenames.any? { |b| t =~ /#{b}/ } }
+
+ tests = all_tests.dup if tests.empty?
+
+ # Nice API, Rake::TestTask.
+ ENV["TEST"] = "{#{tests.uniq.join(',')}}"
+ end
+ end
end
end
View
118 lib/rake/lathertesttask.rb
@@ -1,118 +0,0 @@
-require "rake"
-require "rake/tasklib"
-require "lather/watcher"
-
-module Rake
-
- # A simplified version of <tt>Rake::TestTask</tt> with support for
- # Lather. It creates <tt>test</tt> and <tt>test:lather</tt>
- # tasks. It's more opinionated and less configurable than
- # <tt>Rake::TestTask</tt>: Test file load order is random.
- #
- # When lathering, a very stupid heuristic is used to decide which
- # test files to run: Any test file whose path contains the basename
- # (without extension) of the file that changed. If no test files
- # match, everything gets run. No tracking of failures, no specific
- # tests. If you want more than this, you should be using Autotest.
-
- class LatherTestTask < TaskLib
-
- # An optional array of stuff to tack on to the end of the Ruby
- # command-line. Default is <tt>[]</tt>.
-
- attr_accessor :extras
-
- # An array of glob patterns to match implementation files. Default
- # is <tt>%w(lib/**/*.rb)</tt>.
-
- attr_accessor :files
-
- # An array of command-line flags to pass on to Ruby. Default is
- # <tt>%w(-w)</tt>.
-
- attr_accessor :flags
-
- # An array of directories to add to the load path. Default is
- # <tt>%w(lib test)</tt>.
-
- attr_accessor :libs
-
- # A hash of options to pass on to <tt>Lather::Watcher.new</tt>.
- # Default is <tt>{ :force => true }</tt>.
-
- attr_accessor :options
-
- # An array of glob patterns to match test files. Default is
- # <tt>%w(test/**/*_test.rb)</tt>.
-
- attr_accessor :tests
-
- # Be chatty? Default is <tt>false</tt>.
-
- attr_accessor :verbose
-
- def initialize
- @extras = []
- @files = %w(lib/**/*.rb)
- @flags = %w(-w)
- @libs = %w(lib test)
- @options = { :force => true }
- @tests = %w(test/**/*_test.rb)
- @verbose = false
-
- yield self if block_given?
-
- desc "Run the tests"
- task :test, [:tests] do |task, args|
-
- tests = if args.tests.nil? || args.tests.empty?
- FileList[@tests]
- else
- args.tests
- end
-
- cmd = @flags.dup
- cmd << "-I#{@libs.join(':')}"
- cmd << "-e 'ARGV.each { |f| load f }'"
-
- cmd.concat tests.collect { |f| "'#{f}'" }.sort_by { rand }
- cmd.concat @extras
-
- RakeFileUtils.verbose(@verbose) { ruby cmd.join(" ") }
- end
-
- namespace :test do
- desc "Test, rinse, repeat"
- task :lather do
- watcher = Lather::Watcher.new @files, @tests, @options do |changed|
- all_tests = FileList[@tests]
- tests = all_tests & changed
-
- basenames = (changed - tests).collect do |f|
- File.basename(f).split(".").first
- end
-
- tests.concat all_tests.
- select { |t| basenames.any? { |b| t =~ /#{b}/ } }
-
- task = Rake::Task[:test]
-
- begin
- task.invoke tests.uniq
- rescue StandardError => e
- raise e unless e.to_s =~ /^Command failed/
- ensure
-
- # FIXME: walk the whole tree
-
- task.reenable
- task.prerequisites.each { |p| Rake::Task[p].reenable }
- end
- end
-
- watcher.go!
- end
- end
- end
- end
-end
Please sign in to comment.
Something went wrong with that request. Please try again.