SlideShare une entreprise Scribd logo
1  sur  94
Télécharger pour lire hors ligne
Desenvolvimento
Baseado em Testes
RSpec - Doubles
Eduardo Mendes
edumendes@gmail.com
@dudumendes




Introdução
@dudumendes




Introdução


O que se quer de um bom projeto
Princípios para alcançar
Situações que esclareçam
@dudumendes




RSpec::Mocks
@dudumendes




Criando doubles
método double

 algum_double = double(“um_double”)
 algum_stub = stub(“um_stub”)
 algum_mock = mock(“um_mock”)


   Argumento string é opcional, mas recomendado
     pode ser utilizado um símbolo
   Utilizado na mensagens de falha
   Geram instâncias de RSpec::Mocks::Mock
@dudumendes




Métodos Stubs

Método em que se pode programar uma resposta pré-
definida de um objeto,
  que será retornada durante a execução de exemplo
  utiliza-se quando não se tem expectativas sobre a
  execução
@dudumendes




Stub com classes inexistentes
@dudumendes




         Classe inexistente
                                 Identificador do mock
describe "classe Candidato" do
                                     métodos e retornos
	 it "retorna nome e partido" do
	 	 candidato = mock(:candidato)
	 	 candidato.stub(:nome => "Luiz Augusto",
                    :partido => "PRAONDEEH")

	 	 expect(candidato.nome).to eql("Luiz Augusto")
	 	 expect(candidato.partido).to eql("PRAONDEEH")
	 end
end
@dudumendes




  Classe inexistente / atalho
describe "classe Candidato" do    Identificador do mock
	 it "retorna nome e partido" do       métodos e retornos
	 	 candidato = mock(:candidato,
                      :nome => "Luiz Augusto",
                      :partido => "PRAONDEEH")
	 	
	 	 expect(candidato.nome).to eql("Luiz Augusto")
	 	 expect(candidato.partido).to eql("PRAONDEEH")
	 end
end
@dudumendes




candidato = mock(:candidato)
candidato.stub(:nome => "Luiz Augusto",
                    :email => "PRAONDEEH")

candidato = mock(:candidato)
candidato.stub(:nome).and_return("Luiz Augusto")
candidato.stub(:email).and_return("PRAONDEEH")

candidato = mock(:candidato,
                      :nome => "Luiz Augusto",
                      :partido => "PRAONDEEH")
@dudumendes




Utilizando o subject
@dudumendes




o método subject
Subject
 O subject de um exemplo é o objeto que está sendo
 descrito, exercitado
 Se o subject é uma classe chamada Usuario
   uma instância de Usuario é fornecida
   automaticamente pelo método subject
   subjects são instanciados nos blocos before
@dudumendes


describe Professor do
	 it "eh uma instancia de Professor" do
	 	 expect(subject).to be_a(Professor)
	 end
	
	 it "nao deve ser um aluno" do
	 	 expect(subject).not_to be_an(Aluno)
	 end
	
	 it "nao possui nome definido" do
	 	 expect(subject.nome).to be_nil
	 end
end                         Professor
	                            eh uma instancia de Professor
                               nao deve ser um aluno
                               nao possui nome definido
describe Candidato do                                         @dudumendes
	 it "possui email" do
	 	 subject.stub(:email => "luiz@email.com")
	 	 expect(subject.email).to eql("luiz@email.com")
	 end
	
	 it "pode ter partido nulo" do
	 	 subject.stub(:partido)
	 	 expect(subject.partido).to be_nil
	 end

	   it "possui email alternativo" do
	   	 subject.stub(:emailAlternativo) do
	   	 	 "luiz@alternativo.com"
	   	 end
	   	
	   	 expect(subject.emailAlternativo).to eql("luiz@alternativo.com")
	   end

	 it "possui email e partido" do
	 	 subject.stub(:email => "luiz@email.com", :partido => "PUTZ")
	 	 expect(subject.email).to eql("luiz@email.com")
	 	 expect(subject.partido).to eql("PUTZ")
	 end	
end
@dudumendes




Exercício 1
@dudumendes




Funcionario
Crie specs com mocks para a classe funcionario e
exercite expectativas em valores pré-configurados
  Faça os testes falharem e passarem para comparar
  os resultados
  Crie 02 versões
    um spec com uma classe que não existe
    e outro com utilizando o subject
@dudumendes




método and_return
@dudumendes




retornando vários valores
método and_return




 O and_return
   é uma alternativa para definição do valor a ser
   retornado
   possibilita a passagem de vários valores
describe UrnaEletronica do
	 it "retorna um voto" do
	 	 subject.stub(:apurar).and_return("Candidato 1")
	 	 expect(subject.apurar).to eql("Candidato 1")
	 end
end
describe UrnaEletronica do
	 it "retorna votos em sequencia" do
	 	 subject.stub(:apurar).and_return("C1", "C2", "C3")
	 	
	 	 expect(subject.apurar).to eql("C1")
	 	 expect(subject.apurar).to eql("C2")
	 	 expect(subject.apurar).to eql("C3")
	 end
end
@dudumendes




método stub_chain
@dudumendes




testando a intimidade
método stub_chain




 O stub_chain
   permite verificar o valor final retornado de uma
   chamada em cadeia de métodos
describe "classe Estacao" do
	 it "retorna a previsao de temperatura maxima" do
	 	 subject.stub_chain(:termometro, :maxima => 32)
	 	 expect(subject.termometro.maxima).to eql(32)
	 end
	
	 it "retorna a previsao de temperatura minima" do
	 	 subject.stub_chain(:termometro, :minima => 32)
	 	 expect(subject.termometro.minima).to eql(32)
	 end
end
@dudumendes




método any_instance
@dudumendes




testando instâncias aleatórias
método any_instance




 O any_instance
   cria expectativas sobre qualquer objeto de um classe
describe Eleitor do
	 it "deve votar" do
	 	 Eleitor.any_instance.stub(:votar => true)
	 	
	 	 eleitor = Eleitor.new
	 	 expect(eleitor.votar).to be_true
	 	
	 	 novo_eleitor = Eleitor.new
	 	 expect(novo_eleitor.votar).to be_true
	 	
	 end
end
@dudumendes




Passando argumentos
@dudumendes




passando argumentos
método with

 O with
   passa os parâmetros que devem ser passados a um
   método de stub
     valor
     hash
     anything, any_args, hash_including(),
     hash_not_including(), instance_of
describe Eleitor do
	 it "deve votar" do
	
	 Eleitor.any_instance.stub(:votar).with(:voto).and_return(true)
	 	 eleitor = Eleitor.new
	 	 expect(eleitor.votar(:voto)).to be_true
	 	
	 	 novo_eleitor = Eleitor.new
	 	 expect(novo_eleitor.votar(:voto)).to be_true
	 	
	 end
end
describe Candidato do
	 it "inicializa com um numero" do
	 	 Candidato.stub(:new).with(:numero => 99)
	 	 Candidato.new :numero => 99
    end
end
it "inicializa com qualquer valor" do
	 	 Candidato.stub(:new).with(any_args)

	 	 Candidato.new
	 	 Candidato.new(:nome => "Valor", :idade => 19)
	 end
it "inicializa com nome especifico" do
	 	 Candidato.stub(:new).with(
           hash_including(:nome => "Joao Luiz"))

	 	 Candidato.new(:nome => "Joao Luiz", :idade => 19)
	 end
