SlideShare uma empresa Scribd logo
1 de 40
TDD em C++
Thiago Delgado Pinto
   Parte 1 – Verificação de Estado
   Parte 2 – Verificação de Comportamento
Verificação de Estado
YAFFUT_CHECK( ok );
YAFFUT_EQUAL( e, o );
YAFFUT_UNEQUAL( e, o );
YAFFUT_FAIL( msg );
YAFFUT_ASSERT_THROW( func, e );
   No Desenvolvimento Guiado por Testes, a
    corretude de um software é verificada
    através da escrita de testes para o mesmo.

   Nesses testes, verificamos se algo funciona
    conforme o esperado.

   Essa expectativa é o que devemos criar no
    teste.
   Uma expectativa é uma suposição sobre
    como algo funciona.

   Por exemplo:
    Se você quiser fazer uma função que some
    dois números naturais e retorne essa soma.
    Você pode supor que dados dois números, por
    exemplo, 1 e 2, a função retorne 3.
void somaDoisNumerosNaturaisCorretamente()
{                                            Nome do Teste
    assert( soma( 1, 2 ) == 3 );
}

         A função assert recebe um valor booleano.
         Se for true, a função não faz nada.
         Se for false, ela interrompe a execução do
         programa informando a linha em que houve a
         falha na afirmação.
void somaDoisNumerosInteirosCorretamente()
{
    assert( soma( -1, -1 ) == -2 );   Suposições devem
    assert( soma( -1, 0 ) == -1 );    tentar exercitar
                                      combinações com
    assert( soma( -1, 1 ) == 0 );     valores mínimos,
    assert( soma( 0, 0 ) == 0 );      máximos e
    assert( soma( 0, 1 ) == 1 );      potencialmente
                                      problemáticos.
    assert( soma( 1, 1 ) == 2 );
}
 Devemos, porém, dividir os casos em mais de
    um teste.
void somaUsandoNumerosNegativosCorretamente()
{
    assert( soma( -1, -1 ) == -2 );
    assert( soma( -1, 1 ) == 0 );
}
void somaComZeroResultaNoProprioNumero()
{
  assert( soma( -1, 0 ) == -1 );
  assert( soma( 0, 0 ) == 0 );
  assert( soma( 0, 1 ) == 1 );
}
void somaUsandoNumerosPositivosCorretamente()
{
  assert( soma( 1, 1 ) == 2 );
  assert( soma( 1, -1 ) == 0 );
}
void chuteAltoTiraUmDecimoDaEnergia()
{
    Lutador a, b;
    a.DefinirEnergia( 100 );
    b.DesferirChuteAltoEm( a );
    assert( a.Energia() == 90 );
}
void transferenciaFazDebitarDaContaOrigem()
{
    Conta origem, destino;
    origem.DefinirSaldo( 10500 );
    double valorATransferir = 500;
    double saldoEsperadoAposTransferencia =
      origem.Saldo() – valorATransferir;
    origem.Transferir( destino, valorATransferir );
    assert( origem.Saldo() ==
      saldoEsperadoAposTransferencia );
}
void transferenciaFazCreditarNaContaDestino()
{
    Conta origem, destino;
    origem.DefinirSaldo( 10500 );
    destino.DefinirSaldo( 2000 );
    double valorATransferir = 500;
    double saldoEsperadoAposTransferencia =
      destino.Saldo() + valorATransferir;
    origem.Transferir( destino, valorATransferir );
    assert( destino.Saldo() ==
      saldoEsperadoAposTransferencia );
}
   O nome deve tentar explicar o que é
    verificado e qual o resultado esperado.

   Nunca tente explicar como é verificado.

   O nome pode ser bem longo.

   Não se preocupe, você nunca precisará
    digitá-lo novamente. 
   ligarNitroFazCarroAcelerarQuandoEmMovimento ()

   acelerarComFreioDeMaoLigadoFazRodasTraseiras
    Derraparem()

   finalizarVendaFazBaixarEstoqueDeItensVendidos()

   cairNoPrecipicioRetiraVidaDoJogador()
   Precisamos criar um programa que chame todos
    os nossos testes.
   Há frameworks (bibliotecas de código que
    podem ser estendidas) que podemos usar para
    simplificar esse processo.
   Usando um framework, nosso main não irá
    precisar fazer nada além de iniciar o framework.
   O framework se encarregará de chamar os
    testes.
1/6



   Yet Another Framework For Unit Testing

   É opensource
   É portátil (Windows,GNU/Linux,MacOS,...)
   É pequeno
   É simples
   É poderoso

   http://members.home.nl/rutger.van.beusekom/
2/6


   Para usar o Yaffut, basta incluir seu único arquivo de código:
#include <yaffut.h>
   Criar uma classe (vazia) que servirá para agrupar os testes:
class TesteContaBancaria {};
   Use a macro TEST que recebe por parâmetro o nome da classe de
    teste e o nome do teste. Ex:
TEST( TesteContaBancaria,
    transferenciaFazDebitarDaContaOrigem )
{
  ...
}
3/6


   No lugar de assert, use YAFFUT_CHECK.
