Anotações
Apresentação de slides
Estrutura de tópicos
1
Modulo II
Técnicas para desenvolvimento de Software Ágil
  • Prof. Ismael H F Santos


2
Bibliografia
  • Software Estimation: Demystifying the Black Art (Best Practices (Microsoft))
    by Steve McConnell
  • Test-Driven Development: By Example,                Kent Beck - Addison-Wesley, 2003,                                  ISBN 0-321-14653-0
  • Refactoring: Improving the Design              of Existing Code, Martin Fowler -                           Addison-Wesley, 1999  SBN 0-201-48567-2


3
Agenda
  • Introdução
  • TDD
  • Testes em XP
  • Boas Práticas de Teste
4
MA-XP
5
O que é "Testar código"?
6
Por que testar?
7
Testes: para quê ?
  • Para verificar a validade de uma implementação com respeito aos requisitos.
  • Para especificar formalmente o critério de aceitação de uma implementação pelo cliente.
  • Para detalhar o design e a forma de uso da funcionalidade.
  • Para garantir que não quebramos nada quando fazemos uma alteração.
8
Teste X Revisão X Prova X Métrica
  • Teste:
    • Execução de um programa através de procedimentos manuais ou automáticos.
  • Revisão/Inspeção:
    • Revisão de produtos de trabalho por especialistas: documentos, código-fonte de programas.
  • Prova/Verificação:
    • Procedimento sistemático e formal para garantir que uma implementação está correta.
  • Métrica:
    • Aferição de características mensuráveis dos produtos de trabalho ou da execução de programas.
9
Desenvolvimento em cascata
  • à Levantamento de requisitos
  • à Análise
  • àDesign de alto nível
  • à Design detalhado
  • à Codificação
  • + teste unitário
  • à Integração
  • + teste de integração
  • à Implantação
  • + teste de sistema
  • àManutenção
  • + teste de regressão
10
Cascata
    • s. f. (do italiano cascata)


    • 1. Queda de água em cachoeira, natural ou artificial;
    • 2. Brasil, gíria: Conversa fiada; mentira; bazófia


    • Fonte:
    • Dicionário Universal da Língua Portuguesa
    • http://www.priberam.pt/DLPO/

11
Algumas cascatas ...
  • Inspeções são sempre mais eficientes que testes na contenção de defeitos.
  • Usar uma matriz para mapear casos de teste X requisitos.
  • Só se pode rodar os testes depois de implementar.
  • Fazer certo da primeira vez, para evitar retrabalho.
  • Procedimentos formais garantem uma implementação correta.
12
..., mais cascatas ...
  • Definir todos os casos de teste antes de começar a programar.
  • Se funciona mais ou menos, é melhor não mexer.
  • Torcer para o teste dar certo na primeira rodada.
  • Automatizar os testes é muito caro: não compensa.
  • É impossível que quem vai rodar os testes não entenda este roteiro: está super claro.
  • Vai pegar mal documentar que esse teste falhou: vai ferrar as nossas métricas.
13
... e mais essas.
  • O teste passou: está 90% certo.
  • Testes (ou inspeções, ou provas, ou métricas) garantem qualidade.
  • Quem testa não pode ser quem programou.
  • Revisar o código muito cuidadosamente antes de compilar: não depender do compilador para detectar erros triviais.
  • Rodar exaustivamente testes de mesa antes de digitar o código.
14
Como escrever bons testes
15
Como descobrir testes?
16
MA-XP
17
Motivation
  • TDD sits nicely in the XP “way of doing things”
    • TDD can be used without practicing XP
  • Writing articles and giving presentations is one such way of achieving that goal
  • To reduce the amount of re-testing that is required
    • Especially with legacy applications
    • To avoid introducing new bugs after refactoring existing code
18
TDD
19
What is TDD?
  • TDD is a technique whereby you write your test cases before you write any implementation code
  • Tests drive or dictate the code that is developed
  • An indication of “intent”
    • Tests provide a specification of “what” a piece of code actually does
    • Some might argue that “tests are part of the documentation”
20
What is TDD?
  • “Before you write code, think about what it will do.
  •      Write a test that will use the methods you haven’t even written yet.”
    • Extreme Programming Applied: Playing To Win
    • Ken Auer, Roy Miller
    • “The Purple Book”


  • A test is not something you “do”, it is something you “write” and run once, twice, three times, etc.
    • It is a piece of code
    • Testing is therefore “automated”
    • Repeatedly executed, even after small changes

21
TDD Stages
  • In Extreme Programming Explored (The Green Book),                  Bill Wake describes the test / code cycle:
  • Write a single test
  • Compile it.  It shouldn’t compile because you’ve not written the implementation code
  • Implement just enough code to get the test to compile
  • Run the test and see it fail
  • Implement just enough code to get the test to pass
  • Run the test and see it pass
  • Refactor for clarity and “once and only once”
  • Repeat