it "inicializa com nome especifico" do
	 	 Candidato.stub(:new).with(
           hash_not_including(:nome => "Joao Luiz"))

	 	 Candidato.new(:idade => 19)
	 end
it "escreve um nome" do
	 	 subject.stub(:nome=).with(/Joao/)

	 	 subject.nome= "Joao Luiz"
end
it "o nome deve ser uma String" do
	 	 subject.stub(:nome=).with(instance_of(String))

	 	 subject.nome= 3
	 end
it "deve ser ficha limpa" do
	 	 subject.stub(:ficha_limpa=).with(boolean)

	 	 subject.ficha_limpa=true
	 end
describe Candidato do
	 it "inicializa com qualquer valor" do
	 	 Candidato.stub(:new).with(anything)

	 	 Candidato.new(:nome => "Valor", :idade => 19)
	 end
end
@dudumendes




Retorno dependente do argumento
describe "Bar" do                              @dudumendes



	 it "so pode vender para maior de 18" do
	 	 cliente = double(:cliente)
	 	
	 	 cliente.stub(:beber) do |idade|
	 	 	 if idade >= 18
	 	 	 	 "OK"
	 	 	 else
	 	 	 	 "ERROR"
	 	 	 end
	 	 end
	 	
	 	 expect(cliente.beber(20)).to eql "OK"
	 	 expect(cliente.beber(10)).to eql "ERROR"
	 end
end
@dudumendes




Stub de exceções
describe Eleitor do
  it "raises" do
    subject.stub(:idade).and_raise("Nao implementado")
	   expect { subject.idade }.to raise_error("Nao implementado")
  end

  it "throws" do
    subject.stub(:votar).and_throw(:nao_comparecimento)
    expect { subject.votar }.to throw_symbol(:nao_comparecimento)
	 end
end
@dudumendes




Combinando classes
@dudumendes




describe Inscricao do
	 it "utiliza o nome do candidato no cabecalho" do

	 	 candidato = double("candidato")
	 	 candidato.stub(:nome).and_return("Luiz")

	 	 inscricao = Inscricao.new(candidato)
	 	 expect(inscricao.gerar).to eql "Inscricao de Luiz"

	 end
end
@dudumendes



describe Inscricao do
	 it "utiliza o nome do candidato no cabecalho" do
	 	 candidato = double("candidato")
	 	 candidato.stub(:nome).and_return("Luiz")

	 	 inscricao = Inscricao.new(candidato)
	 	 expect(inscricao.gerar).to eql "Inscricao de Luiz"
	 end
end

Inscricao: sujeito
Candidato: não é o foco do exemplo, coloborador
imediato

Teste double para atuar como um candidato
@dudumendes




Exercício 2
@dudumendes




Inscricao



 A partir do spec da Inscricao, crie uma classe Inscricao
 que faça o teste passar
@dudumendes




describe Inscricao do
	 it "utiliza o nome do candidato no cabecalho" do
	 	 candidato = double("candidato")
	 	 candidato.stub(:nome).and_return("Luiz")

	 	 inscricao = Inscricao.new(candidato)
	 	 expect(inscricao.gerar).to eql "Inscricao de Luiz"
	 end
end
@dudumendes




Estratégias
 Triangulação
   Criar um outro exemplo utilizando um valor diferente que
   força a generalização do método


 Verificacar duplicação
   Verifica-se que "Inscricao de Luiz" é uma duplicação
     aparece no spec e no método
     consequência: remoção
@dudumendes




Estratégias

 Triangulação
   Exige 02 exemplos para que o sujeito tenha o
   comportamento esperado
 Verificacar duplicação
   Pode legar valores “hard-coded” à implementação
@dudumendes




Message Expectations
@dudumendes




Expectativas de mensagens
método should_receive




 should_receive
   caso a mensagem programada nunca seja chamada
     o método lançará um erro
     o teste falhará
@dudumendes




describe Inscricao do
	 it "utiliza o nome do candidato no cabecalho" do
	 	 candidato = double("candidato")
	 	 candidato.should_receive(:nome).and_return("Luiz")

	 	 inscricao = Inscricao.new(candidato)

	 	 expect(inscricao.gerar).to eql "Inscricao de Luiz"
	 end
end
@dudumendes



class Inscricao
	 def initialize(candidato)
	 	 @candidato = candidato
	 end
	
	 def gerar
	 	 "Inscricao de Luiz"
	 end
end

      Failure/Error: candidato.should_receive(:nome).and_return("Luiz")
        (Double "candidato").nome(any args)
            expected: 1 time
            received: 0 times
      # ./inscricao_spec_2.rb:14:in `block (2 levels) in <top (required)>'

      Finished in 0.00216 seconds
      1 example, 1 failure
@dudumendes




Stubs + Message Expectations
@dudumendes




Stubs + Message Expectations


 O sentido de existir métodos que retornam o mesmo
 objeto
   dar mais semântica ao teste
   identificar sujeito e colaboradores
   intenção incorporada no código
@dudumendes




it "cria um log quando o gerar eh chamado" do
	 candidato = stub("candidato")
	 candidato.stub(:nome).and_return("Luiz")

	 logger = mock("logger")
	 inscricao = Inscricao.new(candidato, logger)
	
	 logger.should_receive(:log).with("Inscricao de Luiz")
	
	 inscricao.gerar
	 	
end
@dudumendes




Intenção no código
Sujeito
  Inscrição
Colaborador primário
  logger -- mock
Colaborador secundário
  Candidato -- stub
@dudumendes




Exercício 3
@dudumendes




Inscricao



 Adicione o exemplo do log no spec e o faça passar
@dudumendes




Counts
@dudumendes




Counts

should_receive
  A expectativa default gerada por uma chamada a
  should_receive é que a mensagem seja chamada
  apenas 01 única vez
  é possível configurar o número de vezes através de
  métodos como exactly(), at_least(), at_most(),
  once, twice, combinados com o método times
@dudumendes




describe "classe Aluno" do
	 it "chama new" do
	 	 aluno = double(:aluno)
	 	 aluno.should_receive(:nome).and_return("Jessica")
	 	
	 	 expect(aluno.nome).to eql "Jessica"
	 	
	 end
	
end
@dudumendes




describe "classe Aluno" do
	 it "chama new" do
	 	 aluno = double(:aluno)
	 	 aluno.should_receive(:nome).and_return("Jessica")
	 	
	 	 expect(aluno.nome).to eql "Jessica"
	 	 expect(aluno.nome).to eql "Jessica"
	 end
	
end
@dudumendes




                     exactly().times
describe "classe Aluno" do
	 it "chama new" do
	 	 aluno = double(:aluno)
	 	 aluno.should_receive(:nome)
       .and_return("Jessica").exactly(1).times
	 	
	 	 expect(aluno.nome).to eql "Jessica"
	 	
	 end
	
end
@dudumendes




                     at_most().times
describe "Rede" do
	 it "deve ser solicitadas no maximo 5 conexoes" do
	 	 rede = double(:rede)
	 	 rede.should_receive(:open_connection).at_most(4).times
	 	
	 	 rede.open_connection
	 	 rede.open_connection
	 	 rede.open_connection
	 	 rede.open_connection
	 	
	 end