#include <yaffut.h>
class TesteContaBancaria {};
TEST( TesteContaBancaria, transferenciaFazDebitarDaContaOrigem )
{
  Conta origem, destino;
  origem.DefinirSaldo( 10500 );
    double valorATransferir = 500;
    double saldoEsperadoAposTransferencia =
      origem.Saldo() – valorATransferir;
    origem.Transferir( destino, valorATransferir );
    YAFFUT_CHECK( origem.Saldo() ==
     saldoEsperadoAposTransferencia );
}
4/6


   Porém, para comparar igualdades, prefira YAFFUT_EQUAL.
   Recebe dois parâmetros: valor esperado e valor obtido.

TEST( TesteContaBancaria,
  transferenciaFazDebitarDaContaOrigem )
{
  Conta origem, destino;
  origem.DefinirSaldo( 10500 );
    double valorATransferir = 500;
    double saldoEsperadoAposTransferencia =
      origem.Saldo() – valorATransferir;
    origem.Transferir( destino, valorATransferir );
    YAFFUT_EQUAL( saldoEsperadoAposTransferencia,
      origem.Saldo() );
}
5/6



   Outras funções:

YAFFUT_UNEQUAL( esperado, obtido )
YAFFUT_FAIL( mensagem )
YAFFUT_ASSERT_THROW( método, exceção )
6/6


   Como pode ser o programa principal de teste:
#include <yaffut.h>
#include “TesteContaBancaria.h”
// ... outras bibliotecas de teste
int main(int argc, const char* argv[])
{
  return yaffut::Factory::Instance().Main (argc,
   argv);
}
   CppUnit
   CppUnitLite
   boost::test
   TUT
   CxxTest
   ...
Verificação de Comportamento
MockRepository mr;
Intf *intf = mr.InterfaceMock< Intf >();
mr.ExpectCall( intf, Intf::Method1 )
 .With( “hello” )
 .Return( 10 );
AClass ac;
ac.DoSomething( *intf );
   TDD serve não só para verificar valores, mas,
    principalmente, para verificar o
    comportamento de objetos em suas
    interações com outros objetos.

   Para isso, criamos objetos substitutos,
    chamados de Mocks, que simulam a
    execução de métodos reais.
1/10



   Se ao fazer uma classe TerminalBancario
    quisermos ter um método que permita
    imprimir o extrato de uma conta bancária.

   Como testar se o extrato foi impresso ?
    (Só olhar o papel saindo, certo?)

   E se não tivermos impressora disponível para
    verificar ?
2/10



   Precisamos mesmo da impressora, ou
    podemos apenas simular o comportamento
    que se espera dela ?

   Se estamos interessados em seu
    comportamento, e não em sua
    implementação, podemos representar a
    impressora como uma interface.
3/10



class ImpressoraExtrato {
public:
   // Retorna true se conseguir imprimir
   bool Imprimir(const ContaBancaria
    &conta) = 0;
};
4/10


   Então, podemos pensar que nosso terminal
    bancário tenha o seguinte método:
// Retorna true se conseguir imprimir
bool TerminalBancario::ImprimirExtrato(
 const ContaBancaria &conta,
 const ImpressoraExtrato &impressora);
   Não importa como essa impressora funciona,
    desde que ela diga que imprimiu, para o terminal
    está OK.
5/10


   Daí, podemos criar uma implementação falsa da
    impressora, para ser nossa substituta da
    impressora real:
class ImpressoraExtratoFalsa : public
   ImpressoraExtrato
{
   bool Imprimir(const ContaBancaria &conta)
   {
     return true; // Só diz que imprimiu !
   }
};
6/10


   Nosso teste pode ficar assim:
TEST( TesteContaBancaria, terminalConsegueImprimirExtrato )
{
  ContaBancaria conta;
  conta.Depositar( 1000 );
  conta.Sacar( 500 );
    ImpressoraExtrato *impressora =
      new ImpressoraExtratoFalsa();
    TerminalBancario terminal;
    bool imprimiu = terminal.Imprimir(conta, *impressora );
    delete impressora;
    YAFFUT_CHECK( imprimiu );
}
7/10


   Mas como saber se o terminal interagiu
    corretamente com a impressora ?
   Sabemos apenas que a impressora foi passada
    como parâmetro, mas como saber se ela foi
    usada ?
   Ou seja, se o terminal chamou o método
    Imprimir como esperado (uma vez, passando a
    conta como parâmetro) e obteve um resultado
    dela ?
8/10



   Podemos, em implementação falsa, criar um
    controle para saber se o método foi chamado
    como esperado.

   E depois, no teste, verificamos se o método
    Imprimir foi chamado.
9/10


class ImpressoraExtratoFalsa : public ImpressoraExtrato
{
  ImpressoraExtratoFalsa() {
    chamadasAImprimir = 0;
  }
  bool Imprimir(const ContaBancaria &conta) {
    chamadasAImprimir++;
     return true;
  }
 int ChamadasAImprimir() const {
   return chamadasAImprimir;
 }
private:
   int chamadasAImprimir;
};
10/10


   Nosso teste pode ficar assim:
