SlideShare una empresa de 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

Más contenido relacionado

La actualidad más candente

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
 

La actualidad más candente (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
 

Destacado

Event Driven Architecture &amp; Complex Event Processing
Event Driven Architecture &amp; Complex Event ProcessingEvent Driven Architecture &amp; Complex Event Processing
Event Driven Architecture &amp; Complex Event Processinglogus2k
 
ApacheHadoop2xDeveloperJava
ApacheHadoop2xDeveloperJavaApacheHadoop2xDeveloperJava
ApacheHadoop2xDeveloperJavaRakesh Gupta
 
Triángulos del cuello
Triángulos del cuelloTriángulos del cuello
Triángulos del cuelloGC QM
 
Dossier de Proyectos de Grupo Shinè
Dossier de Proyectos de Grupo ShinèDossier de Proyectos de Grupo Shinè
Dossier de Proyectos de Grupo ShinèGrupo Shinè
 
Light the Night Raises Funds for Blood-Cancer Research
Light the Night Raises Funds for Blood-Cancer ResearchLight the Night Raises Funds for Blood-Cancer Research
Light the Night Raises Funds for Blood-Cancer ResearchKeyvan Azami
 

Destacado (13)

Ace tutorial c
Ace tutorial cAce tutorial c
Ace tutorial c
 
Event Driven Architecture &amp; Complex Event Processing
Event Driven Architecture &amp; Complex Event ProcessingEvent Driven Architecture &amp; Complex Event Processing
Event Driven Architecture &amp; Complex Event Processing
 
Act#28d 101 m
Act#28d 101 mAct#28d 101 m
Act#28d 101 m
 
ApacheHadoop2xDeveloperJava
ApacheHadoop2xDeveloperJavaApacheHadoop2xDeveloperJava
ApacheHadoop2xDeveloperJava
 
Las drogas
Las drogas Las drogas
Las drogas
 
Calendario Viernes 12 Febrero 2016
Calendario Viernes 12 Febrero 2016Calendario Viernes 12 Febrero 2016
Calendario Viernes 12 Febrero 2016
 
Triángulos del cuello
Triángulos del cuelloTriángulos del cuello
Triángulos del cuello
 
Import trade
Import   tradeImport   trade
Import trade
 
Dossier de Proyectos de Grupo Shinè
Dossier de Proyectos de Grupo ShinèDossier de Proyectos de Grupo Shinè
Dossier de Proyectos de Grupo Shinè
 
5
55
5
 
Історія народу в пісні
Історія народу в пісніІсторія народу в пісні
Історія народу в пісні
 
登山 健康
登山 健康登山 健康
登山 健康
 
Light the Night Raises Funds for Blood-Cancer Research
Light the Night Raises Funds for Blood-Cancer ResearchLight the Night Raises Funds for Blood-Cancer Research
Light the Night Raises Funds for Blood-Cancer Research
 

Similar a TDD em C++

Similar a TDD em 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
 

Más 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
 
DOJO - TDD com C++
DOJO - TDD com C++DOJO - TDD com C++
DOJO - TDD com 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
 

Más 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
 
DOJO - TDD com C++
DOJO - TDD com C++DOJO - TDD com C++
DOJO - TDD com C++
 
I CEFET Coding Dojo - Divulgação
I CEFET Coding Dojo - DivulgaçãoI CEFET Coding Dojo - Divulgação
I CEFET Coding Dojo - Divulgação
 

Último

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
 
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 - 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
 
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
 
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
 
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
 

Último (6)

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
 
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 - 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
 
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
 
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
 
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
 

TDD em 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