end
@dudumendes




                      at_least().times
describe "Rede" do
	 it "deve ser solicitadas no maximo 5 conexoes" do
	 	 rede = double(:rede)
	
	 rede.should_receive(:open_connection).at_least(2).times
	 	
	 	 rede.open_connection
	 	 rede.open_connection
	 	 rede.open_connection
	 	 rede.open_connection
	 	
	 end
end
@dudumendes




                         once, twice
describe "Conta" do
	 it "deve gerar extrato 01 vez" do
	 	 conta = double(:conta)
	 	 conta.should_receive(:gerar_extrato).once
	 	 conta.gerar_extrato
	 end

	 it "deve checar valor 02 vezes" do
	 	 conta = double(:conta)
	 	 conta.should_receive(:checar_valor).twice

	 	 conta.checar_valor
	 	 conta.checar_valor
	 end
@dudumendes




it "nao deve abrir conexao apos ping falso" do
	 @rede.stub(:ping).and_return(false)

	 @rede.should_receive(:open_connection).exactly(0).times
	 	 	
	 @rede.open_connection if @rede.ping
end
@dudumendes




Expectativas negativas
@dudumendes




Expectativas negativas
should_not_receive




 should_not_receive
   Utilizado quando não queremos que determinado
   sujeito receba uma mensagem durante o exemplo
@dudumendes




it "nao deve abrir conexao apos ping falso" do
	 @rede.stub(:ping).and_return(false)

	 @rede.should_not_receive(:open_connection)
	 	 	
	 @rede.open_connection if @rede.ping
end


it "nao deve abrir conexao apos ping falso" do
	 @rede.stub(:ping).and_return(false)

	 @rede.should_receive(:open_connection).never
	 	 	
	 @rede.open_connection if @rede.ping
end
@dudumendes




Mensagem ordenadas
it   "deve fazer campanha antes de votar" do
	   	    subject.stub(:fazer_campanha).ordered
	   	    subject.stub(:votar).ordered
	   	
	   	    subject.fazer_campanha
	   	    subject.votar

	 end
@dudumendes




Exercício 4
@dudumendes




Transferencia
 Contexto
   Testar a transferencia de valores entre 02 contas
   A transferência é realizada por um objeto chamado
   Transferencia
   O objeto guarda as 02 contas e executa uma
   transferência de valores entre elas
   O sujeito a se testar é o objeto Transferencia
   As contas ainda não estão implementadas
@dudumendes




Transferencia
 Exemplos
   o objeto Transferencia deve ser criado com 01 conta de origem, 01 conta de
   destino e um valor
   ao se executar a transferência, a conta de origem deve receber a mensagem
   transferir
   o 1.º argumento deve ser a conta de destino
   o 2.º argumento deve uma instância de Fixnum
   o 2.º argumento deve ter o valor
   deve ser lançado um erro com a mensagem “Saldo insuficiente”, caso o saldo
   da conta de origem seja menor que o valor solicitado
   o saldo deve ser conferido antes de transferir
@dudumendes




Utilização de Mocks
@dudumendes




Isolar dependências

Código fracamente acoplado
  possui dependências
  Se os objetos são fáceis e “baratos” de construir
    não utilize mocks ou stubs
@dudumendes




Isolar dependências
Dependências problemáticas
    configuração e construção cara
    funcionamento lento
    dependência de sistemas externos
      rede, servidores, sistema de arquivos
  Mock para isolar os exemplos das dependências e
  incrementar potenciais pontos de falha
@dudumendes




                               BD
          Interface para BD

Sujeito
          Interface de rede   Web
@dudumendes




                           Stub
                    Interface para BD
Exemplo   Sujeito
                           Stub
                    Interface de rede
@dudumendes



Isolação de comportamentos
não determinísticos

 Dependência de sistemas externos
   pode ser fonte de não determinismo
       arquivos corrompidos, falhas de disco, time out
       de rede
     MOCK e obtenha um ambiente controlado
@dudumendes




Não determinismo local


     Sujeito   Dado
@dudumendes




                    Stub do
Exemplo   Sujeito    Dado
                              3,5,6,6,6,7,10
@dudumendes



Progresso sem
implementações

Às vezes, dependemos de comportamentos de
objetos que outros times não implementaram ainda
  As interfaces podem já ter sido projetadas
  Oportunidade para explorar dependências e
  possibilidades de interfaces alternativas
@dudumendes




Descobrimento de interface

Ao exercitar a implementação de um objeto
  pode-se descobrir que ele necessita de
  comportamento de um outro que ainda não existe
    método não pensado na fase de projeto
    até mesmo objeto
@dudumendes




Focos
@dudumendes




Foco no Papel


Mockar objetos permite a concentração no que
importa
  no que o objeto faz e não no que ele é
@dudumendes




it "cria um log quando o gerar eh chamado" do
	 candidato = stub("candidato")
	 candidato.stub(:nome).and_return("Luiz")

	 logger = mock("logger")
	 inscricao = Inscricao.new(candidato, logger)
	
	 logger.should_receive(:log).with("Inscricao de Luiz")
	
	 inscricao.gerar
	 	
end
@dudumendes




Focar na interação
ao invés do estado


 Sistemas orientados a objetos dizem respeito à
 interfaces e interações
    O estado não faz parte do comportamento
    observável
    Exemplos serão menos frágeis
      se evitar o foco no estado
@dudumendes




describe Inscricao do
	 it "utiliza o nome do candidato no cabecalho" do
	 	 candidato = stub("candidato", :nome => "Luiz")
	 	
	 	 inscricao = Inscricao.new(candidato)

	 	 expect(inscricao.gerar).to eql "Inscricao de Luiz"
	 end
end
@dudumendes




describe Inscricao do
	 it "utiliza o nome do candidato no cabecalho" do
	 	 candidato = double("candidato")
	 	 candidato.should_receive(:nome).and_return("Luiz")

	 	 inscricao = Inscricao.new(candidato)

	 	 expect(inscricao.gerar).to eql "Inscricao de Luiz"
	 end
end
@dudumendes




Focar na interação
ao invés do estado
@dudumendes




Bibliografia

 FOWLER, Martin. “Mocks aren’t Stubs”.
 FREEMAN, Steve; PRYCE, Nat. Growing Object-
 Oriented Software, Guiaded by Tests. Addison-Wesley.
 MESZAROS, Gerard. xUnit Test Patterns:
 RefactoringTest Code. Addison-Wesley: 2007
 MESZAROS, Gerard. xUnitTest Patterns.com. http://
 xunitpatterns.com/

Contenu connexe

Tendances

Zend Framework - PHPSP - 2009
Zend Framework - PHPSP - 2009Zend Framework - PHPSP - 2009
Zend Framework - PHPSP - 2009silva.edgar
 
Perl Moderno, dia4
Perl Moderno, dia4Perl Moderno, dia4
Perl Moderno, dia4garux
 
Perl Moderno, dia3
Perl Moderno, dia3Perl Moderno, dia3
Perl Moderno, dia3garux
 
6. Caracteres; Tipos char e int; Tipos de valor e de referência – Fundamentos...
6. Caracteres; Tipos char e int; Tipos de valor e de referência – Fundamentos...6. Caracteres; Tipos char e int; Tipos de valor e de referência – Fundamentos...
6. Caracteres; Tipos char e int; Tipos de valor e de referência – Fundamentos...Manuel Menezes de Sequeira
 
