SlideShare uma empresa Scribd logo
1 de 54
Testes Automatizados
Usando Ruby on Rails, RSpec e Cucumber
“Inspecionar para previnir defeitos é
bom; Inspecionar para encontrar
defeitos é desperdício”

           Shigeo Shingo
De onde veio?

A ascensão das metodologias ágeis

Documentação Desatualizada

A “queima de documentação”
Pra que serve?


Auxiliar nas Mudanças ou Refactoring

Rastreabilidade

Design
O que é?


Caixa-Branca

*Normalmente feito pelo próprio
Desenvolvedor

Comparação de resultados
Exemplo

describe Calculadora do
  it "soma entre 1 e 1 deve ser 2" do
    (1+1).should eq(2)
  end
end
Modalidades

Unitários

Integração

Aceitação

outros
Quando deve ser
      feito?


Antes, durante e depois
Tecnologias

Ruby on Rails

RSpec

Capybara

Cucumber
RSpec

Examples

Expectations
Voltemos ao exemplo
Projeto
Testes Unitários
Unidade é a menor parte testável de
um software.

Consigo encontrar o erro com mais
eficiência.

Como “escapar” da dependência entre
as camadas?
Stub Methods


Simula o comportamento de um código
existente.

Reduz o tempo de execução.

Isola o teste.
O Método

def create
  @sorteio = Sorteio.new(params[:sorteio])
  if @sorteio.save
    redirect_to @sorteio, notice: 'Sorteio criado.'
  else
    render action: "new"
  end
end
O Teste
context "se sorteio for salvo com sucesso" do
  before do
    Sorteio.any_instance.stub(:save).and_return(true)
  end

  it "deve enviar pra tela de sorteios" do
    post :create, :id => 1
    response.should redirect_to sorteios_path
  end
end
Mock Objects


Objetos “de mentira” ou objetos
substitutos.

Permitem isolar as classes de um
sistema de forma bastante simples.
O Método

def sortear
  @sorteio = Sorteio.find(params[:id])
  @sorteio.sortear
  redirect_to sorteio_path(@sorteio_id),
                notice: 'Sorteio realizado.'
end
O Teste
before do
  @sorteio = mock('Sorteio')
  @sorteio.stub(:sortear)
  Sorteio.stub(:find).and_return(@sorteio)
end

it "deve mostrar mensagem de sorteio realizado" do
  get :sortear, :id => 1
  flash[:notice].should == "Sorteio realizado."
end
Message Expectations



 Cria um Stub Method

 Cria Expectativas
O Método

def edit
  @sorteio = Sorteio.find(params[:id])
end
O Teste
it "popula sorteio com o sorteio enviado" do
  sorteio = mock('Sorteio')
  Sorteio.should_receive(:find).with('1')
                .and_return(sorteio)
  get :edit, :id => 1
  assigns[:sorteio].should == sorteio
end
Testando Controllers


 Redirecionamentos e Parâmetros de
 Tela.

 Não deve invocar o model “de
 verdade”.
context "se concorrente não for salvo" do
  before do
    @concorrente_mock.stub(:save).and_return(false)
  end

  it "deve enviar pra tela de apresentação do sorteio
deste concorrente" do
    post :create, :sorteio_id => 1
    response.should redirect_to sorteio_path(1)
  end

  it "deve enviar uma notificação de Houve um erro na
criação do Concorrente." do
    post :create, :sorteio_id => 1
    flash[:notice].should == "Houve um erro na criação
do Concorrente."
  end
end
Rotas
Sorteando::Application.routes.draw do
  resources :sorteios do
    member do
      get :sortear
    end
    resources :concorrentes, :only => [:new, :create, :destroy]
  end

  root :to => 'sorteios#index'
end
Testando Rotas
    it "routes to #create" do
      post("/sorteios/1/concorrentes").should
route_to("concorrentes#create", :sorteio_id => "1")
    end

    it "routes to #destroy" do
      delete("/sorteios/1/concorrentes/2").should
route_to("concorrentes#destroy", :sorteio_id => "1",
                  :id => "2")
    end

    it "routes to #index" do
      get("/sorteios/1/concorrentes").should_not be_routable
    end
