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