TEST( TesteContaBancaria, terminalConsegueImprimirExtrato )
{
  ContaBancaria conta;
  conta.Depositar( 1000 );
  conta.Sacar( 500 );
    ImpressoraExtrato *impressora =
      new ImpressoraExtratoFalsa();
    TerminalBancario terminal;
    bool imprimiu = terminal.Imprimir(conta, *impressora );
    YAFFUT_EQUAL( 1, impressora->ChamadasAImprimir() );
    YAFFUT_CHECK( imprimiu );
    delete impressora;
}
   Ter que criar manualmente implementações
    falsas (classes falsas) e contabilizar a execução
    de cada método é trabalhoso.
   Porém, há frameworks de teste que permitem a
    criação automática de implementações falsas
    (chamadas de Mocks), bastando apenas definir
    o comportamento esperado dos métodos.
   A contabilização da chamada também é feita
    automaticamente.
   Em C++ há bons frameworks de teste
        automatizado, porém, poucos com recursos de
        criação automática de mocks:
           Isolator++
           AMOP
           MockitoPP
           HippoMocks
           etc.

       Adotaremos o HippoMocks com Yaffut1.
1. Veja análise em http://devhints.blogspot.com/2010/11/bons-frameworks-c-para-criacao.html
   Feito usando Yaffut (já vem com ele).
   É opensource.
   É simples.
   É poderoso.
   É portátil.
   http://www.assembla.com/spaces/hippomocks
   Sua classe principal é MockRepository, que
    permite criar um repositório de objetos falsos
    (mocks).

   Permite criação de mocks através do método
    InterfaceMock.

   Permite definir expectativas através do
    método ExpectCall.
TEST( TesteContaBancaria, terminalConsegueImprimirExtrato )
{
  ContaBancaria conta;
  conta.Depositar( 1000 );
  conta.Sacar( 500 );

    MockRepository mr; // Repositório de mocks
    ImpressoraExtrato *impressora =
      mr.InterfaceMock< ImpressoraExtrato >(); // Cria um mock
    // Cria a expectativa
    mr.ExpectCall( impressora, ImpressoraExtrato::Imprimir )
      .With( conta )
      .Return( true );

    TerminalBancario terminal;
    bool imprimiu = terminal.Imprimir(conta, *impressora );
    YAFFUT_CHECK( imprimiu );
    delete impressora;
    // Não precisa verificar NADA.
    // O framework verifica se a expectativa criada foi atendida!
}
TEST( TesteBomba, atirarNumaBombaFazExplodiLa )
{
  MockRepository mr; // Repositório de objetos falsos
    // Bomba falsa
    Bomba *bomba = mr.InterfaceMock< Bomba >();
    // Expectativa do que deve acontecer com a bomba
    // ao ser acertada por um tiro
    mr.ExpectCall( bomba, Bomba::Explodir );

    Jogador jogador;
    Revolver revolver( 38 );
    jogador.SegurarObjeto( revolver );
    revolver.AtirarNoObjeto( bomba ); // Deve fazê-la explodir
}
TDD em C++
Thiago Delgado Pinto

Mais conteúdo relacionado

Mais procurados

Aula 04 Estruturas de repetição 02 - Para Faça
Aula 04  Estruturas de repetição 02 - Para FaçaAula 04  Estruturas de repetição 02 - Para Faça
Aula 04 Estruturas de repetição 02 - Para FaçaEder Samaniego
 
mod3-programação-estruturada
mod3-programação-estruturadamod3-programação-estruturada
mod3-programação-estruturadadiogoa21
 
Curso de Shell Script 10/11
Curso de Shell Script 10/11Curso de Shell Script 10/11
Curso de Shell Script 10/11Rodrigo Silva
 
Algoritmos resolvidos lista 2
Algoritmos resolvidos lista 2Algoritmos resolvidos lista 2
Algoritmos resolvidos lista 2isa_ise
 
Algoritmos e Programação: Estruturas de repetição
Algoritmos e Programação: Estruturas de repetiçãoAlgoritmos e Programação: Estruturas de repetição
Algoritmos e Programação: Estruturas de repetiçãoAlex Camargo
 
Algoritmos e lp parte3-pseudocódigo
Algoritmos e lp parte3-pseudocódigoAlgoritmos e lp parte3-pseudocódigo
Algoritmos e lp parte3-pseudocódigoMauro Pereira
 
Estruturas de Repetição - FOR, WHILE e DO WHILE
Estruturas de Repetição - FOR, WHILE e DO WHILEEstruturas de Repetição - FOR, WHILE e DO WHILE
Estruturas de Repetição - FOR, WHILE e DO WHILENeto Côrtes
 
Introdução ao php
Introdução ao phpIntrodução ao php
Introdução ao phpTiago Davi
 
Manual-de-php
Manual-de-phpManual-de-php
Manual-de-phpdiogoa21
 
Algoritmos - Comandos de Repetição
Algoritmos - Comandos de RepetiçãoAlgoritmos - Comandos de Repetição
Algoritmos - Comandos de RepetiçãoElaine Cecília Gatto
 
M5-Desenvolvimento-Paginas-Web
M5-Desenvolvimento-Paginas-WebM5-Desenvolvimento-Paginas-Web
M5-Desenvolvimento-Paginas-Webdiogoa21
 
Comandos de Controle de Programa em C
Comandos de Controle de Programa em CComandos de Controle de Programa em C
Comandos de Controle de Programa em CElaine Cecília Gatto
 
