12 December 2011

Testing Rails 3.1 application with minitest

UPDATE: There is my new post with some updated information about testing Rails application with minitest here.

This post is about how to integrate MiniTest::Spec with Rails 3.1 and how to use it with fixtures and shoulda-matchers.
It covers only models spec example. To find more please visit links given below this post.

Create a new rails app:
$ rails new TestApp -T
Option -T skips test unit as we don't want to use it.

Add to your Gemfile:
group :test, :development do
  gem 'minitest-rails'
end
group :test do
  gem 'minitest-matchers'
  gem 'shoulda-matchers'
end
Don't forget to run bundler against your new Gemfile content:
$ bundle install
Note: You may need to run this either with --without assets option or add gem 'execjs' and gem 'therubyracer' into assets group of your Gemfile.

Run the minitest installation generator:
$ rails generate mini_test:install
This should create minitest_helper.rb file within test directory

Edit your test/minitest_helper.rb to look like this:
ENV["RAILS_ENV"] = "test"
require File.expand_path('../../config/environment', __FILE__)
require "minitest/autorun"
require "minitest/rails"
require "minitest/matchers"
require "minitest/pride" # let's have awesome colorful output;)

# define fixtures module
module MiniTest::Rails::Fixtures
  def self.included(klass)
    klass.class_eval do
      include ActiveSupport::Testing::SetupAndTeardown
      include ActiveRecord::TestFixtures
      self.fixture_path = File.join(Rails.root, "test", "fixtures")
    end
  end
end

# include some stuff to be used by all specs
class MiniTest::Rails::Spec
  # cheat to make #context method available
  class << self
    alias :context :describe
  end
end

# make fixtures and shoulda matchers available within models spec
class MiniTest::Rails::Model
  include MiniTest::Rails::Fixtures
  include Shoulda::Matchers::ActiveRecord
  extend Shoulda::Matchers::ActiveRecord
  include Shoulda::Matchers::ActiveModel
  extend Shoulda::Matchers::ActiveModel
end

# make #describe BDD style available
MiniTest::Spec.register_spec_type MiniTest::Rails::Model do |desc|
  desc.constantize < ActiveRecord::Base
end

Add to your config/application.rb:
config.generators do |g|
  g.test_framework :mini_test, :spec => true, :fixture => true
end

Generate your sample model:
$ rails generate model User name:string
This should create files:
test/fixtures/users.yml
test/models/user_test.rb
db/migrate/[timestamp]_create_users.rb

Create database unless exists and run your migrations:
$ rake db:create
$ rake db:migrate
$ rake db:test:prepare

Edit your test/fixtures/users.yml with sample data:
tester:
  name: "Tester"

Write some sample tests into test/models/user_test.rb:
require "minitest_helper"
describe User do
  fixtures :users
  subject { User.new }
  before { @user = users(:tester) }
  context "database" do  
    it { must have_db_column(:name).of_type(:string }
  end
  context "instance methods" do
    it "#name returns name" do
      @user.name.must_equal "Tester"
    end
  end
end

Finally, you can run your tests:
$ rake test:models

This post is based on some other sources. Please take a look at them to find more:

5 comments:

  1. I have a question :)

    Should the :

    config/application.rb:
    config.generators do |g|
    g.test_framework :mini_test, :spec => true, :fixture => true
    end

    be inside the model AppName block

    or added as a separate block

    Peter M

    ReplyDelete
  2. @Openphase
    This should be placed within TestApp::Application in this particular case.

    ReplyDelete
  3. This comment has been removed by a blog administrator.

    ReplyDelete