1 of 88

Desenvolvimento Dirigido a Testes

Prof. Alysson Filgueira Milanez

alysson.milanez@academico.ifpb.edu.br

Testes de Software

2 of 88

TDD

2

3 of 88

TDD

Test-Driven Development

Essência: escreva testes e codifique um pouco; isto em etapas alternativas e incrementais

3

4 of 88

TDD

Um caso de teste é escrito primeiro, e, na ausência do código correspondente, o caso de teste falha ao ser executado

4

5 of 88

TDD

De imediato, apenas o código suficiente para o teste passar é escrito

5

6 of 88

TDD

À medida que o código cresce, refatoramento pode ser realizado, mas os testes originais devem continuar passando - do contrário não se trata de uma atividade de refatoramento

6

7 of 88

TDD

TDD se tornou muito popular na comunidade de desenvolvimento ágil

7

8 of 88

TDD

TDD se baseia em pequenos ciclos de repetição:

- criamos um teste para cada nova funcionalidade;

- o teste falha, daí implementamos a funcionalidade para o teste passar;

- aprimoramos o código (refatoramos)

8

9 of 88

TDD

Um dos objetivos da prática de TDD é criar código limpo e que funciona

9

10 of 88

TDD

Aumenta a cobertura do código - toda nova funcionalidade tem ao menos um caso de teste

Pode levar a aumentos na qualidade do produto de software

10

11 of 88

TDD

TDD proporciona um senso de evolução passo a passo em direção à conclusão do seu projeto

11

12 of 88

Ciclo de Desenvolvimento

12

13 of 88

TDD

Toma por base o ciclo: red, green, refactoring

13

14 of 88

TDD

Toma por base o ciclo: red, green, refactoring

Mantra do TDD

14

15 of 88

TDD

Auxilia a isolar faltas: se um novo caso de teste falha, a falta só pode estar relacionada ao código recentemente adicionado

Todos os demais testes continuam a passar

15

16 of 88

TDD

Isso não é tão óbvio para faltas mais profundas, reveladas via teste de fluxo de dados

16

17 of 88

TDD

Novo teste: escrevemos o código que irá testar a nova função (ainda não implementada)

É necessário especificar bem qual a entrada e a saída do código a ser testado

Se a especificação for ruim, deu ruim

17

18 of 88

TDD

O fato de termos um teste primeiro que o código garante que daremos passos simples para a codificação da funcionalidade: implementação simples para que o teste passe

18

19 of 88

TDD

Como ainda não existe o código, o teste falha (red)

19

20 of 88

TDD

Daí criamos a funcionalidade - escrevemos o código

Faremos isso da forma mais simples possível

20

21 of 88

TDD

O código que acabamos de escrever passou no teste e não quebrou outros testes (green)

Garantir que não houve regressão de funcionalidade

21

22 of 88

TDD

Código limpo, simples e funcional

Esta é a ideia

22

23 of 88

TDD

Agora é hora de refatorar: O TDD nos obriga a escrever códigos menos acoplados e mais coesos para que se tornem mais “testáveis”

refactoring

23

24 of 88

TDD

É neste momento que podemos deixar o nosso código simples e claro e o melhor de tudo: Funcional!

24

25 of 88

TDD

Como conseguimos um código simples? Fazendo um Teste passar

25

26 of 88

TDD

Como conseguimos um código claro? Refatorando o código após ele passar

26

27 of 88

TDD

Como conseguimos um código seguro? Com Testes

27

28 of 88

TDD

SRP - Single Responsibility Principle

Este princípio nos diz que devemos ter somente um motivo para modificar uma classe

Ou seja, ele fala sobre termos uma classe com somente uma responsabilidade

28

29 of 88

TDD

Usando TDD a suíte de testes pode ser usada como documentação das funcionalidades do sistema

29

30 of 88

Por que usar?

30

31 of 88

TDD

Feedback rápido sobre a nova funcionalidade e sobre as outras funcionalidades existentes no sistema

31

32 of 88

TDD

Código mais limpo, já que escrevemos códigos simples para o teste passar

32

33 of 88

TDD

Segurança no Refactoring pois podemos ver o que estamos ou não afetando

33

34 of 88

TDD

Segurança na correção de bugs

34

35 of 88

TDD

Maior produtividade já que o desenvolvedor encontra menos bugs e não desperdiça tempo com depuradores

35

36 of 88

TDD

Código da aplicação mais flexível, já que para escrever testes temos que separar em pequenos "pedaços" o nosso código, para que sejam testáveis, ou seja, nosso código estará menos acoplado

36

37 of 88

Exemplos de uso

37

38 of 88

TDD

Usaremos Java + Eclipse + JUnit

38

39 of 88

TDD

Criar uma Calculadora que calcula as 4 operações básicas: Adição, Subtração, Multiplicação e Divisão

39

40 of 88

TDD

Passos:

- Crie um projeto no Eclipse com o nome TDD

- Crie um pacote tdd.calculadora.teste

40

41 of 88

TDD

Criada a estrutura básica, vamos criar a nossa primeira classe

CalculadoraTeste

41

42 of 88

TDD

Vamos fazer um Teste em algo que ainda não temos implementado

42

43 of 88

TDD

Nossa calculadora terá as 4 operações básicas

Que tal começarmos com uma soma: como testar uma soma?

43

44 of 88

TDD

Dados dois valores, o resultado deveria ser a soma deles

