Autotest your rubygem
Last blog post, I have introduced how to use bundler and rvm to build a rubygem, today I will say something about testing a rubygem.
RSpec
RSpec is a Behaviour-Driven Development tool for Ruby programmers. It's an alternative to ruby unit test framework. If you are going to use rspec to test your rubygem, I strongly recommend you to use rspec2, which does a lot of improvement from rspec1. Check more info here: http://relishapp.com/rspec.
I don't want to teach you how to use the rspec, I just give you a short instruction.
- define spec_helper.rb
- write spec tests, one spec file corresponds to one lib file
-
use
rspec SPEC_FILESto test
It would be better to display the test result with color and nested format, just define .rspec file as follows
--format nested
--color
Autotest
It's fine that you type rspec command to test your spec files each time, but the better way is to make tests run automatically. It really saves your time.
autotest is also easy to use, to install it
gem install autotest
If you work on Mac OS X 10.5 or higher, the following two gems are also helpful
gem install autotest-fsevent autotest-growl
autotest-fsevent makes filesystem modification detection more efficient.
autotest-growl sends test results to growl notification.
then define the global autotest configuration in ~/.autotest
# Include plugins
require 'autotest/fsevent'
require 'autotest/growl'
# Skip some paths
Autotest.add_hook :initialize do |autotest|
%w{.git .DS_Store ._* vendor}.each { |exception| autotest.add_exception(exception) }
false
end
and integrate autotest with rspec2, add a file in your rubygem ./autotest/discover.rb
Autotest.add_discovery { "rspec2" }
After that, you can type autotest at the root directory of your rubygem, you will see all the spec files are running and get the test results. The test process is as follows
- You write some codes/specs that make the tests failure.
- Autotest runs that modified specs (or spec according to modified codes) and get failures, then you will see the growl notification who tells you your tests failed.
- You change your codes/specs to fix the failures.
- Autotest runs that modified specs again and get success. then you will see the growl notification who tells you your tests passed.
- Autotest runs all the specs that check if your modification affects other codes/specs, then you will see the growl notification who tells you if your all tests passed or failed.
I'm really glad to play with autotest, but there is a problem if it takes a long time (more than several minutes) to run all the tests. As each time you fix the failures, autotest will run all the specs again for you, that means each time I fix failures, I have to wait a long time which is not I expect.
Watchr
Watchr is a modern continuous testing (flexible alternative to Autotest). The flexible means you can define the test strategy about when to test and test what files. The following is the .watchr example for rails_best_practices gem.
def growl
title = "Watchr Test Results"
image = $?.success? ? "~/.watchr/images/passed.png" : "~/.watchr/images/failed.png"
message = $?.success? ? "success" : "failed"
growlnotify = `which growlnotify`.chomp
options = "-w -n Watchr --image '#{File.expand_path(image)}' -m '#{message}' '#{title}'"
system %(#{growlnotify} #{options} &)
end
def run(cmd)
puts cmd
system(cmd)
end
def spec(file)
if File.exists?(file)
run("rspec #{file}")
growl
else
puts("Spec: #{file} does not exist.")
end
end
def run_all_specs
run "rake spec"
growl
end
def run_suite
system "clear"
run_all_specs
end
watch("spec/.*/*_spec\.rb") do |match|
puts(match[0])
spec(match[0])
end
watch("lib/(.*/.*)\.rb") do |match|
puts(match[1])
spec("spec/#{match[1]}_spec.rb")
end
# Ctrl-\
Signal.trap 'QUIT' do
puts " --- Running all tests ---\n\n"
run_suite
end
# Ctrl-C
Signal.trap 'INT' do
if @interrupted then
abort("\n")
else
puts "Interrupt a second time to quit"
@interrupted = true
Kernel.sleep 1.5
# raise Interrupt, nil # let the run loop catch it
run_suite
@interrupted = false
end
end
What the watchr configuration do are
- watch the codes in lib directory, if any file modifications occur, run the corresponding spec file.
- watch the codes in spec directory, if any file modifications occur, just run the spec file.
- after each spec running, send growl notification.
- type Ctrl + \ to run all tests.
- type Ctrl + C to stop test.
While I'm developing the rails_best_practices gem, I always run watchr .watchr at the terminal, so whenever I changed the codes/specs, I will got a notification from growl, it makes me more efficient to write robust rubygem. I hope it is also helpful to you.
Enjoy autotest for your rubygem!
