Combinando Test Driven Development
(TDD) com Design By Contract (DBC)
João Arthur Brunet Monteiro
Universidade Federal de Campina Grande - UFCG
Centro de Engenharia Elétrica e Informática - CEEI
Departamento de Sistemas e Computação - DSC
Roteiro
 Introdução
 Backgroud
 Test Driven Development
 Design By Contract
 Combining Formal Specifications with Test Driven Development
 Visão Geral
 Técnica Proposta
 Resultados
 Discussões
Introdução
 Combining Formal Specifications with Test Driven Development
 Design By Contract e Test Driven Development
 Trabalho relativamente recente (2004).
Por quê?
Por quê combinar as duas técnicas?
Test Driven Development
 Técnica de desenvolvimento de software baseada em testes
 Testes são desenvolvidos antes do código
 Técnica ágil
 Pequenos passos (baby steps)
 Manter a simplicidade (KISS)
Test Driven Development
 Não constitui somente uma maneira de testar. TDD é uma
técnica desenvolvida que, ao aplicada, força o programador a
pensar no design do código antes dele ser implementado.
 Passos:
 Escrever o teste
 Obter red bar
 Escrever o código mais simples que passe no teste
 Obter green bar
 Refatorar o código
Testes
 Descrevem parcialmente, através de exemplos, o
comportamento do sistema
 Usados como documentação de um programa
 Aumentam o entendimento sobre o código
 Aumentam a qualidade do código
Mas...
 Não generalizam propriedades do sistema
Design By Contract
Metodologia que se baseia na construção de contratos entre partes do software.
 Usa especificações formais para estabelecer contratos entre partes do software
 pré-condições, pós-condições e invariantes
 Especificações formais são também usadas como documentação sem fazer
referência ao código. Por isso, aumentam a reusabilidade do software e,
consequentemente, sua qualidade
 Especificações formais descrevem o comportamento do sistema de maneira
mais completa que testes o fazem
Mas...
 A tarefa de mostrar que um software está de acordo com as especificações é
geralmente muito complexa
Por quê não?
Por quê não combinar as técnicas?
Combining Formal Specifications with
Test Driven Development
 Objetivos
 Combinar especificação formal com TDD
 Não perder a agilidade de TDD
 Ganhar com as generalizações das especificações formais
Técnica Proposta
 Os testes usados para conduzir o desenvolvimento do código
também são usados para conduzir o desenvolvimento das
especificações
 Especificações generalizam os testes
 Asserções são geradas a partir das especificações afim de checar
inconsistências entre testes, código e especificações
 Três Variáveis de interesse
 Testes
 Código
 Especificações
 Manter a consistência entre as variáveis aumenta a qualidade do
código desenvolvido e da documentação uma vez que as
especificações formais não dão margem a interpretações ambíguas
Tecnologias Utilizadas
Junit
Código
+
Java
Testes
+
JML
Especificações
Tecnologias utilizadas
 Junit e Java dispensam apresentações!
 Java Model Language (JML) é uma linguagem para
formulações de pré-condições, pós-condições e invariantes
 Especificações escritas em JML são simples de entender
 JML vem com um checador de asserções em tempo de
execução
As tecnologias foram usadas para exemplificar a técnica, no
entanto, a mesma não exige tecnologias específicas!
Técnica Proposta
 Consiste em, ao estilo TDD, uma sequência de passos que se
repetem ao longo do desenvolvimento do software.
1.
2.
3.
4.
5.
Escrever o teste
Implementar o código
Refatorar o código
Generalizar os testes para especificações
Refatorar as especificações
Aplicando a técnica
 Exemplo usado: Programa que, dado um inteiro n, retorna os
números primos até n.
Passo 1: Escrever o teste
public void testZero() {
List primes Primes.primes(0);
assertTrue(primes.isEmpty());
}
Passo 2: Escrever o código
public static List primes(int n) {
return new LinkedList();
}
Passo 3: Refatorar o código
Aplicando a técnica
Passo 4: Generalizar o teste para especificações
public bahavior
requires n<=1;
ensures \result.isEmpty();
}
 Veja que o caso de n ser igual a 1 foi coberto pela
