Skip to content

Flexibility Showcase

kenoir edited this page Sep 18, 2012 · 13 revisions

This project was born out of a need for greater continuous testing flexibility than autotest could provide. The following showcases some alternative testing needs that watchr makes possible, as well as uses beyond testing.

Continuous Testing

Autotest is an amazing library that brought continuous testing to the ruby community. It is opinionated, though, which in some circumstances can become problematic. For example, it reacts to saving this project’s test/test_watchr.rb with:

  /usr/bin/ruby1.8 -I.:lib:test -rubygems -e "%w[test/unit test/test_watchr.rb].each { |f| require f }"

locking the environment into ruby1.8, rubygems and test/unit. It’s easy to see why watchr doesn’t have any of these restrictions, since the whole command is custom. The gem you’re working on runs minitest on ruby1.9, and you use rip? Easy:

  watch( 'test/test_.*\.rb' ) {|md| system("/usr/bin/ruby1.9 #{md[0]}") }

Or you use spec/ as your test dir?

  watch( 'spec/.*_spec\.rb' ) {|md| system("ruby -I.:lib:spec #{md[0]}") }

Maybe the project you’re working on doesn’t load rubygems internally (which is good practice), but you still use it locally yourself:

 watch( 'test/test_.*\.rb' ) {|md| system("ruby -rubygems #{md[0]}") }

Continuous Documenting

watchr is generic enough to allow uses other than running specs. One such use is keeping your project’s documentation up to date, similar to livelydocs:

  def run_rdoc
    system('rake --silent rdoc')
  end

  watch( '(lib|bin)/.*\.rb' ) { run_rdoc }
  watch( 'README' )           { run_rdoc }

Assuming the script is stored in rdocs.watchr, run with

  $ watchr rdocs.watchr

and your documentation will be updated whenever you save a ruby file in lib/ or bin/, or the README.

Continuous Building

How about building your gem every time you modify the gemspec file?

  def build(gemspec)
    system "gem build #{gemspec}"
    FileUtils.mv Dir['gemname-*.gem'], 'pkg/'
    puts
  end

  watch( '^gemname.gemspec$' ) { |m| build m[0] }

And run

  $ watchr gem.watchr

Pure Ruby

Watchr scripts are pure ruby, so it’s possible to add various custom enhancements. For instance, extracting common code into methods, or trapping a signal.

  def all_test_files
    Dir['test/**/test_*.rb'] - ['test/test_helper.rb']
  end

  def run_all_tests
    system("ruby -rubygems -I.:lib:test -e'%w( #{all_test_files.join(' ')} ).each {|file| require file }'")
  end

# Ctrl-\
Signal.trap('QUIT') do
  puts " --- Running all tests ---\n\n"
  run_all_tests
end

# Ctrl-C
Signal.trap('INT') { abort("\n") }

Use in a ruby script

Non-blocking

require 'watchr'
script = Watchr::Script.new
script.watch('foo') { puts 'bar' } # doesn't block

Blocking

require 'watchr'
script = Watchr::Script.new  
script.watch('foo') { puts 'bar' } 
handler = Watchr.handler.new;
controller = Watchr::Controller.new(script,handler);
controller.run # does block!