8a. aula -_estrutura_de_controle_de_repeticao_-_while_java
8a. aula -_estrutura_de_controle_de_repeticao_-_while_java8a. aula -_estrutura_de_controle_de_repeticao_-_while_java
8a. aula -_estrutura_de_controle_de_repeticao_-_while_javaMirlem Pereira
 
Exercicios sequenciais
Exercicios sequenciaisExercicios sequenciais
Exercicios sequenciaisMirlem Pereira
 
Controle de Fluxo, Exceções, Assertivas
Controle de Fluxo, Exceções, AssertivasControle de Fluxo, Exceções, Assertivas
Controle de Fluxo, Exceções, AssertivasElenilson Vieira
 

Mais procurados (20)

Aula 04 Estruturas de repetição 02 - Para Faça
Aula 04  Estruturas de repetição 02 - Para FaçaAula 04  Estruturas de repetição 02 - Para Faça
Aula 04 Estruturas de repetição 02 - Para Faça
 
mod3-programação-estruturada
mod3-programação-estruturadamod3-programação-estruturada
mod3-programação-estruturada
 
Curso de Shell Script 10/11
Curso de Shell Script 10/11Curso de Shell Script 10/11
Curso de Shell Script 10/11
 
Algoritmos resolvidos lista 2
Algoritmos resolvidos lista 2Algoritmos resolvidos lista 2
Algoritmos resolvidos lista 2
 
Algoritmos e Programação: Estruturas de repetição
Algoritmos e Programação: Estruturas de repetiçãoAlgoritmos e Programação: Estruturas de repetição
Algoritmos e Programação: Estruturas de repetição
 
Java3
Java3Java3
Java3
 
Algoritmos e lp parte3-pseudocódigo
Algoritmos e lp parte3-pseudocódigoAlgoritmos e lp parte3-pseudocódigo
Algoritmos e lp parte3-pseudocódigo
 
Estruturas de Repetição - FOR, WHILE e DO WHILE
Estruturas de Repetição - FOR, WHILE e DO WHILEEstruturas de Repetição - FOR, WHILE e DO WHILE
Estruturas de Repetição - FOR, WHILE e DO WHILE
 
Introdução ao php
Introdução ao phpIntrodução ao php
Introdução ao php
 
Minicurso php
Minicurso phpMinicurso php
Minicurso php
 
Manual-de-php
Manual-de-phpManual-de-php
Manual-de-php
 
Algoritmos - Comandos de Repetição
Algoritmos - Comandos de RepetiçãoAlgoritmos - Comandos de Repetição
Algoritmos - Comandos de Repetição
 
Java4
Java4Java4
Java4
 
M5-Desenvolvimento-Paginas-Web
M5-Desenvolvimento-Paginas-WebM5-Desenvolvimento-Paginas-Web
M5-Desenvolvimento-Paginas-Web
 
Comandos de Controle de Programa em C
Comandos de Controle de Programa em CComandos de Controle de Programa em C
Comandos de Controle de Programa em C
 
Comandos de controle de fluxo do php
Comandos de controle de fluxo do phpComandos de controle de fluxo do php
Comandos de controle de fluxo do php
 
8a. aula -_estrutura_de_controle_de_repeticao_-_while_java
8a. aula -_estrutura_de_controle_de_repeticao_-_while_java8a. aula -_estrutura_de_controle_de_repeticao_-_while_java
8a. aula -_estrutura_de_controle_de_repeticao_-_while_java
 
Exercicios sequenciais
Exercicios sequenciaisExercicios sequenciais
Exercicios sequenciais
 
Algoritmos Aula 09
Algoritmos Aula 09Algoritmos Aula 09
Algoritmos Aula 09
 
Controle de Fluxo, Exceções, Assertivas
Controle de Fluxo, Exceções, AssertivasControle de Fluxo, Exceções, Assertivas
Controle de Fluxo, Exceções, Assertivas
 

Destaque

Command Design Pattern
Command Design PatternCommand Design Pattern
Command Design PatternRothana Choun
 
Bridge the PPC SEO Gap | SEMpdx | March 2015
Bridge the PPC SEO Gap | SEMpdx | March 2015Bridge the PPC SEO Gap | SEMpdx | March 2015
Bridge the PPC SEO Gap | SEMpdx | March 2015Craig Galyon
 
Taking a Quantum Leap with Html 5 WebSocket
Taking a Quantum Leap with Html 5 WebSocketTaking a Quantum Leap with Html 5 WebSocket
Taking a Quantum Leap with Html 5 WebSocketShahriar Hyder
 
Behavioral pattern By:-Priyanka Pradhan
Behavioral pattern By:-Priyanka PradhanBehavioral pattern By:-Priyanka Pradhan
Behavioral pattern By:-Priyanka PradhanPriyanka Pradhan
 
Command Design Pattern
Command Design PatternCommand Design Pattern
Command Design PatternShahriar Hyder
 
Datos de la encuesta
Datos de la encuestaDatos de la encuesta
Datos de la encuestacarolina2569
 
La sequia en rio hondo 2011
La sequia en rio hondo 2011La sequia en rio hondo 2011
La sequia en rio hondo 2011bermude85
 