especificação, mas não pelo teste. Analisando a especificação é
possível notar que falta um teste. No entanto, a inclusão do
novo teste não irá apontar faltas no código.
Aplicando a técnica
Passo 1: Escrever o teste
public void testTwo() {
List primes = new Primes.primes(2);
assertEquals(1, primes.size());
assertTrue( primes.contains(new Integer(2)));
}
Passo 2: Escrever o código
public static List primes(int n) {
List primes = new LinkedList();
if (n==2) primes.add(new Integer(2));
return primes;
}
Aplicando a técnica
Passo 4: : Generalizar o teste para especificações
public bahavior
requires n<=1;
ensures \result.isEmpty();
also
requires n ==2;
ensures \result.size() == 1 && \result.contains(new Integer(2));
Passo 1: Escrever o teste
public void testLosts1() {
...
for (int i = 1; i<=n ; i++) {
if (isPrime(i)) assertTrue(primes.contains(new Integer(i)))
}
}
Aplicando a técnica
 Especificação da função isPrime(int i)
public bahavior
ensures
\result < = = > (n > 1 && (\forall int i; i > 1 && i < n; n % i != 0));
Passo 2: Escrever o código
public static List primes(int n) {
List primes = new LinkedList();
for (int i = 2; i <= n; i++) primes.add(new Integer(i));
return primes;
}
Aplicando a técnica
Passo 4: : Generalizar o teste para especificações
public bahavior
requires n <= 1;
ensures \result.isEmpty();
also
requires n == 2;
ensures \result.size() == 1 && \result.contains(new Integer(2));
also
requires n > 2;
ensures (\forall int i; i >= 2 && i <= n; isPrime(i) == > \result.contains(new
Integer(i)));
Aplicando a técnica
 A especificação diz que, para um dado n, a função retorna
uma lista contendo os números primos de 2 até n. Porém,
não assegura que a lista só contém os números primos de 2 a
n.
Passo 1: Escrever o teste
public void testLosts1() {
List primes = Primes.primes(1000);
...
for (Integer i : primes) {
assertTrue(isPrime(i));
assertTrue(prime <= n);
}
}
Aplicando a técnica
Passo 2 : Escrever o código ... (crivo de Eratóstenes)
Passo 3: Refatorar o código ...
Passo 4: : Generalizar o teste para especificações
Aplicando a técnica
public bahavior
requires n <= 1;
ensures \result.isEmpty();
also
requires n == 2;
ensures \result.size() == 1 && \result.contains(new Integer(2));
also
requires n > 2;
ensures (\forall int i; i >= 2 && i <= n; isPrime(i) == > \result.contains(new
Integer(i)));
also
requires n > 2;
ensure (\forall Integer i; \result.contains(i));
isPrime(i);
Aplicando a técnica
 Em TDD é argumentado que testes não devem ser
refatorados.
 Refatorar especificações tornam-as mais claras e concisas.
Passo 5: Refatorar especificações
public bahavior
ensures
(\forall int i; i >= 2 && i <= n;
isPrime(i) == > \result.contains(new Integer(i)));
&&
(\forall Integer i; \result.contains(i);
isPrime(i);
Observações
 Rodando os testes instrumentados com as asserções geradas
pelas especificações em JML, é possível garantir que a
especificação não entra em conflito com a implementação do
código
 O caso de haver números maiores que n não foi considerado.
Mas neste caso, basta adicionar na especificação que i deve ser
menor que n
Resultados
 Como resultado do processo temos um conjunto de testes,
código e especificações que assegura que o código
implementa o comportamento esperado, documentado pela
especificação
 As especificações podem ser usadas como documentação para
descrever o comportamento do programa sem fazer
referência ao código fonte
 Note que a especificação é mais simples de entender do que
os testes e o código
 O poder de abstração aumenta com o uso das especificações
Resultados
 Bugs que não eram encontrados fazendo uso de testes, são
revelados quando a técnica é usada
 O uso da técnica ajuda a aumentar o conjunto de testes
 Assim como testes, não garante a ausência de bugs
Discussão
Dúvidas?
Referências
 Hubert Baumeister. Combining Formal Specifications with
Test Driven Development. XP/Agile Universe 2004: 1-12
 Bertrand Meyer: Applying "Design by Contract, in
Computer (IEEE), vol. 25, no. 10, October 1992, pages 4051.
 BECK, K. and FOWLER, M. (2001). Planning Extreme
Programming. Addison Wesley.
Download

Combinando Test Driven Development