Gemfile setup
group :development, :test do
gem 'rspec-rails', '~> 2.14.0'
gem 'factory_girl_rails', '~> 4.2.1'
end
group :test do
gem 'faker', '~> 1.1.2'
gem 'capybara', '~> 2.1.0'
gem 'database_cleaner', '~> 1.0.1'
gem 'launchy', '~> 2.3.0'
gem 'selenium webdriver', '~> 2.39.0'
end
(Test) Database Setup - database.yml
test:
adapter: postgresql
encoding: utf8
database: whatevers_test
pool: 5
username:
password:
timeout: 5000
creates all the dbs
bundle exec rake db:create:all
installs rspec in your project
bundle exec rails generate rspec:install
add this line to .rspec file - makes formatting for rspec easier using documentation format
--format documentation
add to config/application.rb
config.generators do |g|
g.test_framework :rspec,
fixtures: true,
view_specs: false,
helper_specs: false,
routing_specs: false,
controller_specs: true,
request_specs: false
g.fixture_replacement :factory_girl, dir: "spec/factories"
end
make test database schema match dev db schema
rake db:test:clone
bundle exec rspec
Model Specs should include tests for: Model's create method when passed valid/invalid params Data that fail validations Class/Instance methods expected performance
each spec requires this require
require 'spec_helper'
Four Best Practices
- Describes a set of expectations
- Each it only expects one thing
- Each it is explicit
- Each it description begins with a verb, not should
be_valid matcher
model = Model.new(params: value)
expect(model).to be_valid
.to have().errors_on()
expect(Model.new(param: nil)).to have(1).errors_on(:param)
allows you to simply test validations on specific parameters
.to eq(value)
expect(model.method).to eq(value)
happy example
expect(Model.method(param)).to eq(expected_return)
failing example
expect(Model.method(param)).to_not include(instance_variable)
code contained in before block runs before each example within the describe block it's in
before :each do
stuff
end
:each is the default behavior of before
code contained in an after block runs after each example within the describe block it's in
FactoryGirl define method
FactoryGirl.define do
factory :contact do
firstname "John"
lastname "Doe"
sequence(:email) { |n| "johndoe#{n}@example.com" }
end
end
This makes it so that whenever we use FactoryGirl.create(:model) it uses what we define in the factory definition.
A sequence automatically increments n inside the block, yielding higher n values for whatever you want to use them for. This is essential for uniqueness validations on Models. You can pass any data that you need
FactoryGirl.create(:contact, email: "[email protected]")
Just pass a secondary parameter via options hash
Instantiates but does not save.
RSpec.configure do |config|
config.include FactoryGirl::Syntax::Methods
end
This allows you to write methods from FactoryGirl without typing FactoryGirl
expect(build(:model)).to be_valid
expect(build(:model, param: nil)).to have(1).errors_on(:param)
associated factory
association :model
# associates the passed model with the defined factory. use like below
FactoryGirl.define do
factory :phone do
association :contact
phone { '123-456-788' }
phone_type 'whatevs'
end
end
inhereted factory -
allows you to do things like FactoryGirl.build(:type_model)
for ease of customization
FactoryGirl.define do
factory :phone do
association :contact
phone { 'whatevs' }
factory :home_phone do
phone_type 'home'
end
factory :work_phone do
phone_type 'work
end
end
end