Trends em Marketing
Trends em MarketingTrends em Marketing
Trends em MarketingGenaro Galli
 
Metodos y técnicas de estudio
Metodos y técnicas de estudioMetodos y técnicas de estudio
Metodos y técnicas de estudioaleytonpi
 
Aprendiendo a enseñar
Aprendiendo a enseñarAprendiendo a enseñar
Aprendiendo a enseñarpaulacardos
 
2º¿cómo se modificaron tus conceptos
2º¿cómo se modificaron tus conceptos2º¿cómo se modificaron tus conceptos
2º¿cómo se modificaron tus conceptosmisgladiola
 
Principios de calidad
Principios de calidadPrincipios de calidad
Principios de calidadcharoampuero
 
El pensamiento y las emociones
El pensamiento y las emocionesEl pensamiento y las emociones
El pensamiento y las emocionesEuler Ruiz
 

Destaque (20)

Command Pattern
Command PatternCommand Pattern
Command Pattern
 
Command Design Pattern
Command Design PatternCommand Design Pattern
Command Design Pattern
 
Command Pattern
Command PatternCommand Pattern
Command Pattern
 
Bridge the PPC SEO Gap | SEMpdx | March 2015
Bridge the PPC SEO Gap | SEMpdx | March 2015Bridge the PPC SEO Gap | SEMpdx | March 2015
Bridge the PPC SEO Gap | SEMpdx | March 2015
 
Taking a Quantum Leap with Html 5 WebSocket
Taking a Quantum Leap with Html 5 WebSocketTaking a Quantum Leap with Html 5 WebSocket
Taking a Quantum Leap with Html 5 WebSocket
 
Behavioral pattern By:-Priyanka Pradhan
Behavioral pattern By:-Priyanka PradhanBehavioral pattern By:-Priyanka Pradhan
Behavioral pattern By:-Priyanka Pradhan
 
Command pattern
Command patternCommand pattern
Command pattern
 
Command Design Pattern
Command Design PatternCommand Design Pattern
Command Design Pattern
 
Mec guia 1
Mec guia 1Mec guia 1
Mec guia 1
 
Datos de la encuesta
Datos de la encuestaDatos de la encuesta
Datos de la encuesta
 
La sequia en rio hondo 2011
La sequia en rio hondo 2011La sequia en rio hondo 2011
La sequia en rio hondo 2011
 
Trends em Marketing
Trends em MarketingTrends em Marketing
Trends em Marketing
 
Metodos y técnicas de estudio
Metodos y técnicas de estudioMetodos y técnicas de estudio
Metodos y técnicas de estudio
 
Aprendiendo a enseñar
Aprendiendo a enseñarAprendiendo a enseñar
Aprendiendo a enseñar
 
Entra na nosa biblioteca!
Entra na nosa biblioteca!Entra na nosa biblioteca!
Entra na nosa biblioteca!
 
2º¿cómo se modificaron tus conceptos
2º¿cómo se modificaron tus conceptos2º¿cómo se modificaron tus conceptos
2º¿cómo se modificaron tus conceptos
 
Principios de calidad
Principios de calidadPrincipios de calidad
Principios de calidad
 
Pac II Projetos Parte I
Pac II  Projetos   Parte IPac II  Projetos   Parte I
Pac II Projetos Parte I
 
Escuela
EscuelaEscuela
Escuela
 
El pensamiento y las emociones
El pensamiento y las emocionesEl pensamiento y las emociones
El pensamiento y las emociones
 

Semelhante a DOJO - TDD com C++

Semelhante a DOJO - TDD com C++ (20)

Ganhando tempo com casos de testes
Ganhando tempo com casos de testesGanhando tempo com casos de testes
Ganhando tempo com casos de testes
 
0000364 aula 5 estruturas de decisão
0000364 aula 5   estruturas de decisão0000364 aula 5   estruturas de decisão
0000364 aula 5 estruturas de decisão
 
Curso de Java (Parte 3)
 Curso de Java (Parte 3) Curso de Java (Parte 3)
Curso de Java (Parte 3)
 
Conceitos base de programação - parte 2
Conceitos base de programação - parte 2Conceitos base de programação - parte 2
Conceitos base de programação - parte 2
 
Curso Java #02 - Variáveis, Tipos e Estruturas de Controle
Curso Java #02 - Variáveis, Tipos e Estruturas de ControleCurso Java #02 - Variáveis, Tipos e Estruturas de Controle
Curso Java #02 - Variáveis, Tipos e Estruturas de Controle
 
Programacao orientada-a-objetos-java
Programacao orientada-a-objetos-javaProgramacao orientada-a-objetos-java
Programacao orientada-a-objetos-java
 
RevisãoCompactaFuncoesPonteiro.pptx
RevisãoCompactaFuncoesPonteiro.pptxRevisãoCompactaFuncoesPonteiro.pptx
RevisãoCompactaFuncoesPonteiro.pptx
 
Javascript manual
Javascript manualJavascript manual
Javascript manual
 
Repetições e vetores
Repetições e vetoresRepetições e vetores
Repetições e vetores
 
Estrutura de repetição
Estrutura de repetiçãoEstrutura de repetição
Estrutura de repetição
 