Perl Moderno, dia2
Perl Moderno, dia2Perl Moderno, dia2
Perl Moderno, dia2garux
 
ORM: Sendo produtivo com NHibernate
ORM: Sendo produtivo com NHibernateORM: Sendo produtivo com NHibernate
ORM: Sendo produtivo com NHibernateJuliano Oliveira
 

Tendances (9)

Introdução à Linguagem Ruby
Introdução à Linguagem RubyIntrodução à Linguagem Ruby
Introdução à Linguagem Ruby
 
Zend Framework - PHPSP - 2009
Zend Framework - PHPSP - 2009Zend Framework - PHPSP - 2009
Zend Framework - PHPSP - 2009
 
Perl Moderno, dia4
Perl Moderno, dia4Perl Moderno, dia4
Perl Moderno, dia4
 
Perl Moderno, dia3
Perl Moderno, dia3Perl Moderno, dia3
Perl Moderno, dia3
 
SQL - Banco de Dados Biblioteca
SQL - Banco de Dados BibliotecaSQL - Banco de Dados Biblioteca
SQL - Banco de Dados Biblioteca
 
6. Caracteres; Tipos char e int; Tipos de valor e de referência – Fundamentos...
6. Caracteres; Tipos char e int; Tipos de valor e de referência – Fundamentos...6. Caracteres; Tipos char e int; Tipos de valor e de referência – Fundamentos...
6. Caracteres; Tipos char e int; Tipos de valor e de referência – Fundamentos...
 
Perl Moderno, dia2
Perl Moderno, dia2Perl Moderno, dia2
Perl Moderno, dia2
 
ORM: Sendo produtivo com NHibernate
ORM: Sendo produtivo com NHibernateORM: Sendo produtivo com NHibernate
ORM: Sendo produtivo com NHibernate
 
Seletores css
Seletores cssSeletores css
Seletores css
 

En vedette

Evolucao de software - parte 1
Evolucao de software - parte 1Evolucao de software - parte 1
Evolucao de software - parte 1Eduardo Mendes
 
Evolucao de software - parte 2
Evolucao de software - parte 2Evolucao de software - parte 2
Evolucao de software - parte 2Eduardo Mendes
 
Teste de Software - parte 1
Teste de Software - parte 1Teste de Software - parte 1
Teste de Software - parte 1Eduardo Mendes
 
Engenharia de Requisitos
Engenharia de RequisitosEngenharia de Requisitos
Engenharia de RequisitosEduardo Mendes
 
TDD - Prática com RSpec
TDD - Prática com RSpecTDD - Prática com RSpec
TDD - Prática com RSpecEduardo Mendes
 
Desenvolvimento Web com PHP parte 7
Desenvolvimento Web com PHP parte 7Desenvolvimento Web com PHP parte 7
Desenvolvimento Web com PHP parte 7Eduardo Mendes
 
TDD Projeto e Estrategias
TDD Projeto e EstrategiasTDD Projeto e Estrategias
TDD Projeto e EstrategiasEduardo Mendes
 
Testes de Software parte 2
Testes de Software parte 2Testes de Software parte 2
Testes de Software parte 2Eduardo Mendes
 
Academia do Arquiteto Globalcode
Academia do Arquiteto GlobalcodeAcademia do Arquiteto Globalcode
Academia do Arquiteto GlobalcodeGlobalcode
 
Acesso a banco de dados com JDBC
Acesso a banco de dados com JDBCAcesso a banco de dados com JDBC
Acesso a banco de dados com JDBCEduardo Mendes
 
Java Web 4 - Servlets e JSP 2
Java Web 4 - Servlets e JSP 2Java Web 4 - Servlets e JSP 2
Java Web 4 - Servlets e JSP 2Eduardo Mendes
 
The Power of Collaboration to Build Your Own Startup
The Power of Collaboration to Build Your Own StartupThe Power of Collaboration to Build Your Own Startup
The Power of Collaboration to Build Your Own StartupTaufan Erfiyanto
 
Desenvolvimento web com PHP parte 4
Desenvolvimento web com PHP parte 4Desenvolvimento web com PHP parte 4
Desenvolvimento web com PHP parte 4Eduardo Mendes
 
Turbinando o desenvolvimento com Eclipse
Turbinando o desenvolvimento com EclipseTurbinando o desenvolvimento com Eclipse
Turbinando o desenvolvimento com EclipseMarcos Sousa
 

En vedette (20)

Introdução ao TDD
Introdução ao TDDIntrodução ao TDD
Introdução ao TDD
 
Evolucao de software - parte 1
Evolucao de software - parte 1Evolucao de software - parte 1
Evolucao de software - parte 1
 
Evolucao de software - parte 2
Evolucao de software - parte 2Evolucao de software - parte 2
Evolucao de software - parte 2
 
Teste de Software - parte 1
Teste de Software - parte 1Teste de Software - parte 1
Teste de Software - parte 1
 
Engenharia de Requisitos
Engenharia de RequisitosEngenharia de Requisitos
Engenharia de Requisitos
 
TDD - Prática com RSpec
TDD - Prática com RSpecTDD - Prática com RSpec
TDD - Prática com RSpec
 
Html Aula 1 - parte 2
Html Aula 1 - parte 2Html Aula 1 - parte 2
Html Aula 1 - parte 2
 
Academia java intensivo
Academia java intensivoAcademia java intensivo
Academia java intensivo
 
Desenvolvimento Web com PHP parte 7
Desenvolvimento Web com PHP parte 7Desenvolvimento Web com PHP parte 7
Desenvolvimento Web com PHP parte 7
 
TDD Projeto e Estrategias
TDD Projeto e EstrategiasTDD Projeto e Estrategias
TDD Projeto e Estrategias
 
Testes de Software parte 2
Testes de Software parte 2Testes de Software parte 2
Testes de Software parte 2
 
Academia do Arquiteto Globalcode
Academia do Arquiteto GlobalcodeAcademia do Arquiteto Globalcode
Academia do Arquiteto Globalcode
 
AngularJS - Rotas
AngularJS - RotasAngularJS - Rotas
AngularJS - Rotas
 
Acesso a banco de dados com JDBC
Acesso a banco de dados com JDBCAcesso a banco de dados com JDBC
Acesso a banco de dados com JDBC
 
Java Web 4 - Servlets e JSP 2
Java Web 4 - Servlets e JSP 2Java Web 4 - Servlets e JSP 2
Java Web 4 - Servlets e JSP 2
 
The Power of Collaboration to Build Your Own Startup
The Power of Collaboration to Build Your Own StartupThe Power of Collaboration to Build Your Own Startup
The Power of Collaboration to Build Your Own Startup
 
Desenvolvimento web com PHP parte 4
Desenvolvimento web com PHP parte 4Desenvolvimento web com PHP parte 4
Desenvolvimento web com PHP parte 4
 
Rails - parte 1
Rails - parte 1Rails - parte 1
Rails - parte 1
 
Jquery
JqueryJquery
Jquery
 
Turbinando o desenvolvimento com Eclipse
Turbinando o desenvolvimento com EclipseTurbinando o desenvolvimento com Eclipse
Turbinando o desenvolvimento com Eclipse
 

