Upload
nando-vieira
View
6.916
Download
4
Embed Size (px)
DESCRIPTION
Minha apresentação no Ceará on Rails 2009
Citation preview
nando vieira
testando railsapps com rspec
sobre mim• trabalho com web desde 1999
• desenvolvo com ruby desde 2006
• escrevo testes desde 2007
RubyPHP JavaScript Objective-C
minhas urls• http://simplesideias.com.br
• http://howtocode.com.br
• http://spesa.com.br
• http://twitter.com/fnando
• http://github.com/fnando
Por que testar?Para verificar se o sistema se comporta como deveria.
Como testar?Testes manuais.Testes automatizados.Testes manuais.Testes automatizados.
Testes automatizadosTrazem mais confiança.Identificam regressões no código.Permitem refatorar com segurança.
Testar antes ou depois?Tanto faz.
Testar depoisExige mais disciplina.O código é mais difícil de testar.
Testar antesO código é mais simples de testar.Geralmente é mais bem escrito.
a.k.a Test Driven Development
Então surgiu o BDDDesenvolver aplicações descrevendo seu comportamento do ponto de vista do cliente.
Behavior Driven Development
BDD não é sobre testar o código.
É sobre o design e documentação do código.
É sobre escrever software que é realmente importante.
Frameworks
JBehave, PHPSpec, GSpec, JSpec, specs, NSpec...
Sua linguagem preferida deve ter umframework BDD.
No Ruby temos o RSpec.
RSpec é um framework BDD para Ruby e Rails.
Spec e StoryDavid Chelimsky
http://rspec.info
Descreva o comportamento como em uma conversa.
Eu: descreva uma palestraVocês:• ela deve ter um palestrante.• ela deve ter um tempo definido.• ela deve ser interessante.
describe "My Talk" do it "should be awesome" do true.should be_true endend
Configuração
Ruby on RailsUse como plugin.script/plugin install git://github.com/dchelimsky/rspec.gitscript/plugin install git://github.com/dchelimsky/rspec-rails.git
Ruby on RailsUse como gem.gem install rspecgem install rspec-rails
Ruby on RailsConfigure sua aplicação.script/generate rspec
Ruby on RailsGenerators disponíveis.script/generateintegration_spec, rspec, rspec_controller, rspec_model, rspec_scaffold
O que testar?Tudo o que você julgar importante ser testado.
Como testar?Teste uma coisa de cada vez.Acostume-se com o workflow.
Red-Green-RefactorWorkflow
RedEscreva um teste que falhe
GreenEscreva a funcionalidade
RefactorRefatore o código que passou
Rails Checklist• Models• Controllers• Helpers• Views• E-mails• Rake tasks• JavaScript• ...
• Models• Controllers• Helpers• Views
Modelscript/generate rspec_model user role:string --skip-fixture
create app/models/user.rbcreate spec/models/user_spec.rbcreate db/migrate/20091104135200_create_users.rb
Modelspec/models/user_spec.rbrequire 'spec_helper'
describe User do before(:each) do @valid_attributes = { } end
it "should create a new instance given valid attributes" do User.create!(@valid_attributes) endend
ExemploVerificar se um usuário é admin.
describe User do it "should be an admin" do subject.role = "admin" subject.should be_admin endend
Escreva um teste que falhespec/models/user_spec.rb
F
1) NoMethodError in 'User should be an admin'undefined method `admin?' for #<User id: nil, created_at: nil, updated_at: nil>active_record/attribute_methods.rb:255:in `method_missing'./spec/models/user_spec.rb:5:
Finished in 0.088512 seconds
1 example, 1 failure
$ rake spec:models
Execute a suíte de testes
app/models/user.rbFaça o teste passar
class User < ActiveRecord::Base def admin? true endend
Execute a suíte de testes$ rake spec:models
.
Finished in 0.087279 seconds
1 example, 0 failures
Adicione um teste negativospec/models/user_spec.rb
describe User do it "should be an admin" do subject.role = "admin" subject.should be_admin end it "should not be admin" do subject.should_not be_admin endend
Execute a suíte de testes$ rake spec:models.F
1)'User should not be admin' FAILEDexpected admin? to return false, got true./spec/models/user_spec.rb:10:
Finished in 0.098295 seconds
2 examples, 1 failure
app/models/user.rbFaça o teste passar
class User < ActiveRecord::Base def admin? role == "admin" endend
ModelCoisas mais comunsit "should be valid" do subject.should be_validend
it "should have errors" do subject.should have(1).error_on(:role) subject.should have(2).errors_on(:role)end
it "should have no errors" do subject.should have(:no).error_on(:role)end
it "should have records" do User.should have(1).record User.should have(2).recordsend
Controllerscript/generate rspec_controller users
create spec/controllers/users_controller_spec.rbcreate spec/helpers/users_helper_spec.rbcreate app/controllers/users_controller.rbcreate app/helpers/users_helper.rb
Controllerspec/controllers/users_controller_spec.rb
describe UsersController do
#Delete this example and add some real ones it "should use UsersController" do controller.should be_an_instance_of(UsersController) end
end
ExemploCriar um novo usuário.class UsersController < ApplicationController def new @user = User.new end def create @user = User.new(params[:user]) if @user.save flash[:notice] = "A new user has been created!" redirect_to @user end endend
Escreva um teste que falhespec/controllers/users_controller_spec.rb
describe UsersController do context "GET: new" do it "should instantiate user" do assigns[:user].should be_a_kind_of(User) end endend
F
1) 'UsersController GET: new should instantiate user' FAILEDexpected nil to be a kind of User(id: integer, role: string, created_at: datetime, updated_at: datetime)
Finished in 0.088512 seconds
1 example, 1 failure
$ rake spec:controllers
Execute a suíte de testes
app/controllers/users_controller.rbFaça o teste passar
class UsersController < ApplicationController def new @user = User.new endend
Execute a suíte de testes$ rake spec:controllers
.
Finished in 0.119345 seconds
1 example, 0 failures
Escreva o próximo testespec/controllers/users_controller_spec.rb
describe UsersController do describe "POST: create" do context "on success" do it "should create user with provided arguments" do user = mock_model(User).as_null_object User.should_receive(:new).with("role" => "editor").and_return(user) post :create, :user => {:role => "editor"} end end endend
F
1) Spec::Mocks::MockExpectationError in 'UsersController POST: create on success should create user with provided arguments'<User(id: integer, role: string, created_at: datetime, updated_at: datetime) (class)> expected :new with ({"role"=>"editor"}) once, but received it 0 times
Finished in 0.138342 seconds
4 examples, 3 failures
$ rake spec:controllers
Execute a suíte de testes
app/controllers/users_controller.rbFaça o teste passar
class UsersController < ApplicationController def create @user = User.new(params[:user]) endend
Execute a suíte de testes$ rake spec:controllers
..
Finished in 0.119345 seconds
2 example, 0 failures
Escreva o próximo testespec/controllers/users_controller_spec.rb
describe UsersController do describe "POST: create" do context "on success" do it "should redirect to the show page" do post :create, :user => {:role => "editor"} response.should redirect_to(user_url(assigns[:user])) end end endend
F
1) 'UsersController POST: create on success should redirect to the show page' FAILEDexpected redirect to "http://test.host/users/1", got no redirect
Finished in 0.138342 seconds
4 examples, 2 failures
$ rake spec:controllers
Execute a suíte de testes
app/controllers/users_controller.rbFaça o teste passar
class UsersController < ApplicationController def create @user = User.new(params[:user]) if @user.save redirect_to @user end endend
Execute a suíte de testes$ rake spec:controllers
.....F
Finished in 0.119345 seconds
5 examples, 1 failures
Escreva o próximo testespec/controllers/users_controller_spec.rb
describe UsersController do describe "POST: create" do context "on success" do it "should set success message" do post :create, :user => {:role => "editor"} flash[:notice].should == "A new user has been created!" end end endend
F
1) 'UsersController POST: create on success should set success message' FAILEDexpected: "A new user has been created!", got: nil (using ==)
Finished in 0.138342 seconds
5 examples, 1 failure
$ rake spec:controllers
Execute a suíte de testes
app/controllers/users_controller.rbFaça o teste passarclass UsersController < ApplicationController def create @user = User.new(params[:user]) if @user.save flash[:notice] = "A new user has been created!" redirect_to @user end endend
Execute a suíte de testes$ rake spec:controllers
.......
Finished in 0.119345 seconds
7 examples
Escreva o próximo testespec/controllers/users_controller_spec.rb
describe UsersController do describe "POST: create" do context "on failure" do it "should not redirect" do user = mock_model(User) user.should_receive(:save).and_return(false) User.should_receive(:new).and_return(user) post :create response.should_not be_redirect end end endend
HelperÉ gerado quando um controller é criado
describe UsersHelper do #Delete this example and add some real ones or delete this file it "should be included in the object returned by #helper" do included_modules = (class << helper; self; end).send :included_modules included_modules.should include(UsersHelper) end
end
ExemploExibir conteúdo para usuários admin.<% content_for_admin(@user) do %> <!-- admin content --><% end %>
Escreva um teste que falhespec/helpers/users_helper_spec.rb
describe UsersHelper do describe "#content_for_admin" do it "should display content for admins" do user = User.new(:role => "admin") content = helper.content_for_admin(user) { "content" } content.should == "content" end endend
F
1) NoMethodError in 'UsersHelper#content_for_admin should display content for admins'undefined method `content_for_admin' for #<Spec::Rails::Example::HelperExampleGroup::HelperObject:0x1030c2138>
Finished in 0.138342 seconds
1 example, 1 failure
$ rake spec:helpers
Execute a suíte de testes
app/helpers/users_helper.rbFaça o teste passar
module UsersHelper def content_for_admin(user, &block) yield if user.admin? endend
Execute a suíte de testes$ rake spec:helpers
.
Finished in 0.119345 seconds
1 example, 0 failures
ViewsTeste a semântica e não o código gerado.É difícil escrever testes antes do markup.Utilize stubs & mocks!Sem exemplos!
Duas coisas que você deve tirar desta palestraTente de verdade se acostumar ao workflow RED-GREEN-REFACTOR.
Crie testes tão rápido quanto possível.Ou você não irá escrever testes.
Saiba mais sobreRSpec http://rspec.info Cucumber http://cukes.infoFactory Girl http://bit.ly/4EicvV
TATFT
dúvidas?