Aula1
Aula1Aula1
Aula1
 
Aula3
Aula3Aula3
Aula3
 
apostila C++
apostila C++apostila C++
apostila C++
 
Switchcase
SwitchcaseSwitchcase
Switchcase
 
Exemplos registros e funções
Exemplos registros e funçõesExemplos registros e funções
Exemplos registros e funções
 
Apostila script
Apostila scriptApostila script
Apostila script
 
Java script2
Java script2Java script2
Java script2
 
Aula 1 2
Aula 1 2Aula 1 2
Aula 1 2
 
Algoritmos - Aula 07 A - Lacos
Algoritmos - Aula 07 A - LacosAlgoritmos - Aula 07 A - Lacos
Algoritmos - Aula 07 A - Lacos
 
Aprendendo objective c - parte 1
Aprendendo objective c - parte 1Aprendendo objective c - parte 1
Aprendendo objective c - parte 1
 

Mais de thiagodp

Coding Dojo - Conceitos
Coding Dojo - ConceitosCoding Dojo - Conceitos
Coding Dojo - Conceitosthiagodp
 
Coding Dojo - Funcionamento
Coding Dojo - FuncionamentoCoding Dojo - Funcionamento
Coding Dojo - Funcionamentothiagodp
 
CEFET Coding Dojo - Divulgação
CEFET Coding Dojo - DivulgaçãoCEFET Coding Dojo - Divulgação
CEFET Coding Dojo - Divulgaçãothiagodp
 
CEFET Coding Dojo - Desafios
CEFET Coding Dojo - DesafiosCEFET Coding Dojo - Desafios
CEFET Coding Dojo - Desafiosthiagodp
 
TDD em C++
TDD em C++TDD em C++
TDD em C++thiagodp
 
I CEFET Coding Dojo - Divulgação
I CEFET Coding Dojo - DivulgaçãoI CEFET Coding Dojo - Divulgação
I CEFET Coding Dojo - Divulgaçãothiagodp
 

Mais de thiagodp (6)

Coding Dojo - Conceitos
Coding Dojo - ConceitosCoding Dojo - Conceitos
Coding Dojo - Conceitos
 
Coding Dojo - Funcionamento
Coding Dojo - FuncionamentoCoding Dojo - Funcionamento
Coding Dojo - Funcionamento
 
CEFET Coding Dojo - Divulgação
CEFET Coding Dojo - DivulgaçãoCEFET Coding Dojo - Divulgação
CEFET Coding Dojo - Divulgação
 
CEFET Coding Dojo - Desafios
CEFET Coding Dojo - DesafiosCEFET Coding Dojo - Desafios
CEFET Coding Dojo - Desafios
 
TDD em C++
TDD em C++TDD em C++
TDD em C++
 
I CEFET Coding Dojo - Divulgação
I CEFET Coding Dojo - DivulgaçãoI CEFET Coding Dojo - Divulgação
I CEFET Coding Dojo - Divulgação
 