Testes de Models


Objetos Reais.

Usar somente as propriedades
necessárias.

Validação de Campo Obrigatório.
Factory

Teste mais limpo.

Código desnecessário “escondido”.
#sorteio.rb
FactoryGirl.define do
  factory :sorteio do
    sequence(:nome) { |n| "sorteio_#{n}" }
    qtd_premios 1
  end
end


#concorrente.rb
FactoryGirl.define do
  factory :concorrente do
    sequence(:nome) { |n| "nome_#{n}" }
    sequence(:email) { |n| "nome_#{n}@email.com" }
    association :sorteio
  end
end
Usando Factory Girl
before do
  @sorteio = FactoryGirl.create(:sorteio,
                :qtd_premios => 2)
  conc1 = FactoryGirl.create(:concorrente,
                :sorteio => @sorteio)
  conc2 = FactoryGirl.create(:concorrente,
                :sorteio => @sorteio)
  conc3 = FactoryGirl.create(:concorrente,
                :sorteio => @sorteio)
end
describe "Validations" do
  it { should validate_presence_of(:nome).with_message(/é um
campo obrigatório/) }
  it { should validate_presence_of(:qtd_premios).with_message(/é
um campo obrigatório/) }
end



it "sortear com quantidade menor que a quantidade de prêmios" do
  sorteio = FactoryGirl.create(:sorteio, :qtd_premios => 3)
  conc1 = FactoryGirl.create(:concorrente, :sorteio => sorteio)
  conc2 = FactoryGirl.create(:concorrente, :sorteio => sorteio)

  sorteio.sortear
  sorteio.vencedores.should have(2).vencedores
end
Testes de Views


Renderização.

Propriedades necessárias.
describe "sorteios/index" do
  it "mostrar titulo Sorteios" do
    assign :sorteios, []
    render
    rendered.should have_content("Sorteios")
  end

  it "mostrar listagem de sorteios" do
    assign :sorteios, [ FactoryGirl.build(:sorteio,
                  :id => '1',
                  :nome => 'mega sena da virada') ]
    render
    rendered.should have_selector("tr > td") do |td|
      td.should have_content('mega sena da virada')
    end
  end
end
Code Coverage

Verificar se cada linha do software
esta “coberta” por, pelo menos, 1
teste.
Usando o Simplecov
Linhas de Código X
 Linhas de Teste
TDD

Design.

Testes são brindes de Luxo.
Teste Falho
describe "#eh_vencedor?" do
  sorteio = FactoryGirl.create(:sorteio)
  concorrente = FactoryGirl.create(:concorrente,
:sorteio => sorteio)
  concorrente.eh_vencedor?.should == true
end
Teste “Passando”

def eh_vencedor
  true
end
Refactoring e teste
      volta a Falhar
def eh_vencedor?
  VencedorSorteio.where(:concorrente_id => self).exists?
end
Teste “Passando”
             Novamente
it "#eh_vencedor?" do
  sorteio = FactoryGirl.create(:sorteio)
  concorrente = FactoryGirl.create(:concorrente,
                  :sorteio => sorteio)

  concorrente.eh_vencedor?.should == false
end
Refactoring
describe "#eh_vencedor?" do
  it "Se não venceu o sorteio, retorna falso" do
    sorteio = FactoryGirl.create(:sorteio)
    concorrente = FactoryGirl.create(:concorrente,
                    :sorteio => sorteio)
    concorrente.eh_vencedor?.should == false
  end

  it "Se venceu o sorteio, retorna verdadeiro" do
    sorteio = FactoryGirl.create(:sorteio)
    concorrente = FactoryGirl.create(:concorrente,
                    :sorteio => sorteio)
    sorteio.vencedores << concorrente
    sorteio.save
    concorrente.eh_vencedor?.should == true
  end
end
TDD feito



... mas caberiam mais
      iterações
Testes de Integração


 Camadas interagem.

 Encontra erros que o teste unitário
 não encontra.

 Ineficiente para “apontar” o erro.
Caso: Cadastro de
     Sorteio
