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.

comments powered by Disqus