Por que testar?
Para verificar se o sistema se comporta
como deveria.
Como testar?
Testes manuais.
Testes automatizados.
Testes automatizados
Trazem mais confiança.
Identificam regressões no código.
Permitem refatorar com segurança.
Testar antes ou depois?
Tanto faz.
Testar depois
Exige mais disciplina.
O código é mais difícil de testar.
a.k.a Test Driven Development
Testar antes
O código é mais simples de testar.
Geralmente é mais bem escrito.
Behavior Driven Development
Então surgiu o BDD
Desenvolver aplicações descrevendo seu
comportamento do ponto de vista do cliente.
BDD não é sobre testar o
código.
É sobre o design e
documentação do código.
É sobre escrever software
que é realmente importante.
Frameworks
Sua linguagem preferida deve ter um
framework BDD.
JBehave, PHPSpec, GSpec, JSpec, specs,
NSpec...
No Ruby temos o RSpec.
David Chelimsky Spec e Story
RSpec é um framework
BDD para Ruby e Rails.
http://rspec.info
Descreva o comportamento
como em uma conversa.
Eu: descreva uma palestra
Você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
end
end
Configuração
Ruby on Rails
Use como plugin.
script/plugin install git://github.com/dchelimsky/rspec.git
script/plugin install git://github.com/dchelimsky/rspec-rails.git
Ruby on Rails
Use como gem.
gem install rspec
gem install rspec-rails
Ruby on Rails
Configure sua aplicação.
script/generate rspec
Model
script/generate rspec_model user role:string --skip-fixture
create app/models/user.rb
create spec/models/user_spec.rb
create db/migrate/20091104135200_create_users.rb
Model
spec/models/user_spec.rb
require '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)
end
end
Exemplo
Verificar se um usuário é admin.
Escreva um teste que falhe
spec/models/user_spec.rb
describe User do
it "should be an admin" do
subject.role = "admin"
subject.should be_admin
end
end
Execute a suíte de testes
$ rake spec:models
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
Faça o teste passar
app/models/user.rb
class User < ActiveRecord::Base
def admin?
true
end
end
Execute a suíte de testes
$ rake spec:models
.
Finished in 0.087279 seconds
1 example, 0 failures
Adicione um teste negativo
spec/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
end
end
Execute a suíte de testes
$ rake spec:models
.F
1)
'User should not be admin' FAILED
expected admin? to return false, got true
./spec/models/user_spec.rb:10:
Finished in 0.098295 seconds
2 examples, 1 failure
Faça o teste passar
app/models/user.rb
class User < ActiveRecord::Base
def admin?
role == "admin"
end
end
Model
Coisas mais comuns
it "should be valid" do
subject.should be_valid
end
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).records
end
Controller
spec/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
Exemplo
Criar 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
end
end
Escreva um teste que falhe
spec/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
end
end
Execute a suíte de testes
$ rake spec:controllers
F
1) 'UsersController GET: new should instantiate user' FAILED
expected 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
Faça o teste passar
app/controllers/users_controller.rb
class UsersController < ApplicationController
def new
@user = User.new
end
end
Execute a suíte de testes
$ rake spec:controllers
.
Finished in 0.119345 seconds
1 example, 0 failures
Escreva o próximo teste
spec/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
end
end
Execute a suíte de testes
$ rake spec:controllers
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
Faça o teste passar
app/controllers/users_controller.rb
class UsersController < ApplicationController
def create
@user = User.new(params[:user])
end
end
Execute a suíte de testes
$ rake spec:controllers
..
Finished in 0.119345 seconds
2 example, 0 failures
Escreva o próximo teste
spec/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
end
end
Execute a suíte de testes
$ rake spec:controllers
F
1) 'UsersController POST: create on success should redirect to
the show page' FAILED
expected redirect to "http://test.host/users/1", got no redirect
Finished in 0.138342 seconds
4 examples, 2 failures
Faça o teste passar
app/controllers/users_controller.rb
class UsersController < ApplicationController
def create
@user = User.new(params[:user])
if @user.save
redirect_to @user
end
end
end
Execute a suíte de testes
$ rake spec:controllers
.....F
Finished in 0.119345 seconds
5 examples, 1 failures
Escreva o próximo teste
spec/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
end
end
Execute a suíte de testes
$ rake spec:controllers
F
1) 'UsersController POST: create on success should set success
message' FAILED
expected: "A new user has been created!",
got: nil (using ==)
Finished in 0.138342 seconds
5 examples, 1 failure
Faça o teste passar
app/controllers/users_controller.rb
class UsersController < ApplicationController
def create
@user = User.new(params[:user])
if @user.save
flash[:notice] = "A new user has been created!"
redirect_to @user
end
end
end
Execute a suíte de testes
$ rake spec:controllers
.......
Finished in 0.119345 seconds
7 examples
Escreva o próximo teste
spec/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
end
end
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
Exemplo
Exibir conteúdo para usuários admin.
<% content_for_admin(@user) do %>
<!-- admin content -->
<% end %>
Escreva um teste que falhe
spec/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
end
end
Execute a suíte de testes
$ rake spec:helpers
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
Faça o teste passar
app/helpers/users_helper.rb
module UsersHelper
def content_for_admin(user, &block)
yield if user.admin?
end
end
Execute a suíte de testes
$ rake spec:helpers
.
Finished in 0.119345 seconds
1 example, 0 failures
Views
Teste 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 palestra
Tente 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 sobre
RSpec http://rspec.info
Cucumber http://cukes.info
Factory Girl http://bit.ly/4EicvV
TATFT
dúvidas?
one more thing
compra agora!
http://howtocode.com.br
obrigado
nando@simplesideias.com.br
Let LinkedIn power your SlideShare experience
+
Let LinkedIn power your SlideShare experience
Customize SlideShare content based on your interests
We will import your LinkedIn profile and you will be visible on SlideShare.
Keep up to date when your LinkedIn contacts post on SlideShare