Usando o Capybara
it "fluxo completo de cadastro" do
   visit "/sorteios"
   click_link('+')
   fill_in('Nome', :with => 'Livro de Testes Automatizados')
   fill_in('Qtd de Premios', :with => '1')
   click_button('Novo')
   page.should have_content("Sorteio criado.")
   page.should have_content("Livro de Testes Automatizados")
   page.should have_content("Concorrentes: +")
 end
Testes de Aceitação

Caixa-Preta

Pode ser criado por um Não-
Programador
Criando Steps
Dado /^que estou na página "(.*?)"$/ do |pagina|
  visit pagina
end

Então /^devo ver o texto "(.*?)"$/ do |texto|
  page.should have_content(texto)
end

Quando /^clicar no link "(.*?)"$/ do |link|
  click_link(link)
end

Quando /^clicar no botao "(.*?)"$/ do |botao|
  click_button(botao)
end
Usando o Cucumber
Cenário: Cadastrando um sorteio
  Dado que estou na página "/sorteios"
  Quando clicar no link "+"
  Então devo mudar a pagina
  Quando preencher o campo "Nome" com "Livro de
Testes Automatizados"
  E preencher o campo "Qtd de Premios" com "1"
  E clicar no botao "Novo"
  Então devo mudar a pagina
  Então devo ver o texto "Sorteio criado."
  E devo ver o texto "Livro de Testes Automatizados"
  E devo ver o texto "Concorrentes: +"
Integração Continua

Membros de um time integram seu
trabalho frequentemente.

Podem haver multiplas integrações por
dia.

Cada integração é verificada por um
build automatizado.
Servidores de CI


Jenkins(Hudson)

Cruise Control

Travis
Usando o Travis
Considerações Finais
Perguntas???

Mais conteúdo relacionado

Mais procurados

Introdução a python módulo b
Introdução a python   módulo bIntrodução a python   módulo b
Introdução a python módulo bJader Gabriel
 
Boas práticas de Automação de Testes
Boas práticas de Automação de TestesBoas práticas de Automação de Testes
Boas práticas de Automação de TestesCamilo Ribeiro
 
Cafe com Tom - ExtJS 4
Cafe com Tom - ExtJS 4Cafe com Tom - ExtJS 4
Cafe com Tom - ExtJS 4Loiane Groner
 
TDC2016 Boas Práticas SQL em Banco Relacional para Desenvolvedores
TDC2016 Boas Práticas SQL em Banco Relacional para DesenvolvedoresTDC2016 Boas Práticas SQL em Banco Relacional para Desenvolvedores
TDC2016 Boas Práticas SQL em Banco Relacional para DesenvolvedoresFernando Franquini
 
JavaScript ninja com jQuery
JavaScript ninja com jQueryJavaScript ninja com jQuery
JavaScript ninja com jQueryReinaldo Junior
 
Testando Rails apps com RSpec
Testando Rails apps com RSpecTestando Rails apps com RSpec
Testando Rails apps com RSpecNando Vieira
 

Mais procurados (8)

Introdução a python módulo b
Introdução a python   módulo bIntrodução a python   módulo b
Introdução a python módulo b
 
Boas práticas de Automação de Testes
Boas práticas de Automação de TestesBoas práticas de Automação de Testes
Boas práticas de Automação de Testes
 
Cafe com Tom - ExtJS 4
Cafe com Tom - ExtJS 4Cafe com Tom - ExtJS 4
Cafe com Tom - ExtJS 4
 
TDC2016 Boas Práticas SQL em Banco Relacional para Desenvolvedores
TDC2016 Boas Práticas SQL em Banco Relacional para DesenvolvedoresTDC2016 Boas Práticas SQL em Banco Relacional para Desenvolvedores
TDC2016 Boas Práticas SQL em Banco Relacional para Desenvolvedores
 
JavaScript ninja com jQuery
JavaScript ninja com jQueryJavaScript ninja com jQuery
JavaScript ninja com jQuery
 
Python 04
Python 04Python 04
Python 04
 
Testando Rails apps com RSpec
Testando Rails apps com RSpecTestando Rails apps com RSpec
Testando Rails apps com RSpec
 
Ns tutorial so
Ns tutorial soNs tutorial so
Ns tutorial so
 