22
JUnit para guiar o desenvolvimento
23
TDD
Test Driven Development
  • Desenvolvimento Guiado por  Testes, define que antes de criarmos um código novo, devemos escrever um teste para ele.
  • E testes serão usados como métrica em todo o tempo de vida do projeto.
24
TDD Stages
25
Why TDD?
  • Programmers dislike testing
    • They will test reasonably thoroughly the first time
    • The second time however, testing is usually less thorough
    • The third time, well..
  • Testing is considered a “boring” task
  • Testing might be the job of another department / person
  • TDD encourages programmers to maintain an exhaustive set of repeatable tests
    • Tests live alongside the Class/Code Under Test (CUT)
    • With tool support, tests can be run selectively
    • The tests can be run after every single change


26
Why TDD?
  • Bob Martin:
    • “The act of writing a unit test is more an act of design than of verification”
  • Confidence boost
    • By practicing TDD, developers will strive to improve their code – without the fear that is normally associated with code changes
    • Isn’t the green bar a feel good factor?
  • Remove / Reduce reliance on the debugger
    • No more “debug-later” attitudes
27
Who should write the tests?
  • The programmers should write the tests
    • The programmers can’t wait for somebody else to write tests
  • TDD promotes “small steps”, and lots of them
    • Small steps: the shortest distance between two points
    • Your destination is closer…





28
MA-XP
29
Práticas XP
30
Testes em XP
  • Testes do programador
    • Testes unitários (caixa branca)
    • Codificados pelo desenvolvedor.
    • Detalham o design da implementação.
    • Rodam muito rápido.
    • Todo código integrado roda 100% desses testes.


31
Testes em XP
  • Testes do cliente
    • Testes de sistema (caixa preta)
    • Escritos pelo cliente.
    • Detalham os critérios de aceitação de uma implementação.
    • Podem demorar mais.
    • Mais difíceis
    • Quando estão rodando 100%, o produto pode ser entregue.

32
Integração Contínua
33
 
34
Procedimento
  • Entrada: estórias de usuário (requisitos), arquitetura
    • Escreva um teste para uma porção ridiculamente pequena da funcionalidade.
    • Compile e rode o teste.
    • Escreva o mínimo código funcional para passar o teste (com possível enganação). Compile.
    • Compile e rode o teste
    • Melhore o teste para desvendar a enganação, se houver Vá para (2)
    • Melhore (refatore) o código funcional. Vá para (2)
35
Testas ¹ Depurar
  • Simplificando
    • Depurar - o que se faz quando se sabe que o programa não funciona;
    • Teste - tentativas sistemáticas de encontrar erros em programa que você “acha” que está funcionando.


  • “Testes podem mostrar a presença de erros, não a sua ausência (Dijkstra)”
36
Teste enquanto você escreve código
  • Se possível escreva os testes antes mesmo de escrever o código
    • uma das técnicas de XP


  • quanto antes for encontrado o erro melhor !!
37
Técnicas básicas
  • Teste o código em seus limites;
  • Teste de pré e pós condições;
  • Uso de premissas (assert);
  • Programe defensivamente;
  • Use os códigos de erro.
38
Teste o código em seus limites
  • Para cada pequeno trecho de código (um laço, ou if por exemplo) verifique o seu bom funcionamento;


  • Tente uma entrada vazia, um único item, um vetor cheio, etc.
39
Teste de pré e pós condições
  • Solução possível



  • Não existe uma única resposta certa
    • A única resposta claramente errada é ignorar o erro !!
    • Ex: USS Yorktown.
40
Uso de premissas
  • Em C e C++ use <assert.h>
    • ex:
    • assert (n>0);


    • se a condição for violadada:
      • Assertion failed: n>0, file avgtest.c, line 7.
  • Ajuda a identificar “culpados” pelos erros
41
Programação defensiva
  • Tratar situações que não “podem” acontecer
      • Exemplo:
42
Utilizar códigos de erro
  • Checar os códigos de erro de funções e métodos;
    • você sabia que o scanf retorna o número de parâmetros lidos, ou EOF ?


  • Sempre verificar se ocorreram erros ao abrir, ler, escrever e principalmente fechar arquivos.


  • Em java sempre tratar as possíveis exceções


43
Testes sistemáticos (1/4)
  • Teste incrementalmente
    • durante a construção do sistema
      • após testar dois pacotes independentemente teste se eles funcionam juntos
  • Teste primeiro partes simples
    • tenha certeza que partes básicas funcionam antes de prosseguir
    • testes simples encontram erros simples
    • teste as funções/métodos individualmente
      • Ex: teste de função que faz a busca binária em inteiros
44
Testes Sistemáticos (2/4)
  • Conheça as saídas esperadas
    • conheça a resposta certa
    • para programas mais complexos valide a saída com exemplos conhecidos
      • compiladores - arquivos de teste;
      • numéricos - exemplos conhecidos, características;
      • gráficos - exemplos, não confie apenas nos seus olhos.