Similaire à RSpec com doubles

Curso Java Básico - Aula 03
Curso Java Básico - Aula 03Curso Java Básico - Aula 03
Curso Java Básico - Aula 03Natanael Fonseca
 
Testes automatizados
Testes automatizadosTestes automatizados
Testes automatizadosRodrigo Maia
 
Lista IV de Programação Orientada a Objetos
Lista IV de Programação Orientada a ObjetosLista IV de Programação Orientada a Objetos
Lista IV de Programação Orientada a Objetosunifesptk
 
mod5-estruturas-dadosdinamicas
mod5-estruturas-dadosdinamicasmod5-estruturas-dadosdinamicas
mod5-estruturas-dadosdinamicasdiogoa21
 
Exemplos registros e funções
Exemplos registros e funçõesExemplos registros e funções
Exemplos registros e funçõesCarla Lee
 
Javascript Recuperando Dados De Formularios
Javascript    Recuperando Dados De FormulariosJavascript    Recuperando Dados De Formularios
Javascript Recuperando Dados De Formulariosguestd9e271
 
Curso de Java (Parte 4)
Curso de Java (Parte 4)Curso de Java (Parte 4)
Curso de Java (Parte 4)Mario Sergio
 
Classe integer-float-byte-short-long-double
Classe integer-float-byte-short-long-doubleClasse integer-float-byte-short-long-double
Classe integer-float-byte-short-long-doublePAULO Moreira
 
Java - Aula 2 - Orientado a Objetos
Java - Aula 2 - Orientado a ObjetosJava - Aula 2 - Orientado a Objetos
Java - Aula 2 - Orientado a ObjetosMoises Omena
 
Java básico - Módulo 08 - Introdução à programação orientada à objetos oo - c...
Java básico - Módulo 08 - Introdução à programação orientada à objetos oo - c...Java básico - Módulo 08 - Introdução à programação orientada à objetos oo - c...
Java básico - Módulo 08 - Introdução à programação orientada à objetos oo - c...Professor Samuel Ribeiro
 
Substituir Type Codes "com" Classe
Substituir Type Codes "com" ClasseSubstituir Type Codes "com" Classe
Substituir Type Codes "com" ClasseAntonio Spinelli
 
Java - Visão geral e Exercícios
Java - Visão geral e ExercíciosJava - Visão geral e Exercícios
Java - Visão geral e ExercíciosArthur Emanuel
 
AULA 1 - Classes e Objetos com codigicação Java.ppt
AULA 1 - Classes e Objetos com codigicação Java.pptAULA 1 - Classes e Objetos com codigicação Java.ppt
AULA 1 - Classes e Objetos com codigicação Java.pptJoberthSilva
 

Similaire à RSpec com doubles (20)

MongoDB - Iniciando e Conhecendo
MongoDB - Iniciando e ConhecendoMongoDB - Iniciando e Conhecendo
MongoDB - Iniciando e Conhecendo
 
Curso Java Básico - Aula 03
Curso Java Básico - Aula 03Curso Java Básico - Aula 03
Curso Java Básico - Aula 03
 
Testes automatizados
Testes automatizadosTestes automatizados
Testes automatizados
 
Lista IV de Programação Orientada a Objetos
Lista IV de Programação Orientada a ObjetosLista IV de Programação Orientada a Objetos
Lista IV de Programação Orientada a Objetos
 
mod5-estruturas-dadosdinamicas
mod5-estruturas-dadosdinamicasmod5-estruturas-dadosdinamicas
mod5-estruturas-dadosdinamicas
 
JQuery
JQuery JQuery
JQuery
 
Exemplos registros e funções
Exemplos registros e funçõesExemplos registros e funções
Exemplos registros e funções
 
Javascript Recuperando Dados De Formularios
Javascript    Recuperando Dados De FormulariosJavascript    Recuperando Dados De Formularios
Javascript Recuperando Dados De Formularios
 
Curso de Java (Parte 4)
Curso de Java (Parte 4)Curso de Java (Parte 4)
Curso de Java (Parte 4)
 
Classe integer-float-byte-short-long-double
Classe integer-float-byte-short-long-doubleClasse integer-float-byte-short-long-double
Classe integer-float-byte-short-long-double
 
Java - Aula 2 - Orientado a Objetos
Java - Aula 2 - Orientado a ObjetosJava - Aula 2 - Orientado a Objetos
Java - Aula 2 - Orientado a Objetos
 
Vetores e Matrizes.pdf
Vetores e Matrizes.pdfVetores e Matrizes.pdf
Vetores e Matrizes.pdf
 
Math
MathMath
Math
 
Minicurso de Expressões Regulares
Minicurso de Expressões RegularesMinicurso de Expressões Regulares
Minicurso de Expressões Regulares
 
Python 02
Python 02Python 02
Python 02
 
Java básico - Módulo 08 - Introdução à programação orientada à objetos oo - c...
Java básico - Módulo 08 - Introdução à programação orientada à objetos oo - c...Java básico - Módulo 08 - Introdução à programação orientada à objetos oo - c...
Java básico - Módulo 08 - Introdução à programação orientada à objetos oo - c...
 
Substituir Type Codes "com" Classe
Substituir Type Codes "com" ClasseSubstituir Type Codes "com" Classe
Substituir Type Codes "com" Classe
 
PHP Básico - Parte 3
PHP Básico - Parte 3PHP Básico - Parte 3
PHP Básico - Parte 3
 
Java - Visão geral e Exercícios
Java - Visão geral e ExercíciosJava - Visão geral e Exercícios
Java - Visão geral e Exercícios
 
AULA 1 - Classes e Objetos com codigicação Java.ppt
AULA 1 - Classes e Objetos com codigicação Java.pptAULA 1 - Classes e Objetos com codigicação Java.ppt
AULA 1 - Classes e Objetos com codigicação Java.ppt
 

Plus de Eduardo Mendes

JavaScript - Introdução com Orientação a Objetos
JavaScript - Introdução com Orientação a ObjetosJavaScript - Introdução com Orientação a Objetos
JavaScript - Introdução com Orientação a ObjetosEduardo Mendes
 
Angular JS - Fundamentos
Angular JS - FundamentosAngular JS - Fundamentos
Angular JS - FundamentosEduardo Mendes
 
Singleton - Padrão de Projeto
Singleton - Padrão de ProjetoSingleton - Padrão de Projeto
Singleton - Padrão de ProjetoEduardo Mendes
 
Introdução à Internet, Http e HTML
Introdução à Internet, Http e HTMLIntrodução à Internet, Http e HTML
Introdução à Internet, Http e HTMLEduardo Mendes
 
Estimativas de Esforço - Engenharia de Software
Estimativas de Esforço - Engenharia de SoftwareEstimativas de Esforço - Engenharia de Software
Estimativas de Esforço - Engenharia de SoftwareEduardo Mendes
 
Java web 6 JSP Expression Language Taglib parte 2
Java web 6 JSP Expression Language Taglib parte 2Java web 6 JSP Expression Language Taglib parte 2
Java web 6 JSP Expression Language Taglib parte 2Eduardo Mendes
 
Validações no Ruby on Rails
Validações no Ruby on Rails Validações no Ruby on Rails
Validações no Ruby on Rails Eduardo Mendes
 