Destaque

JavaScript Applications
JavaScript ApplicationsJavaScript Applications
JavaScript ApplicationsLuciano Costa
 
Aulas de Java Avançado 2- Faculdade iDez 2010
Aulas de Java Avançado 2- Faculdade iDez 2010Aulas de Java Avançado 2- Faculdade iDez 2010
Aulas de Java Avançado 2- Faculdade iDez 2010Maurício Linhares
 
O que faz (ou não) um tester no mundo ágil
O que faz (ou não) um tester no mundo ágilO que faz (ou não) um tester no mundo ágil
O que faz (ou não) um tester no mundo ágilSamanta Cicilia
 
Testes ágeis
Testes ágeisTestes ágeis
Testes ágeisQualister
 
Plano de projeto - Sistema de Remoção de Servidores
Plano de projeto - Sistema de Remoção de ServidoresPlano de projeto - Sistema de Remoção de Servidores
Plano de projeto - Sistema de Remoção de ServidoresDiego Armando
 
Curso java 06 - mais construtores, interfaces e polimorfismo
Curso java   06 - mais construtores, interfaces e polimorfismoCurso java   06 - mais construtores, interfaces e polimorfismo
Curso java 06 - mais construtores, interfaces e polimorfismoMaurício Linhares
 
Plano de gerenciamento_da_qualidade
Plano de gerenciamento_da_qualidadePlano de gerenciamento_da_qualidade
Plano de gerenciamento_da_qualidadeSharles Sa
 
Demoiselle 3 Está chegando a hora
Demoiselle 3 Está chegando a horaDemoiselle 3 Está chegando a hora
Demoiselle 3 Está chegando a horaVanderson Silva
 
Mixing Ruby and Java in a Service Oriented Architecture at OfficeDrop
Mixing Ruby and Java in a Service Oriented Architecture at OfficeDropMixing Ruby and Java in a Service Oriented Architecture at OfficeDrop
Mixing Ruby and Java in a Service Oriented Architecture at OfficeDropMaurício Linhares
 
Docker e suas tecnologias por @cesarnog
Docker e suas tecnologias por @cesarnogDocker e suas tecnologias por @cesarnog
Docker e suas tecnologias por @cesarnogCesar Augusto Nogueira
 

Destaque (20)

Aplicações Web Ricas e Acessíveis
Aplicações Web Ricas e AcessíveisAplicações Web Ricas e Acessíveis
Aplicações Web Ricas e Acessíveis
 
JavaScript Applications
JavaScript ApplicationsJavaScript Applications
JavaScript Applications
 
Aulas de Java Avançado 2- Faculdade iDez 2010
Aulas de Java Avançado 2- Faculdade iDez 2010Aulas de Java Avançado 2- Faculdade iDez 2010
Aulas de Java Avançado 2- Faculdade iDez 2010
 
O que faz (ou não) um tester no mundo ágil
O que faz (ou não) um tester no mundo ágilO que faz (ou não) um tester no mundo ágil
O que faz (ou não) um tester no mundo ágil
 
Docker e suas tecnologias
Docker e suas tecnologiasDocker e suas tecnologias
Docker e suas tecnologias
 
Testes Rápidos
Testes RápidosTestes Rápidos
Testes Rápidos
 
Behaviour-Driven Development com Ruby
Behaviour-Driven Development com RubyBehaviour-Driven Development com Ruby
Behaviour-Driven Development com Ruby
 
Ajax em java
Ajax em javaAjax em java
Ajax em java
 
BDD com Cucumber
BDD com CucumberBDD com Cucumber
BDD com Cucumber
 
Testes ágeis
Testes ágeisTestes ágeis
Testes ágeis
 
Plano de projeto - Sistema de Remoção de Servidores
Plano de projeto - Sistema de Remoção de ServidoresPlano de projeto - Sistema de Remoção de Servidores
Plano de projeto - Sistema de Remoção de Servidores
 
Curso java 06 - mais construtores, interfaces e polimorfismo
Curso java   06 - mais construtores, interfaces e polimorfismoCurso java   06 - mais construtores, interfaces e polimorfismo
Curso java 06 - mais construtores, interfaces e polimorfismo
 
