RSpec
Testando suas aplicações Ruby on Rails
Hercules Lemke Merscher - @hlmerscher
Behavior Driven Development
gem install
gem install rspec
# Gemfilegroup :development, :test do
gem 'rspec-rails'end
bundle install
rails generate rspec:install
rspec
estrutura
spec/├── controllers│ └── produtos_controller_spec.rb├── models│ ├── categoria_spec.rb│ └── produto_spec.rb├── routing│ └── produtos_routing_spec.rb└── spec_helper.rb
spec/models/produto_spec.rb
describe Produto do describe 'ativar' do it 'deve ativar produto' do produto = Produto.create(nome: 'Cadeira',
valor: 200.0, status: 'inativo')
expect(produto.ativar).to be_true end endend
spec/models/produto_spec.rb
describe Produto do describe '#ativar' do let(:produto) do Produto.create(nome: 'Cadeira', valor: 200.0, status: 'inativo') end it { expect(produto.ativar).to be_true } endend
let / let!
let(:produto) do Produto.newend let(:produto) { Produto.new }
let!(:produto) do Produto.newend let!(:produto) { Produto.new }
before / after
before { produto.ativar }
before do produto.ativarend
after { produto.destroy }
after do produto.destroyend
app/models/produto.rb
class Produto < ActiveRecord::Base SITUACOES = %w(ativo inativo esgotado)
...
def ativar update(status: 'ativo') endend
spec/models/produto_spec.rb
describe Produto do describe '#ativar' do let(:produto) do Produto.create(nome: 'Cadeira', valor: 200.0, status: 'inativo') end before { @resultado = produto.ativar } it { expect(@resultado).to be_true } it { expect(produto.status).to eq 'ativo' } endend
matchers
expect(produto.valor).to eq 50
expect(produto.valor).not_to eq 50
expect(produto.valor).to be < 50
expect(produto.valor).to be >= 50
expect(produto.valid?).to be_true
expect(produto).to be_valid
app/models/produto.rb
class Produto < ActiveRecord::Base SITUACOES = %w(ativo inativo esgotado)
...
def ativo? status == 'ativo' endend
spec/models/produto_spec.rb
describe Produto do describe '#ativo?' do let(:produto) { Produto.new(status: 'ativo') } it { expect(produto.ativo?).to be_true } it { expect(produto).to be_ativo } endend
context
describe Produto do describe '#ativo?' do context 'quando ativo' do let(:produto) { Produto.new(status: 'ativo') } it { expect(produto).to be_ativo } end context 'quando inativo' do let(:produto) { Produto.new(status: 'inativo') } it { expect(produto).not_to be_ativo } end endend
context
describe Produto do describe '#ativo?' do ... context 'quando inativo' do
%w(inativo esgotado).each do |status| let(:produto) { Produto.new(status: status) } it { expect(produto).not_to be_ativo }
end end endend
subject
describe Produto do context 'sem usar subject' do let(:produto) { Produto.new } it { expect(produto).to respond_to(:nome) } end
context 'usando subject' do it { should respond_to(:nome) } endend
subject
describe Produto do describe '#ativo?' do context 'quando ativo' do subject { Produto.new(status: 'ativo') } it { should be_ativo } end ... endend
expect vs should
Não use a sintaxe do should.
it { produto.valor.should eq 50 }
Prefira a sintaxe nova(não tão nova assim :P) do expect.
it { expect(produto.valor).to eq 50 }
produtos_controller_spec.rb
describe "POST create" do describe "com parâmetros válidos" do it "deve criar um novo produto" do expect { post :create, {:produto => valid_attributes} }.to change(Produto, :count).by(1) end it "deve atribuir o produto criado como @produto" do post :create, {:produto => valid_attributes} expect(assigns(:produto)).to be_a(Produto) expect(assigns(:produto)).to be_persisted end it "deve redirecionar para página do produto criado" do post :create, {:produto => valid_attributes} expect(response).to redirect_to(Produto.last) end endend
descrições curtas
describe "POST create" do describe "com parâmetros válidos" do before { post :create, :produto => valid_attributes } it { expect(assigns(:produto)).to be_a Produto } it { expect(assigns(:produto)).to be_persisted } it { expect(response).to redirect_to assigns(:produto) } endend
shared examples
module Codificavel extend ActiveSupport::Concern
included do before_validation :definir_codigo end
private def definir_codigo self.codigo = SecureRandom.hex(6) endend
spec/support/shared_examples.rb
shared_examples_for 'codificavel' do |objeto| subject(:codificavel) { objeto }
it { expect(codificavel.codigo).to be_a String } it { expect(codificavel.codigo).not_to be_blank }end
shared examples
describe Produto dosubject do
Produto.create(:nome => 'bla', :valor => 50, :status => 'ativo')
end
it_behaves_like 'codificavel', subjectend
shared examples
describe Categoria dosubject do Categoria.create(:nome => 'bla')end
it_behaves_like 'codificavel', subjectend
shoulda-matchers
# Gemfilegroup :development, :test do
gem 'rspec-rails'gem 'shoulda-matchers'
end
# spec_helperrequire 'rspec/rails'require 'shoulda/matchers'
shoulda-matchers
describe Produto do context 'validações' do it { should validate_presence_of(:nome) } it { should validate_uniqueness_of(:nome) } it { should validate_numericality_of(:valor)
.is_greater_than(0) } it { should ensure_inclusion_of(:status)
.in_array(Produto::SITUACOES) } endend
shoulda-matchers
describe Produto do context 'relacionamentos' do it { should belong_to(:categoria) } endend
describe Categoria do context 'relacionamentos' do
it { should have_many(:produtos) } endend
http://rspec.info/http://betterspecs.org/
https://relishapp.com/rspec
Exemplos
https://github.com/hlmerscher/liberdade-interativa-2014
Obrigado!
www.herculesdev.com.br
twitter.com/hlmerscher
github.com/hlmerscher
Top Related