RSpec - Testando suas aplicações Ruby on Rails

hlmerscher 1,041 views 31 slides May 12, 2014
Slide 1
Slide 1 of 31
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19
Slide 20
20
Slide 21
21
Slide 22
22
Slide 23
23
Slide 24
24
Slide 25
25
Slide 26
26
Slide 27
27
Slide 28
28
Slide 29
29
Slide 30
30
Slide 31
31

About This Presentation

Palestra sobre testes automatizados utilizando BDD e RSpec para testar aplicações Ruby on Rails.


Slide Content

RSpec
Testando suas aplicações Ruby on Rails
Hercules Lemke Merscher - @hlmerscher

Behavior Driven Development

gem install
gem install rspec
# Gemfile
group :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
end
end

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 }
end
end

let / let!
let(:produto) do
Produto.new
end

let(:produto) { Produto.new }
let!(:produto) do
Produto.new
end

let!(:produto) { Produto.new }

before / after
before { produto.ativar }
before do
produto.ativar
end
after { produto.destroy }
after do
produto.destroy
end

app/models/produto.rb
class Produto < ActiveRecord::Base
SITUACOES = %w(ativo inativo esgotado)
...
def ativar
update(status: 'ativo')
end
end

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' }
end
end

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'
end
end

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 }
end
end

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
end
end

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
end
end

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) }
end
end

subject
describe Produto do
describe '#ativo?' do
context 'quando ativo' do
subject { Produto.new(status: 'ativo') }
it { should be_ativo }
end
...
end
end

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
end
end

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) }
end
end

shared examples
module Codificavel
extend ActiveSupport::Concern
included do
before_validation :definir_codigo
end
private
def definir_codigo
self.codigo = SecureRandom.hex(6)
end
end

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 do
subject do
Produto.create(:nome => 'bla',
:valor => 50,
:status => 'ativo')
end
it_behaves_like 'codificavel', subject
end

shared examples
describe Categoria do
subject do
Categoria.create(:nome => 'bla')
end
it_behaves_like 'codificavel', subject
end

shoulda-matchers
# Gemfile
group :development, :test do
gem 'rspec-rails'
gem 'shoulda-matchers'
end
# spec_helper
require '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) }
end
end

shoulda-matchers
describe Produto do
context 'relacionamentos' do
it { should belong_to(:categoria) }
end
end
describe Categoria do
context 'relacionamentos' do
it { should have_many(:produtos) }
end
end

http://rspec.info/
http://betterspecs.org/
https://relishapp.com/rspec

Exemplos
https://github.com/hlmerscher/liberdade-interativa-2014

Obrigado!
www.herculesdev.com.br
[email protected]
twitter.com/hlmerscher
github.com/hlmerscher