Aprendendo ruby
Aprendendo rubyAprendendo ruby
Aprendendo ruby
 
BDD em Ação - Testadores 2015
BDD em Ação - Testadores 2015BDD em Ação - Testadores 2015
BDD em Ação - Testadores 2015
 
Plano de gerenciamento_da_qualidade
Plano de gerenciamento_da_qualidadePlano de gerenciamento_da_qualidade
Plano de gerenciamento_da_qualidade
 
Mercado de TI
Mercado de TIMercado de TI
Mercado de TI
 
Demoiselle 3 Está chegando a hora
Demoiselle 3 Está chegando a horaDemoiselle 3 Está chegando a hora
Demoiselle 3 Está chegando a hora
 
Mixing Ruby and Java in a Service Oriented Architecture at OfficeDrop
Mixing Ruby and Java in a Service Oriented Architecture at OfficeDropMixing Ruby and Java in a Service Oriented Architecture at OfficeDrop
Mixing Ruby and Java in a Service Oriented Architecture at OfficeDrop
 
Docker e suas tecnologias por @cesarnog
Docker e suas tecnologias por @cesarnogDocker e suas tecnologias por @cesarnog
Docker e suas tecnologias por @cesarnog
 
Curso java 07 - exceções
Curso java   07 - exceçõesCurso java   07 - exceções
Curso java 07 - exceções
 

Semelhante a Testes automatizados

Cucumber Best Practices
Cucumber Best PracticesCucumber Best Practices
Cucumber Best PracticesKaroline Leite
 
GraphQL e APIs: como manter a qualidade?
GraphQL e APIs: como manter a qualidade?GraphQL e APIs: como manter a qualidade?
GraphQL e APIs: como manter a qualidade?Qaladies
 
TDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no AndroidTDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no Androidtdc-globalcode
 
TDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no AndroidTDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no Androidtdc-globalcode
 
Introdução ao JS1.pptx
Introdução ao JS1.pptxIntrodução ao JS1.pptx
Introdução ao JS1.pptxLuanDev1
 
Introdução à Linguagem de programação Python
Introdução à Linguagem de programação PythonIntrodução à Linguagem de programação Python
Introdução à Linguagem de programação Pythondmmartins
 
Testes unitários e de integração: Quando e Porque
Testes unitários e de integração: Quando e PorqueTestes unitários e de integração: Quando e Porque
Testes unitários e de integração: Quando e PorqueTiago Albineli Motta
 
Introdução a JavaScript
Introdução a JavaScriptIntrodução a JavaScript
Introdução a JavaScriptBruno Catão
 
Testes unitários como ferramentas de design de código
Testes unitários como ferramentas de design de códigoTestes unitários como ferramentas de design de código
Testes unitários como ferramentas de design de códigoPaula Grangeiro
 
Qualidade no desenvolvimento de software com PHPUnit
Qualidade no desenvolvimento de software com PHPUnitQualidade no desenvolvimento de software com PHPUnit
Qualidade no desenvolvimento de software com PHPUnitDiego Tremper
 
[GUTS-RS] Evento Abril 2018 - Qualidade de código para automação de testes
[GUTS-RS] Evento Abril 2018 - Qualidade de código para automação de testes[GUTS-RS] Evento Abril 2018 - Qualidade de código para automação de testes
[GUTS-RS] Evento Abril 2018 - Qualidade de código para automação de testesGUTS-RS
 
Grails parte 1 - introdução
Grails   parte 1 - introduçãoGrails   parte 1 - introdução
Grails parte 1 - introduçãoJosino Rodrigues
 
Relato Sobre a Migração de uma Aplicação Legada para Rails
Relato Sobre a Migração de uma Aplicação Legada para RailsRelato Sobre a Migração de uma Aplicação Legada para Rails
Relato Sobre a Migração de uma Aplicação Legada para RailsCássio Marques
 
Lista de exercicios algoritmos resolvida-
Lista de exercicios   algoritmos  resolvida-Lista de exercicios   algoritmos  resolvida-
Lista de exercicios algoritmos resolvida-Mauro Pereira
 