Padroes Template-Method (Método Gabarito)
Padroes Template-Method (Método Gabarito)Padroes Template-Method (Método Gabarito)
Padroes Template-Method (Método Gabarito)Eduardo Mendes
 
PHP básico para iniciantes
PHP básico para iniciantesPHP básico para iniciantes
PHP básico para iniciantesEduardo Mendes
 

Plus de Eduardo Mendes (20)

JavaScript - Introdução com Orientação a Objetos
JavaScript - Introdução com Orientação a ObjetosJavaScript - Introdução com Orientação a Objetos
JavaScript - Introdução com Orientação a Objetos
 
Angular JS - Fundamentos
Angular JS - FundamentosAngular JS - Fundamentos
Angular JS - Fundamentos
 
Singleton - Padrão de Projeto
Singleton - Padrão de ProjetoSingleton - Padrão de Projeto
Singleton - Padrão de Projeto
 
Layout Fluido
Layout FluidoLayout Fluido
Layout Fluido
 
Web Design Responsivo
Web Design ResponsivoWeb Design Responsivo
Web Design Responsivo
 
Html - Aula 4
Html - Aula 4Html - Aula 4
Html - Aula 4
 
Html - Aula 3
Html - Aula 3Html - Aula 3
Html - Aula 3
 
Introdução à Internet, Http e HTML
Introdução à Internet, Http e HTMLIntrodução à Internet, Http e HTML
Introdução à Internet, Http e HTML
 
ExtJS-4
ExtJS-4ExtJS-4
ExtJS-4
 
Jquery 2
Jquery 2Jquery 2
Jquery 2
 
Estimativas de Esforço - Engenharia de Software
Estimativas de Esforço - Engenharia de SoftwareEstimativas de Esforço - Engenharia de Software
Estimativas de Esforço - Engenharia de Software
 
Java web 6 JSP Expression Language Taglib parte 2
Java web 6 JSP Expression Language Taglib parte 2Java web 6 JSP Expression Language Taglib parte 2
Java web 6 JSP Expression Language Taglib parte 2
 
Validações no Ruby on Rails
Validações no Ruby on Rails Validações no Ruby on Rails
Validações no Ruby on Rails
 
Padrão Iterator
Padrão IteratorPadrão Iterator
Padrão Iterator
 
Padroes Template-Method (Método Gabarito)
Padroes Template-Method (Método Gabarito)Padroes Template-Method (Método Gabarito)
Padroes Template-Method (Método Gabarito)
 
Padrão Command
Padrão CommandPadrão Command
Padrão Command
 
Padrão Fachada
Padrão FachadaPadrão Fachada
Padrão Fachada
 
Padrão Adapter
Padrão AdapterPadrão Adapter
Padrão Adapter
 
Web Design Responsivo
Web Design ResponsivoWeb Design Responsivo
Web Design Responsivo
 
PHP básico para iniciantes
PHP básico para iniciantesPHP básico para iniciantes
PHP básico para iniciantes
 

Dernier

ATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docx
ATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docxATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docx
ATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docx2m Assessoria
 
ATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docx
ATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docxATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docx
ATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docx2m Assessoria
 
Assessement Boas Praticas em Kubernetes.pdf
Assessement Boas Praticas em Kubernetes.pdfAssessement Boas Praticas em Kubernetes.pdf
Assessement Boas Praticas em Kubernetes.pdfNatalia Granato
 
ATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docx
ATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docxATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docx
ATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docx2m Assessoria
 
Boas práticas de programação com Object Calisthenics
Boas práticas de programação com Object CalisthenicsBoas práticas de programação com Object Calisthenics
Boas práticas de programação com Object CalisthenicsDanilo Pinotti
 
Padrões de Projeto: Proxy e Command com exemplo
Padrões de Projeto: Proxy e Command com exemploPadrões de Projeto: Proxy e Command com exemplo
Padrões de Projeto: Proxy e Command com exemploDanilo Pinotti
 

Dernier (6)

ATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docx
ATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docxATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docx
ATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docx
 
ATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docx
ATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docxATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docx
ATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docx
 
Assessement Boas Praticas em Kubernetes.pdf
Assessement Boas Praticas em Kubernetes.pdfAssessement Boas Praticas em Kubernetes.pdf
Assessement Boas Praticas em Kubernetes.pdf
 
ATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docx
ATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docxATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docx
ATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docx
 
Boas práticas de programação com Object Calisthenics
Boas práticas de programação com Object CalisthenicsBoas práticas de programação com Object Calisthenics
Boas práticas de programação com Object Calisthenics
 
Padrões de Projeto: Proxy e Command com exemplo
Padrões de Projeto: Proxy e Command com exemploPadrões de Projeto: Proxy e Command com exemplo
Padrões de Projeto: Proxy e Command com exemplo
 