DOJO - TDD com C++

  • 1. TDD em C++ Thiago Delgado Pinto
  • 2. Parte 1 – Verificação de Estado  Parte 2 – Verificação de Comportamento
  • 3. Verificação de Estado YAFFUT_CHECK( ok ); YAFFUT_EQUAL( e, o ); YAFFUT_UNEQUAL( e, o ); YAFFUT_FAIL( msg ); YAFFUT_ASSERT_THROW( func, e );
  • 4. No Desenvolvimento Guiado por Testes, a corretude de um software é verificada através da escrita de testes para o mesmo.  Nesses testes, verificamos se algo funciona conforme o esperado.  Essa expectativa é o que devemos criar no teste.
  • 5. Uma expectativa é uma suposição sobre como algo funciona.  Por exemplo: Se você quiser fazer uma função que some dois números naturais e retorne essa soma. Você pode supor que dados dois números, por exemplo, 1 e 2, a função retorne 3.
  • 6. void somaDoisNumerosNaturaisCorretamente() { Nome do Teste assert( soma( 1, 2 ) == 3 ); } A função assert recebe um valor booleano. Se for true, a função não faz nada. Se for false, ela interrompe a execução do programa informando a linha em que houve a falha na afirmação.
  • 7. void somaDoisNumerosInteirosCorretamente() { assert( soma( -1, -1 ) == -2 ); Suposições devem assert( soma( -1, 0 ) == -1 ); tentar exercitar combinações com assert( soma( -1, 1 ) == 0 ); valores mínimos, assert( soma( 0, 0 ) == 0 ); máximos e assert( soma( 0, 1 ) == 1 ); potencialmente problemáticos. assert( soma( 1, 1 ) == 2 ); }  Devemos, porém, dividir os casos em mais de um teste.
  • 8. void somaUsandoNumerosNegativosCorretamente() { assert( soma( -1, -1 ) == -2 ); assert( soma( -1, 1 ) == 0 ); } void somaComZeroResultaNoProprioNumero() { assert( soma( -1, 0 ) == -1 ); assert( soma( 0, 0 ) == 0 ); assert( soma( 0, 1 ) == 1 ); } void somaUsandoNumerosPositivosCorretamente() { assert( soma( 1, 1 ) == 2 ); assert( soma( 1, -1 ) == 0 ); }
  • 9. void chuteAltoTiraUmDecimoDaEnergia() { Lutador a, b; a.DefinirEnergia( 100 ); b.DesferirChuteAltoEm( a ); assert( a.Energia() == 90 ); }
  • 10. void transferenciaFazDebitarDaContaOrigem() { Conta origem, destino; origem.DefinirSaldo( 10500 ); double valorATransferir = 500; double saldoEsperadoAposTransferencia = origem.Saldo() – valorATransferir; origem.Transferir( destino, valorATransferir ); assert( origem.Saldo() == saldoEsperadoAposTransferencia ); }
  • 11. void transferenciaFazCreditarNaContaDestino() { Conta origem, destino; origem.DefinirSaldo( 10500 ); destino.DefinirSaldo( 2000 ); double valorATransferir = 500; double saldoEsperadoAposTransferencia = destino.Saldo() + valorATransferir; origem.Transferir( destino, valorATransferir ); assert( destino.Saldo() == saldoEsperadoAposTransferencia ); }
  • 12. O nome deve tentar explicar o que é verificado e qual o resultado esperado.  Nunca tente explicar como é verificado.  O nome pode ser bem longo.  Não se preocupe, você nunca precisará digitá-lo novamente. 
  • 13. ligarNitroFazCarroAcelerarQuandoEmMovimento ()  acelerarComFreioDeMaoLigadoFazRodasTraseiras Derraparem()  finalizarVendaFazBaixarEstoqueDeItensVendidos()  cairNoPrecipicioRetiraVidaDoJogador()
  • 14. Precisamos criar um programa que chame todos os nossos testes.  Há frameworks (bibliotecas de código que podem ser estendidas) que podemos usar para simplificar esse processo.  Usando um framework, nosso main não irá precisar fazer nada além de iniciar o framework.  O framework se encarregará de chamar os testes.
  • 15. 1/6  Yet Another Framework For Unit Testing  É opensource  É portátil (Windows,GNU/Linux,MacOS,...)  É pequeno  É simples  É poderoso  http://members.home.nl/rutger.van.beusekom/
  • 16. 2/6  Para usar o Yaffut, basta incluir seu único arquivo de código: #include <yaffut.h>  Criar uma classe (vazia) que servirá para agrupar os testes: class TesteContaBancaria {};  Use a macro TEST que recebe por parâmetro o nome da classe de teste e o nome do teste. Ex: TEST( TesteContaBancaria, transferenciaFazDebitarDaContaOrigem ) { ... }
  • 17. 3/6  No lugar de assert, use YAFFUT_CHECK. #include <yaffut.h> class TesteContaBancaria {}; TEST( TesteContaBancaria, transferenciaFazDebitarDaContaOrigem ) { Conta origem, destino; origem.DefinirSaldo( 10500 ); double valorATransferir = 500; double saldoEsperadoAposTransferencia = origem.Saldo() – valorATransferir; origem.Transferir( destino, valorATransferir ); YAFFUT_CHECK( origem.Saldo() == saldoEsperadoAposTransferencia ); }
  • 18. 4/6  Porém, para comparar igualdades, prefira YAFFUT_EQUAL.  Recebe dois parâmetros: valor esperado e valor obtido. TEST( TesteContaBancaria, transferenciaFazDebitarDaContaOrigem ) { Conta origem, destino; origem.DefinirSaldo( 10500 ); double valorATransferir = 500; double saldoEsperadoAposTransferencia = origem.Saldo() – valorATransferir; origem.Transferir( destino, valorATransferir ); YAFFUT_EQUAL( saldoEsperadoAposTransferencia, origem.Saldo() ); }
  • 19. 5/6  Outras funções: YAFFUT_UNEQUAL( esperado, obtido ) YAFFUT_FAIL( mensagem ) YAFFUT_ASSERT_THROW( método, exceção )
  • 20. 6/6  Como pode ser o programa principal de teste: #include <yaffut.h> #include “TesteContaBancaria.h” // ... outras bibliotecas de teste int main(int argc, const char* argv[]) { return yaffut::Factory::Instance().Main (argc, argv); }
  • 21. CppUnit  CppUnitLite  boost::test  TUT  CxxTest  ...
  • 22. Verificação de Comportamento MockRepository mr; Intf *intf = mr.InterfaceMock< Intf >(); mr.ExpectCall( intf, Intf::Method1 ) .With( “hello” ) .Return( 10 ); AClass ac; ac.DoSomething( *intf );
  • 23. TDD serve não só para verificar valores, mas, principalmente, para verificar o comportamento de objetos em suas interações com outros objetos.  Para isso, criamos objetos substitutos, chamados de Mocks, que simulam a execução de métodos reais.
  • 24. 1/10  Se ao fazer uma classe TerminalBancario quisermos ter um método que permita imprimir o extrato de uma conta bancária.  Como testar se o extrato foi impresso ? (Só olhar o papel saindo, certo?)  E se não tivermos impressora disponível para verificar ?
  • 25. 2/10  Precisamos mesmo da impressora, ou podemos apenas simular o comportamento que se espera dela ?  Se estamos interessados em seu comportamento, e não em sua implementação, podemos representar a impressora como uma interface.
  • 26. 3/10 class ImpressoraExtrato { public: // Retorna true se conseguir imprimir bool Imprimir(const ContaBancaria &conta) = 0; };
  • 27. 4/10  Então, podemos pensar que nosso terminal bancário tenha o seguinte método: // Retorna true se conseguir imprimir bool TerminalBancario::ImprimirExtrato( const ContaBancaria &conta, const ImpressoraExtrato &impressora);  Não importa como essa impressora funciona, desde que ela diga que imprimiu, para o terminal está OK.
  • 28. 5/10  Daí, podemos criar uma implementação falsa da impressora, para ser nossa substituta da impressora real: class ImpressoraExtratoFalsa : public ImpressoraExtrato { bool Imprimir(const ContaBancaria &conta) { return true; // Só diz que imprimiu ! } };
  • 29. 6/10  Nosso teste pode ficar assim: TEST( TesteContaBancaria, terminalConsegueImprimirExtrato ) { ContaBancaria conta; conta.Depositar( 1000 ); conta.Sacar( 500 ); ImpressoraExtrato *impressora = new ImpressoraExtratoFalsa(); TerminalBancario terminal; bool imprimiu = terminal.Imprimir(conta, *impressora ); delete impressora; YAFFUT_CHECK( imprimiu ); }
  • 30. 7/10  Mas como saber se o terminal interagiu corretamente com a impressora ?  Sabemos apenas que a impressora foi passada como parâmetro, mas como saber se ela foi usada ?  Ou seja, se o terminal chamou o método Imprimir como esperado (uma vez, passando a conta como parâmetro) e obteve um resultado dela ?
  • 31. 8/10  Podemos, em implementação falsa, criar um controle para saber se o método foi chamado como esperado.  E depois, no teste, verificamos se o método Imprimir foi chamado.
  • 32. 9/10 class ImpressoraExtratoFalsa : public ImpressoraExtrato { ImpressoraExtratoFalsa() { chamadasAImprimir = 0; } bool Imprimir(const ContaBancaria &conta) { chamadasAImprimir++; return true; } int ChamadasAImprimir() const { return chamadasAImprimir; } private: int chamadasAImprimir; };
  • 33. 10/10  Nosso teste pode ficar assim: TEST( TesteContaBancaria, terminalConsegueImprimirExtrato ) { ContaBancaria conta; conta.Depositar( 1000 ); conta.Sacar( 500 ); ImpressoraExtrato *impressora = new ImpressoraExtratoFalsa(); TerminalBancario terminal; bool imprimiu = terminal.Imprimir(conta, *impressora ); YAFFUT_EQUAL( 1, impressora->ChamadasAImprimir() ); YAFFUT_CHECK( imprimiu ); delete impressora; }
  • 34. Ter que criar manualmente implementações falsas (classes falsas) e contabilizar a execução de cada método é trabalhoso.  Porém, há frameworks de teste que permitem a criação automática de implementações falsas (chamadas de Mocks), bastando apenas definir o comportamento esperado dos métodos.  A contabilização da chamada também é feita automaticamente.
  • 35. Em C++ há bons frameworks de teste automatizado, porém, poucos com recursos de criação automática de mocks:  Isolator++  AMOP  MockitoPP  HippoMocks  etc.  Adotaremos o HippoMocks com Yaffut1. 1. Veja análise em http://devhints.blogspot.com/2010/11/bons-frameworks-c-para-criacao.html
  • 36. Feito usando Yaffut (já vem com ele).  É opensource.  É simples.  É poderoso.  É portátil.  http://www.assembla.com/spaces/hippomocks
  • 37. Sua classe principal é MockRepository, que permite criar um repositório de objetos falsos (mocks).  Permite criação de mocks através do método InterfaceMock.  Permite definir expectativas através do método ExpectCall.
  • 38. TEST( TesteContaBancaria, terminalConsegueImprimirExtrato ) { ContaBancaria conta; conta.Depositar( 1000 ); conta.Sacar( 500 ); MockRepository mr; // Repositório de mocks ImpressoraExtrato *impressora = mr.InterfaceMock< ImpressoraExtrato >(); // Cria um mock // Cria a expectativa mr.ExpectCall( impressora, ImpressoraExtrato::Imprimir ) .With( conta ) .Return( true ); TerminalBancario terminal; bool imprimiu = terminal.Imprimir(conta, *impressora ); YAFFUT_CHECK( imprimiu ); delete impressora; // Não precisa verificar NADA. // O framework verifica se a expectativa criada foi atendida! }
  • 39. TEST( TesteBomba, atirarNumaBombaFazExplodiLa ) { MockRepository mr; // Repositório de objetos falsos // Bomba falsa Bomba *bomba = mr.InterfaceMock< Bomba >(); // Expectativa do que deve acontecer com a bomba // ao ser acertada por um tiro mr.ExpectCall( bomba, Bomba::Explodir ); Jogador jogador; Revolver revolver( 38 ); jogador.SegurarObjeto( revolver ); revolver.AtirarNoObjeto( bomba ); // Deve fazê-la explodir }
  • 40. TDD em C++ Thiago Delgado Pinto