testando rails apps com rspec

Post on 19-May-2015

6.915 Views

Category:

Technology

4 Downloads

Preview:

Click to see full reader

DESCRIPTION

Minha apresentação no Ceará on Rails 2009

TRANSCRIPT

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?

one more thing

compra agora!http://howtocode.com.br

nando@simplesideias.com.br

obrigado

top related