RSpec com doubles

  • 1. Desenvolvimento Baseado em Testes RSpec - Doubles Eduardo Mendes edumendes@gmail.com
  • 3. @dudumendes Introdução O que se quer de um bom projeto Princípios para alcançar Situações que esclareçam
  • 5. @dudumendes Criando doubles método double algum_double = double(“um_double”) algum_stub = stub(“um_stub”) algum_mock = mock(“um_mock”) Argumento string é opcional, mas recomendado pode ser utilizado um símbolo Utilizado na mensagens de falha Geram instâncias de RSpec::Mocks::Mock
  • 6. @dudumendes Métodos Stubs Método em que se pode programar uma resposta pré- definida de um objeto, que será retornada durante a execução de exemplo utiliza-se quando não se tem expectativas sobre a execução
  • 8. @dudumendes Classe inexistente Identificador do mock describe "classe Candidato" do métodos e retornos it "retorna nome e partido" do candidato = mock(:candidato) candidato.stub(:nome => "Luiz Augusto", :partido => "PRAONDEEH") expect(candidato.nome).to eql("Luiz Augusto") expect(candidato.partido).to eql("PRAONDEEH") end end
  • 9. @dudumendes Classe inexistente / atalho describe "classe Candidato" do Identificador do mock it "retorna nome e partido" do métodos e retornos candidato = mock(:candidato, :nome => "Luiz Augusto", :partido => "PRAONDEEH") expect(candidato.nome).to eql("Luiz Augusto") expect(candidato.partido).to eql("PRAONDEEH") end end
  • 10. @dudumendes candidato = mock(:candidato) candidato.stub(:nome => "Luiz Augusto", :email => "PRAONDEEH") candidato = mock(:candidato) candidato.stub(:nome).and_return("Luiz Augusto") candidato.stub(:email).and_return("PRAONDEEH") candidato = mock(:candidato, :nome => "Luiz Augusto", :partido => "PRAONDEEH")
  • 12. @dudumendes o método subject Subject O subject de um exemplo é o objeto que está sendo descrito, exercitado Se o subject é uma classe chamada Usuario uma instância de Usuario é fornecida automaticamente pelo método subject subjects são instanciados nos blocos before
  • 13. @dudumendes describe Professor do it "eh uma instancia de Professor" do expect(subject).to be_a(Professor) end it "nao deve ser um aluno" do expect(subject).not_to be_an(Aluno) end it "nao possui nome definido" do expect(subject.nome).to be_nil end end Professor eh uma instancia de Professor nao deve ser um aluno nao possui nome definido
  • 14. describe Candidato do @dudumendes it "possui email" do subject.stub(:email => "luiz@email.com") expect(subject.email).to eql("luiz@email.com") end it "pode ter partido nulo" do subject.stub(:partido) expect(subject.partido).to be_nil end it "possui email alternativo" do subject.stub(:emailAlternativo) do "luiz@alternativo.com" end expect(subject.emailAlternativo).to eql("luiz@alternativo.com") end it "possui email e partido" do subject.stub(:email => "luiz@email.com", :partido => "PUTZ") expect(subject.email).to eql("luiz@email.com") expect(subject.partido).to eql("PUTZ") end end
  • 16. @dudumendes Funcionario Crie specs com mocks para a classe funcionario e exercite expectativas em valores pré-configurados Faça os testes falharem e passarem para comparar os resultados Crie 02 versões um spec com uma classe que não existe e outro com utilizando o subject
  • 18. @dudumendes retornando vários valores método and_return O and_return é uma alternativa para definição do valor a ser retornado possibilita a passagem de vários valores
  • 19. describe UrnaEletronica do it "retorna um voto" do subject.stub(:apurar).and_return("Candidato 1") expect(subject.apurar).to eql("Candidato 1") end end
  • 20. describe UrnaEletronica do it "retorna votos em sequencia" do subject.stub(:apurar).and_return("C1", "C2", "C3") expect(subject.apurar).to eql("C1") expect(subject.apurar).to eql("C2") expect(subject.apurar).to eql("C3") end end
  • 22. @dudumendes testando a intimidade método stub_chain O stub_chain permite verificar o valor final retornado de uma chamada em cadeia de métodos
  • 23. describe "classe Estacao" do it "retorna a previsao de temperatura maxima" do subject.stub_chain(:termometro, :maxima => 32) expect(subject.termometro.maxima).to eql(32) end it "retorna a previsao de temperatura minima" do subject.stub_chain(:termometro, :minima => 32) expect(subject.termometro.minima).to eql(32) end end
  • 25. @dudumendes testando instâncias aleatórias método any_instance O any_instance cria expectativas sobre qualquer objeto de um classe
  • 26. describe Eleitor do it "deve votar" do Eleitor.any_instance.stub(:votar => true) eleitor = Eleitor.new expect(eleitor.votar).to be_true novo_eleitor = Eleitor.new expect(novo_eleitor.votar).to be_true end end
  • 28. @dudumendes passando argumentos método with O with passa os parâmetros que devem ser passados a um método de stub valor hash anything, any_args, hash_including(), hash_not_including(), instance_of
  • 29. describe Eleitor do it "deve votar" do Eleitor.any_instance.stub(:votar).with(:voto).and_return(true) eleitor = Eleitor.new expect(eleitor.votar(:voto)).to be_true novo_eleitor = Eleitor.new expect(novo_eleitor.votar(:voto)).to be_true end end
  • 30. describe Candidato do it "inicializa com um numero" do Candidato.stub(:new).with(:numero => 99) Candidato.new :numero => 99 end end
  • 31. it "inicializa com qualquer valor" do Candidato.stub(:new).with(any_args) Candidato.new Candidato.new(:nome => "Valor", :idade => 19) end
  • 32. it "inicializa com nome especifico" do Candidato.stub(:new).with( hash_including(:nome => "Joao Luiz")) Candidato.new(:nome => "Joao Luiz", :idade => 19) end
  • 33. it "inicializa com nome especifico" do Candidato.stub(:new).with( hash_not_including(:nome => "Joao Luiz")) Candidato.new(:idade => 19) end
  • 34. it "escreve um nome" do subject.stub(:nome=).with(/Joao/) subject.nome= "Joao Luiz" end
  • 35. it "o nome deve ser uma String" do subject.stub(:nome=).with(instance_of(String)) subject.nome= 3 end
  • 36. it "deve ser ficha limpa" do subject.stub(:ficha_limpa=).with(boolean) subject.ficha_limpa=true end
  • 37. describe Candidato do it "inicializa com qualquer valor" do Candidato.stub(:new).with(anything) Candidato.new(:nome => "Valor", :idade => 19) end end
  • 39. describe "Bar" do @dudumendes it "so pode vender para maior de 18" do cliente = double(:cliente) cliente.stub(:beber) do |idade| if idade >= 18 "OK" else "ERROR" end end expect(cliente.beber(20)).to eql "OK" expect(cliente.beber(10)).to eql "ERROR" end end
  • 41. describe Eleitor do it "raises" do subject.stub(:idade).and_raise("Nao implementado") expect { subject.idade }.to raise_error("Nao implementado") end it "throws" do subject.stub(:votar).and_throw(:nao_comparecimento) expect { subject.votar }.to throw_symbol(:nao_comparecimento) end end
  • 43. @dudumendes describe Inscricao do it "utiliza o nome do candidato no cabecalho" do candidato = double("candidato") candidato.stub(:nome).and_return("Luiz") inscricao = Inscricao.new(candidato) expect(inscricao.gerar).to eql "Inscricao de Luiz" end end
  • 44. @dudumendes describe Inscricao do it "utiliza o nome do candidato no cabecalho" do candidato = double("candidato") candidato.stub(:nome).and_return("Luiz") inscricao = Inscricao.new(candidato) expect(inscricao.gerar).to eql "Inscricao de Luiz" end end Inscricao: sujeito Candidato: não é o foco do exemplo, coloborador imediato Teste double para atuar como um candidato
  • 46. @dudumendes Inscricao A partir do spec da Inscricao, crie uma classe Inscricao que faça o teste passar
  • 47. @dudumendes describe Inscricao do it "utiliza o nome do candidato no cabecalho" do candidato = double("candidato") candidato.stub(:nome).and_return("Luiz") inscricao = Inscricao.new(candidato) expect(inscricao.gerar).to eql "Inscricao de Luiz" end end
  • 48. @dudumendes Estratégias Triangulação Criar um outro exemplo utilizando um valor diferente que força a generalização do método Verificacar duplicação Verifica-se que "Inscricao de Luiz" é uma duplicação aparece no spec e no método consequência: remoção
  • 49. @dudumendes Estratégias Triangulação Exige 02 exemplos para que o sujeito tenha o comportamento esperado Verificacar duplicação Pode legar valores “hard-coded” à implementação
  • 51. @dudumendes Expectativas de mensagens método should_receive should_receive caso a mensagem programada nunca seja chamada o método lançará um erro o teste falhará
  • 52. @dudumendes describe Inscricao do it "utiliza o nome do candidato no cabecalho" do candidato = double("candidato") candidato.should_receive(:nome).and_return("Luiz") inscricao = Inscricao.new(candidato) expect(inscricao.gerar).to eql "Inscricao de Luiz" end end
  • 53. @dudumendes class Inscricao def initialize(candidato) @candidato = candidato end def gerar "Inscricao de Luiz" end end Failure/Error: candidato.should_receive(:nome).and_return("Luiz") (Double "candidato").nome(any args) expected: 1 time received: 0 times # ./inscricao_spec_2.rb:14:in `block (2 levels) in <top (required)>' Finished in 0.00216 seconds 1 example, 1 failure
  • 55. @dudumendes Stubs + Message Expectations O sentido de existir métodos que retornam o mesmo objeto dar mais semântica ao teste identificar sujeito e colaboradores intenção incorporada no código
  • 56. @dudumendes it "cria um log quando o gerar eh chamado" do candidato = stub("candidato") candidato.stub(:nome).and_return("Luiz") logger = mock("logger") inscricao = Inscricao.new(candidato, logger) logger.should_receive(:log).with("Inscricao de Luiz") inscricao.gerar end
  • 57. @dudumendes Intenção no código Sujeito Inscrição Colaborador primário logger -- mock Colaborador secundário Candidato -- stub
  • 59. @dudumendes Inscricao Adicione o exemplo do log no spec e o faça passar
  • 61. @dudumendes Counts should_receive A expectativa default gerada por uma chamada a should_receive é que a mensagem seja chamada apenas 01 única vez é possível configurar o número de vezes através de métodos como exactly(), at_least(), at_most(), once, twice, combinados com o método times
  • 62. @dudumendes describe "classe Aluno" do it "chama new" do aluno = double(:aluno) aluno.should_receive(:nome).and_return("Jessica") expect(aluno.nome).to eql "Jessica" end end
  • 63. @dudumendes describe "classe Aluno" do it "chama new" do aluno = double(:aluno) aluno.should_receive(:nome).and_return("Jessica") expect(aluno.nome).to eql "Jessica" expect(aluno.nome).to eql "Jessica" end end
  • 64. @dudumendes exactly().times describe "classe Aluno" do it "chama new" do aluno = double(:aluno) aluno.should_receive(:nome) .and_return("Jessica").exactly(1).times expect(aluno.nome).to eql "Jessica" end end
  • 65. @dudumendes at_most().times describe "Rede" do it "deve ser solicitadas no maximo 5 conexoes" do rede = double(:rede) rede.should_receive(:open_connection).at_most(4).times rede.open_connection rede.open_connection rede.open_connection rede.open_connection end end
  • 66. @dudumendes at_least().times describe "Rede" do it "deve ser solicitadas no maximo 5 conexoes" do rede = double(:rede) rede.should_receive(:open_connection).at_least(2).times rede.open_connection rede.open_connection rede.open_connection rede.open_connection end end
  • 67. @dudumendes once, twice describe "Conta" do it "deve gerar extrato 01 vez" do conta = double(:conta) conta.should_receive(:gerar_extrato).once conta.gerar_extrato end it "deve checar valor 02 vezes" do conta = double(:conta) conta.should_receive(:checar_valor).twice conta.checar_valor conta.checar_valor end
  • 68. @dudumendes it "nao deve abrir conexao apos ping falso" do @rede.stub(:ping).and_return(false) @rede.should_receive(:open_connection).exactly(0).times @rede.open_connection if @rede.ping end
  • 70. @dudumendes Expectativas negativas should_not_receive should_not_receive Utilizado quando não queremos que determinado sujeito receba uma mensagem durante o exemplo
  • 71. @dudumendes it "nao deve abrir conexao apos ping falso" do @rede.stub(:ping).and_return(false) @rede.should_not_receive(:open_connection) @rede.open_connection if @rede.ping end it "nao deve abrir conexao apos ping falso" do @rede.stub(:ping).and_return(false) @rede.should_receive(:open_connection).never @rede.open_connection if @rede.ping end
  • 73. it "deve fazer campanha antes de votar" do subject.stub(:fazer_campanha).ordered subject.stub(:votar).ordered subject.fazer_campanha subject.votar end
  • 75. @dudumendes Transferencia Contexto Testar a transferencia de valores entre 02 contas A transferência é realizada por um objeto chamado Transferencia O objeto guarda as 02 contas e executa uma transferência de valores entre elas O sujeito a se testar é o objeto Transferencia As contas ainda não estão implementadas
  • 76. @dudumendes Transferencia Exemplos o objeto Transferencia deve ser criado com 01 conta de origem, 01 conta de destino e um valor ao se executar a transferência, a conta de origem deve receber a mensagem transferir o 1.º argumento deve ser a conta de destino o 2.º argumento deve uma instância de Fixnum o 2.º argumento deve ter o valor deve ser lançado um erro com a mensagem “Saldo insuficiente”, caso o saldo da conta de origem seja menor que o valor solicitado o saldo deve ser conferido antes de transferir
  • 78. @dudumendes Isolar dependências Código fracamente acoplado possui dependências Se os objetos são fáceis e “baratos” de construir não utilize mocks ou stubs
  • 79. @dudumendes Isolar dependências Dependências problemáticas configuração e construção cara funcionamento lento dependência de sistemas externos rede, servidores, sistema de arquivos Mock para isolar os exemplos das dependências e incrementar potenciais pontos de falha
  • 80. @dudumendes BD Interface para BD Sujeito Interface de rede Web
  • 81. @dudumendes Stub Interface para BD Exemplo Sujeito Stub Interface de rede
  • 82. @dudumendes Isolação de comportamentos não determinísticos Dependência de sistemas externos pode ser fonte de não determinismo arquivos corrompidos, falhas de disco, time out de rede MOCK e obtenha um ambiente controlado
  • 84. @dudumendes Stub do Exemplo Sujeito Dado 3,5,6,6,6,7,10
  • 85. @dudumendes Progresso sem implementações Às vezes, dependemos de comportamentos de objetos que outros times não implementaram ainda As interfaces podem já ter sido projetadas Oportunidade para explorar dependências e possibilidades de interfaces alternativas
  • 86. @dudumendes Descobrimento de interface Ao exercitar a implementação de um objeto pode-se descobrir que ele necessita de comportamento de um outro que ainda não existe método não pensado na fase de projeto até mesmo objeto
  • 88. @dudumendes Foco no Papel Mockar objetos permite a concentração no que importa no que o objeto faz e não no que ele é
  • 89. @dudumendes it "cria um log quando o gerar eh chamado" do candidato = stub("candidato") candidato.stub(:nome).and_return("Luiz") logger = mock("logger") inscricao = Inscricao.new(candidato, logger) logger.should_receive(:log).with("Inscricao de Luiz") inscricao.gerar end
  • 90. @dudumendes Focar na interação ao invés do estado Sistemas orientados a objetos dizem respeito à interfaces e interações O estado não faz parte do comportamento observável Exemplos serão menos frágeis se evitar o foco no estado
  • 91. @dudumendes describe Inscricao do it "utiliza o nome do candidato no cabecalho" do candidato = stub("candidato", :nome => "Luiz") inscricao = Inscricao.new(candidato) expect(inscricao.gerar).to eql "Inscricao de Luiz" end end
  • 92. @dudumendes describe Inscricao do it "utiliza o nome do candidato no cabecalho" do candidato = double("candidato") candidato.should_receive(:nome).and_return("Luiz") inscricao = Inscricao.new(candidato) expect(inscricao.gerar).to eql "Inscricao de Luiz" end end
  • 94. @dudumendes Bibliografia FOWLER, Martin. “Mocks aren’t Stubs”. FREEMAN, Steve; PRYCE, Nat. Growing Object- Oriented Software, Guiaded by Tests. Addison-Wesley. MESZAROS, Gerard. xUnit Test Patterns: RefactoringTest Code. Addison-Wesley: 2007 MESZAROS, Gerard. xUnitTest Patterns.com. http:// xunitpatterns.com/