A voting extension from scratch for Rails 3 (Part 2 – Testing environment)

In the last episode we created the basic structure for the make_voteable gem. With “test first” in mind we now set up our RSpec testing environment for developing the make_voteable gem. We already installed RSpec at the beginning of this blog series. First we need to create a testing folder (named spec) directly under the project root (make_voteable/spec). We also create a file named spec_helper.rb in this spec folder containing the testing configurations.

  1. # spec/spec_helper.rb
  2. require 'rubygems'
  3. require 'bundler'
  4. require 'logger'
  5. require 'rspec'
  6. require 'active_record'
  7. require 'database_cleaner'
  8.  
  9. $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib')
  10. require 'make_voteable'
  11.  
  12. ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + '/debug.log')
  13. ActiveRecord::Base.configurations = YAML::load_file(File.dirname(__FILE__) + '/database.yml')
  14. ActiveRecord::Base.establish_connection(ENV['DB'] || 'sqlite3')
  15.  
  16. ActiveRecord::Base.silence do
  17.   ActiveRecord::Migration.verbose = false
  18.  
  19.   load(File.dirname(__FILE__) + '/schema.rb')
  20.   load(File.dirname(__FILE__) + '/models.rb')
  21. end
  22.  
  23. RSpec.configure do |config|
  24.   config.filter_run :focus => true
  25.   config.run_all_when_everything_filtered = true
  26.   config.filter_run_excluding :exclude => true
  27.  
  28.   config.mock_with :rspec
  29.  
  30.   config.before(:suite) do
  31.     DatabaseCleaner.strategy = :truncation
  32.     DatabaseCleaner.clean
  33.   end
  34.  
  35.   config.after(:each) do
  36.     DatabaseCleaner.clean
  37.   end
  38. end

Line 2-10 adds the dependent code to our spec_helper.rb and so to our tests (as this file is required by all other test files). We even add the plugin code itself (line 10). Then we setup an ActiveRecord logger (line 12) and establish a connection to the test database (line 13-14). For this task we also have to create a database configuration file database.yml where the database options are stored (pretty easy for SQLite). Then the database schema will be created (line 19) and some test models will be loaded (line 20). For now we just create empty schema.rb and models.rb files and fill them later. In the next step RSpec itself will be configured. Line 24-26 brings some convenience by allowing to exclude test cases or running just a particular one. Line 28 tells RSpec to use the RSpec mocking framework for mocking. The rest (line 30 and below) configures database cleaner to clean the database before the whole test suite and after each test run.

As already mentioned, the spec_helper.rb configuration file presumes that you have a database.yml (your database configuration), a models.rb (the models that are used for testing) and a schema.rb (your database schema for those models) file in your spec folder. For now just create a database.yml file (the other files will be created in the next part).

We also add a new task to the already available Rakefile (created by Bundler) for running our specs using Rake (using rake spec). This is just for convenience as we could run the tests also by using bundle exec rspec spec. Setting the default task in the last line gives us even more comfort, as we now just have to run rake to run our tests.

# Rakefile
... 
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new(:spec)
task :default => :spec

As the last step for today series we add some stuff to .gitignore to exclude it from checking this in our GIT repository.

# .gitignore
...
Gemfile.lock
*.log
*.sqlite3
...

If you ask yourself why to exclude Gemfile.lock then have a look at this blog post of Yehuda Katz. In short, exclude the Gemfile.lock from Git when developing gems. This makes the gem independent from specific gem versions (and leaves it more universal). Include the Gemfile.lock into Git when developing a Rails app as the priority here is to make it work with those versions.

Also, if you are using an IDE that adds additional project files into the make_voteable project directory it is advisable to exclude them from version control, too. I recommend to use a global .gitignore file for that instead of the local project .gitignore file.

In the next part we will take a deeper look into the make_voteable model.