Generally, it is a good idea to automate every boring, complicated programming task that often needs to be repeated. Firstly, developer’s time and nerves can be spared. Secondly, the risk of doing something wrong (e.g. making a typo or leaving out one of the steps required) is minimized. Prepare the task once and don’t repeat yourself anymore.
There are many tools available and the choice is determined principally by the language and environment we use. Some of the most well-know tools are make, Ant, Phing and Rake. In this short article, we are going to focus on the last one.
One thing we should do before integrating/releasing/deploying the code is to run automated tests, just to make (almost) sure everything works fine. When writing Ruby application, we can use the cute RSpec framework. Knowing that tests are located in the spec
directory, we can use the spec
command to run them:
$ spec spec/* --format specdoc
It means: “run every test file located in the spec
directory and use the specdoc
output format”. However, if the directory structure looks like following:
+ project
- main.rb
- other.rb
+ spec
- first_spec.rb
- second_spec.rb
+ other
- third_spec.rb
only first_spec.rb
and second_spec.rb
files are going to be run, because the spec
command won’t go through the subdirectories. Perhaps we could cope with this by doing some console magic, but what if we came up with idea of test results email notification? List of desired additional functionalities may grow up in time and the best solution is to use the programming language we are conversant with. And this is where the Ruby hits the road.
Running RSpec tests can be automated using Rake task. Rake directives can be located either in “rakefile”, “Rakefile”, “rakefile.rb” or “Rakefile.rb” file. When called, rake
command looks for one of these files. Let’s write our first Rake task:
require 'rubygems'
require 'spec/rake/spectask'
Spec::Rake::SpecTask.new(:spec) do |t|
t.spec_files = Dir.glob('spec/**/*_spec.rb')
t.spec_opts << '--format specdoc'
t.rcov = true
end
Save it under the “rakefile” name and run by executing the rake spec
command:
$ rake spec
This will cause all tests named *_spec.rb and located in “spec” directory and any of its subdirectories to run. Let’s go through the task line by line now.
At the very beginning, rubygems
are being loaded. They are required if Rake was installed from RubyGems and usually that’s the case. In the second line, Spec::Rake::SpecTask
is being taken into our project. Rake already contains class that makes running RSpec tests easier and we are making use of it.
Then we define our task named spec
(that is why we previously wrote rake spec
in the command line). Nothing crosses our path to call the task whatever we want, like “test”, “check”, or something else.
By setting task’s spec_files
property, we tell Rake which tests to run. Dir.glob('spec/**/spec_*')
call means “list of files located in the spec directory and any of its subdirectories, ending with _spec.rb
”. These files are going to be run.
spec_opts
property contains list of switches that are going to be passed to the spec
command call in the command line. In this case, we set the output format.
The last, rcov
property turns on the rcov code coverage meter. After all tests are done, there would be a HTML code coverage report located in the coverage
directory. Of course, the rcov library must be installed in our system.
Well, in these few steps we crated a very handy Rake task. As we have only one Rake task in our rakefile, we can set the spec
task to be the default one:
require 'rubygems'
require 'spec/rake/spectask'
Spec::Rake::SpecTask.new(:spec) do |t|
t.spec_files = Dir.glob('spec/**/*_spec.rb')
t.spec_opts << '--format specdoc'
t.rcov = true
end
task :default => :spec
That’s it! I hope I encouraged you to take a deeper look at Rake. Good luck in writing your own tasks!
If it was your first contact with Rake, I encourage you to read the Rake tutorial.