45
Testes Sistemáticos (3/4)
  • Verifique as propriedades invariantes
    • alguns programas mantém propriedades da entrada
      • número de linha
      • tamanho da entrada
      • freqüência de caracteres
        • Ex: a qualquer instante o número de elementos em uma estrutura de dados deve ser igual ao número de inserções menos o número de remoções.
46
Testes Sistemáticos (3/4)
  • #include <stdio.h>
  • #include <ctype.h>
  • #include <limits.h>
  • unsigned long count[UCHAR_MAX+1];


  • int main(void) {
  •     int c;
  •     while ((c = getchar()) != EOF){
  •         count[c]++;
  •     }
  •     for(c=0; c <= UCHAR_MAX; c++){
  •      printf(``%.2x %c %lu\n’’, c, isprint(c) ? c: `-’,                                                                                      count[c]);
  •     return 0;
  • }
47
Testes Sistemáticos (4/4)
  • Compare implementações independentes
    • os resultados devem ser os mesmos
      • se forem diferentes pelo menos uma das implementações está incorreta
  • Cobertura dos testes
    • cada comando do programa deve ser executado por algum teste
      • existem profilers que indicam a cobertura de testes
48
Automação de testes
  • Testes manuais
    • tedioso, não confiável


  • Testes automatizados
    • devem ser facilmente executáveis
      • junte em um script  todos os testes
49
Automação de testes
  • Teste de regressão automáticos
    • Comparar a nova versão com a antiga
    • verificar se os erros da versão antiga foram corrigidos
    • verificar que novos erros não foram criados


  • Testes devem rodar de maneira silenciosa
    • se tudo estiver ok
50
Automação de testes
51
Automação de testes
  • Crie testes autocontidos
    • testes que contém suas próprias entradas e respectivas saídas esperadas
    • programas tipo awk podem ajudar
  • O quê fazer quando um erro é encontrado
    • se não foi encontrado por um teste
      • faça um teste que o provoque
  • Como fazer um testador automático para o programa de freqüência ?
52
Framework de testes
  • As vezes para se testar um componente isoladamente é necessários criar um ambiente com características de onde este componente será executado
    • ex: testar funções mem* do C (como memset)


  • /* memset: set the first n bytes of s to the byte c */
  • void *memset(void *s, int c, size_t n) {
  •     size_t i;
  •     char *p;
  •     p = (char *)s;
  •     for (i=0; i<n; i++) p[i] = c;
  •     return s;
  • }
  • // memset(s0 + offset, c, n);
  • // memset2(s1 + offset, c, n);
  • // compare s0 e s1 byte a byte


  • Como testar funções do math.h ?
53
Testes de stress
  • Testar com grandes quantidades de dados
    • gerados automaticamente
    • erros comuns:
      • overflow nos buffers de entrada, vetores e contadores
    • Exemplo: ataques de segurança
      • gets do C - não limita o tamanho da entrada
      • o scanf(``%s’’, str) também não...
      • Erro conhecido por “buffer overflow error” NYT98
54
Testes de stress
55
Dicas para fazer testes
  • Cheque os limites dos vetores
    • caso a linguagem não faça isto por você
    • faça com que o tamanho dos vetores seja pequeno; ao invés de criar testes muito grandes
  • Faça funções de hashing constantes
  • Crie versões de malloc que ocasionalmente falham
  • Desligue todos os testes antes de lançar a versão final
  • Inicialize os vetores e variáveis com um valor não nulo
    • ex: 0xDEADBEEF pode ser facilmente encontrado
  • Não continue a implementação de novas características se já foram encontrados erros
  • Teste em várias máquinas, compiladores e SOs
56
Tipos de teste
  • “white box”
    • testes feitos por quem conhece (escreveu) o código
  • “black box”
    • testes sem conhecer o código
  • “usuários”
    • encontram novos erros pois usam o programa de formas que não foram previstas
57
Testes difíceis
  • Testes unitários não podem depender de estado
  • Então, como testar:
    • Bancos de Dados
    • Servidor Web
    • Interface Usuário
    • ..., etc.
58
Teste em camadas
  • Coloca-se uma camada que funciona como se o serviço sempre fizesse a coisa certa, para testar o cliente (mock objects = objetos fajutos)
  • O serviço tem testes específicos que verificam seu funcionamento interno.
59
Extensões e Vantagens
  • Desempenho (JUnitPerf)
  • Métricas de qualidade
  • Padrões de projeto (PatternTest)
  • Cobertura de testes (Jester)
  • ... Todas escritas seguindo o padrão Xunit.
  • Vantagens
    • Integração com ambientes de desenvolvimento (IDEs)
    • Feedback rápido
    • Robustez
60
Referências
  • Grupo testdrivendevelopment do Yahoo
  • http://junit.org
  • Test-driven development (Kent Beck, 2003)
  • http://www.xispe.com.br