Criando sua própria linguagem de programação
Criando sua própria linguagem de programaçãoCriando sua própria linguagem de programação
Criando sua própria linguagem de programaçãoronaldoferraz
 

Semelhante a Testes automatizados (20)

Cucumber Best Practices
Cucumber Best PracticesCucumber Best Practices
Cucumber Best Practices
 
GraphQL e APIs: como manter a qualidade?
GraphQL e APIs: como manter a qualidade?GraphQL e APIs: como manter a qualidade?
GraphQL e APIs: como manter a qualidade?
 
TDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no AndroidTDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no Android
 
TDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no AndroidTDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no Android
 
Introdução ao JS1.pptx
Introdução ao JS1.pptxIntrodução ao JS1.pptx
Introdução ao JS1.pptx
 
04_Introducao_JavaScript.pdf
04_Introducao_JavaScript.pdf04_Introducao_JavaScript.pdf
04_Introducao_JavaScript.pdf
 
Introdução à Linguagem de programação Python
Introdução à Linguagem de programação PythonIntrodução à Linguagem de programação Python
Introdução à Linguagem de programação Python
 
Design Patterns em Ruby
Design Patterns em RubyDesign Patterns em Ruby
Design Patterns em Ruby
 
Testes unitários e de integração: Quando e Porque
Testes unitários e de integração: Quando e PorqueTestes unitários e de integração: Quando e Porque
Testes unitários e de integração: Quando e Porque
 
Introdução a JavaScript
Introdução a JavaScriptIntrodução a JavaScript
Introdução a JavaScript
 
Testes unitários como ferramentas de design de código
Testes unitários como ferramentas de design de códigoTestes unitários como ferramentas de design de código
Testes unitários como ferramentas de design de código
 
Qualidade no desenvolvimento de software com PHPUnit
Qualidade no desenvolvimento de software com PHPUnitQualidade no desenvolvimento de software com PHPUnit
Qualidade no desenvolvimento de software com PHPUnit
 
Construcao de Algoritmos - Aula 05
Construcao de Algoritmos - Aula 05Construcao de Algoritmos - Aula 05
Construcao de Algoritmos - Aula 05
 
[GUTS-RS] Evento Abril 2018 - Qualidade de código para automação de testes
[GUTS-RS] Evento Abril 2018 - Qualidade de código para automação de testes[GUTS-RS] Evento Abril 2018 - Qualidade de código para automação de testes
[GUTS-RS] Evento Abril 2018 - Qualidade de código para automação de testes
 
Grails parte 1 - introdução
Grails   parte 1 - introduçãoGrails   parte 1 - introdução
Grails parte 1 - introdução
 
DDD > Experiências
DDD > ExperiênciasDDD > Experiências
DDD > Experiências
 
Aplicacoes Rapidas Para Web Com Django
Aplicacoes Rapidas Para Web Com DjangoAplicacoes Rapidas Para Web Com Django
Aplicacoes Rapidas Para Web Com Django
 
Relato Sobre a Migração de uma Aplicação Legada para Rails
Relato Sobre a Migração de uma Aplicação Legada para RailsRelato Sobre a Migração de uma Aplicação Legada para Rails
Relato Sobre a Migração de uma Aplicação Legada para Rails
 
Lista de exercicios algoritmos resolvida-
Lista de exercicios   algoritmos  resolvida-Lista de exercicios   algoritmos  resolvida-
Lista de exercicios algoritmos resolvida-
 
Criando sua própria linguagem de programação
Criando sua própria linguagem de programaçãoCriando sua própria linguagem de programação
Criando sua própria linguagem de programação
 