Assim criamos o método

44

45 of 88

TDD

45

46 of 88

TDD

Vamos agora inserir duas variáveis e usar o método "assertEquals" do próprio JUnit

46

47 of 88

TDD

Eis o código

47

48 of 88

TDD

Ao executar…

Red bar

48

49 of 88

TDD

Isto já era esperado:

Test -> Red -> Green -> Refactor

49

50 of 88

TDD

Podemos analisar o trace para entender o erro

50

51 of 88

TDD

O JUnit indica que esperava o valor 3 porém foi encontrado o valor 0

E agora o nosso objetivo é fazer o Teste passar

Colocamos agora a classe responsável pela implementação da funcionalidade

51

52 of 88

TDD

52

53 of 88

TDD

Como assim jóvis???

53

54 of 88

TDD

Como assim jóvis???

É isso mesmo: usamos a classe antes de criá-la

54

55 of 88

TDD

Agora criamos a classe e o método

55

56 of 88

TDD

Então implementamos o método

56

57 of 88

TDD

Daí vemos a tão desejada green bar

57

58 of 88

TDD

A última etapa seria a refatoração, mas o nosso sistema ainda é simples demais

58

59 of 88

TDD

Seguindo os mesmos passos anteriores, vamos criar agora o teste para a subtração

59

60 of 88

TDD

@Test

public void deveriaSubtrairDoisValoresPassados() throws Exception{

Calculadora calculadora = new Calculadora();

int valorA = 5;

int valorB = 2;

int subtrai = calculadora.subtrai(valorA, valorB);

assertEquals(3, subtrai);

}

60

61 of 88

TDD

Método na classe Calculadora

public int subtrai(int valorA, int valorB) {

return valorA - valorB;

}

61

62 of 88

TDD

Divisão

@Test

public void deveriaDividirDoisValoresPassados() throws Exception {

int valorA = 6;

int valorB = 2;

Calculadora calculadora = new Calculadora();

int divisao = calculadora.divide(valorA, valorB);

assertEquals(3, divisao);

}

62

63 of 88

TDD

Na classe Calculadora

public int divide(int valorA, int valorB) {

return valorA / valorB;

}

63

64 of 88

TDD

E se eu mudar o teste para:

@Test

public void deveriaDividirDoisValoresPassados() throws Exception {

int valorA = 6;

int valorB = 0; // divisao por zero

Calculadora calculadora = new Calculadora();

int divisao = calculadora.divide(valorA, valorB);

assertEquals(?, divisao);

}

64

65 of 88

TDD

Eis um teste esperando por uma exceção

65

66 of 88

TDD

@Test

public void deveriaLancarUmaExcecaoIndicandoFalhaAoDividirUmNumeroPorZero() throws Exception {

int valorA = 6;

int valorB = 0;

Calculadora calculadora = new Calculadora();

int divisao = calculadora.divide(valorA, valorB);

assertEquals(0, divisao);

}

66

67 of 88

TDD

Podemos usar um parâmetro na própria anotação do JUnit (@Test) para indicar qual a exceção que estamos esperando receber

67

68 of 88

TDD

@Test(expected = ArithmeticException.class)

public void deveriaLancarUmaExcecaoIndicandoFalhaAoDividirUmNumeroPorZero() throws Exception {

int valorA = 6;

int valorB = 0;

Calculadora calculadora = new Calculadora();

calculadora.divide(valorA, valorB);

}

68

69 of 88

TDD

Agora sim temos a green bar novamente

69

70 of 88

TDD

E para a multiplicação, como fica?

70

71 of 88

Frameworks de Teste

71

72 of 88

TDD

TDD depende de um ambiente que facilite a execução de testes

Alguns exemplos de tais ambientes para as principais linguagens de programação

72

73 of 88

TDD

CUnit - teste de unidade para C

CPPUnit - teste de unidade para C++

73

74 of 88

TDD

JUnit - para Java

PyUnit - para Python

74

75 of 88

Questões restantes

75

76 of 88

TDD

TDD pode ser caixa preta ou caixa branca

Depende de como conduzimos o processo: se focamos em user stories ou em código, depende dos detalhes que usamos

76

77 of 88

TDD

TDD força uma abordagem de desenvolvimento bottom-up

isso ajuda a isolar faltas

77

78 of 88

Exercício

78

79 of 88

Exercício

Escrever casos de teste e a implementação para a sequência de Fibonacci, conforme a especificação:

F(0) = 0

F(1) = 1

F(2) = 1

F(n) = F(n-1) + F(n-2), para qualquer n maior que 2.

79

80 of 88

Exercício

Escrever o código da classe ValidDate usada para validar incrementos em datas

80

81 of 88

Exercício

Casos de teste

Link aqui

81

82 of 88

Exercício

Com base na documentação fornecida, escreva os testes e o código para a classe implementando a interface AccountStack

Código da interface

82

83 of 88

Exercício

Outras classes necessárias:

Account

SavingsAccount

CheckingAccount

Exceção

83

84 of 88

Referências

84

85 of 88

Referências

JORGENSEN, P. C. Software Testing: A Craftsman's Approach.

Cap. 19

85

86 of 88

Veja mais...

86

87 of 88

Veja mais

87

88 of 88

Desenvolvimento Dirigido a Testes

Prof. Alysson Filgueira Milanez

alysson.milanez@academico.ifpb.edu.br

Testes de Software