Testes automatizados

  • 1. Testes Automatizados Usando Ruby on Rails, RSpec e Cucumber
  • 2. “Inspecionar para previnir defeitos é bom; Inspecionar para encontrar defeitos é desperdício” Shigeo Shingo
  • 3. De onde veio? A ascensão das metodologias ágeis Documentação Desatualizada A “queima de documentação”
  • 4. Pra que serve? Auxiliar nas Mudanças ou Refactoring Rastreabilidade Design
  • 5. O que é? Caixa-Branca *Normalmente feito pelo próprio Desenvolvedor Comparação de resultados
  • 6. Exemplo describe Calculadora do it "soma entre 1 e 1 deve ser 2" do (1+1).should eq(2) end end
  • 8. Quando deve ser feito? Antes, durante e depois
  • 12. Testes Unitários Unidade é a menor parte testável de um software. Consigo encontrar o erro com mais eficiência. Como “escapar” da dependência entre as camadas?
  • 13. Stub Methods Simula o comportamento de um código existente. Reduz o tempo de execução. Isola o teste.
  • 14. O Método def create @sorteio = Sorteio.new(params[:sorteio]) if @sorteio.save redirect_to @sorteio, notice: 'Sorteio criado.' else render action: "new" end end
  • 15. O Teste context "se sorteio for salvo com sucesso" do before do Sorteio.any_instance.stub(:save).and_return(true) end it "deve enviar pra tela de sorteios" do post :create, :id => 1 response.should redirect_to sorteios_path end end
  • 16. Mock Objects Objetos “de mentira” ou objetos substitutos. Permitem isolar as classes de um sistema de forma bastante simples.
  • 17. O Método def sortear @sorteio = Sorteio.find(params[:id]) @sorteio.sortear redirect_to sorteio_path(@sorteio_id), notice: 'Sorteio realizado.' end
  • 18. O Teste before do @sorteio = mock('Sorteio') @sorteio.stub(:sortear) Sorteio.stub(:find).and_return(@sorteio) end it "deve mostrar mensagem de sorteio realizado" do get :sortear, :id => 1 flash[:notice].should == "Sorteio realizado." end
  • 19. Message Expectations Cria um Stub Method Cria Expectativas
  • 20. O Método def edit @sorteio = Sorteio.find(params[:id]) end
  • 21. O Teste it "popula sorteio com o sorteio enviado" do sorteio = mock('Sorteio') Sorteio.should_receive(:find).with('1') .and_return(sorteio) get :edit, :id => 1 assigns[:sorteio].should == sorteio end
  • 22. Testando Controllers Redirecionamentos e Parâmetros de Tela. Não deve invocar o model “de verdade”.
  • 23. context "se concorrente não for salvo" do before do @concorrente_mock.stub(:save).and_return(false) end it "deve enviar pra tela de apresentação do sorteio deste concorrente" do post :create, :sorteio_id => 1 response.should redirect_to sorteio_path(1) end it "deve enviar uma notificação de Houve um erro na criação do Concorrente." do post :create, :sorteio_id => 1 flash[:notice].should == "Houve um erro na criação do Concorrente." end end
  • 24. Rotas Sorteando::Application.routes.draw do resources :sorteios do member do get :sortear end resources :concorrentes, :only => [:new, :create, :destroy] end root :to => 'sorteios#index' end
  • 25. Testando Rotas it "routes to #create" do post("/sorteios/1/concorrentes").should route_to("concorrentes#create", :sorteio_id => "1") end it "routes to #destroy" do delete("/sorteios/1/concorrentes/2").should route_to("concorrentes#destroy", :sorteio_id => "1", :id => "2") end it "routes to #index" do get("/sorteios/1/concorrentes").should_not be_routable end
  • 26. Testes de Models Objetos Reais. Usar somente as propriedades necessárias. Validação de Campo Obrigatório.
  • 27. Factory Teste mais limpo. Código desnecessário “escondido”.
  • 28. #sorteio.rb FactoryGirl.define do factory :sorteio do sequence(:nome) { |n| "sorteio_#{n}" } qtd_premios 1 end end #concorrente.rb FactoryGirl.define do factory :concorrente do sequence(:nome) { |n| "nome_#{n}" } sequence(:email) { |n| "nome_#{n}@email.com" } association :sorteio end end
  • 29. Usando Factory Girl before do @sorteio = FactoryGirl.create(:sorteio, :qtd_premios => 2) conc1 = FactoryGirl.create(:concorrente, :sorteio => @sorteio) conc2 = FactoryGirl.create(:concorrente, :sorteio => @sorteio) conc3 = FactoryGirl.create(:concorrente, :sorteio => @sorteio) end
  • 30. describe "Validations" do it { should validate_presence_of(:nome).with_message(/é um campo obrigatório/) } it { should validate_presence_of(:qtd_premios).with_message(/é um campo obrigatório/) } end it "sortear com quantidade menor que a quantidade de prêmios" do sorteio = FactoryGirl.create(:sorteio, :qtd_premios => 3) conc1 = FactoryGirl.create(:concorrente, :sorteio => sorteio) conc2 = FactoryGirl.create(:concorrente, :sorteio => sorteio) sorteio.sortear sorteio.vencedores.should have(2).vencedores end
  • 32. describe "sorteios/index" do it "mostrar titulo Sorteios" do assign :sorteios, [] render rendered.should have_content("Sorteios") end it "mostrar listagem de sorteios" do assign :sorteios, [ FactoryGirl.build(:sorteio, :id => '1', :nome => 'mega sena da virada') ] render rendered.should have_selector("tr > td") do |td| td.should have_content('mega sena da virada') end end end
  • 33. Code Coverage Verificar se cada linha do software esta “coberta” por, pelo menos, 1 teste.
  • 35. Linhas de Código X Linhas de Teste
  • 37.
  • 38. Teste Falho describe "#eh_vencedor?" do sorteio = FactoryGirl.create(:sorteio) concorrente = FactoryGirl.create(:concorrente, :sorteio => sorteio) concorrente.eh_vencedor?.should == true end
  • 40. Refactoring e teste volta a Falhar def eh_vencedor? VencedorSorteio.where(:concorrente_id => self).exists? end
  • 41. Teste “Passando” Novamente it "#eh_vencedor?" do sorteio = FactoryGirl.create(:sorteio) concorrente = FactoryGirl.create(:concorrente, :sorteio => sorteio) concorrente.eh_vencedor?.should == false end
  • 42. Refactoring describe "#eh_vencedor?" do it "Se não venceu o sorteio, retorna falso" do sorteio = FactoryGirl.create(:sorteio) concorrente = FactoryGirl.create(:concorrente, :sorteio => sorteio) concorrente.eh_vencedor?.should == false end it "Se venceu o sorteio, retorna verdadeiro" do sorteio = FactoryGirl.create(:sorteio) concorrente = FactoryGirl.create(:concorrente, :sorteio => sorteio) sorteio.vencedores << concorrente sorteio.save concorrente.eh_vencedor?.should == true end end
  • 43. TDD feito ... mas caberiam mais iterações
  • 44. Testes de Integração Camadas interagem. Encontra erros que o teste unitário não encontra. Ineficiente para “apontar” o erro.
  • 45. Caso: Cadastro de Sorteio
  • 46. Usando o Capybara it "fluxo completo de cadastro" do visit "/sorteios" click_link('+') fill_in('Nome', :with => 'Livro de Testes Automatizados') fill_in('Qtd de Premios', :with => '1') click_button('Novo') page.should have_content("Sorteio criado.") page.should have_content("Livro de Testes Automatizados") page.should have_content("Concorrentes: +") end
  • 47. Testes de Aceitação Caixa-Preta Pode ser criado por um Não- Programador
  • 48. Criando Steps Dado /^que estou na página "(.*?)"$/ do |pagina| visit pagina end Então /^devo ver o texto "(.*?)"$/ do |texto| page.should have_content(texto) end Quando /^clicar no link "(.*?)"$/ do |link| click_link(link) end Quando /^clicar no botao "(.*?)"$/ do |botao| click_button(botao) end
  • 49. Usando o Cucumber Cenário: Cadastrando um sorteio Dado que estou na página "/sorteios" Quando clicar no link "+" Então devo mudar a pagina Quando preencher o campo "Nome" com "Livro de Testes Automatizados" E preencher o campo "Qtd de Premios" com "1" E clicar no botao "Novo" Então devo mudar a pagina Então devo ver o texto "Sorteio criado." E devo ver o texto "Livro de Testes Automatizados" E devo ver o texto "Concorrentes: +"
  • 50. Integração Continua Membros de um time integram seu trabalho frequentemente. Podem haver multiplas integrações por dia. Cada integração é verificada por um build automatizado.

Notas do Editor

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n