Testes de correção (de defeitos)
• Revelam a presença de erros, mas NÃO a ausência
• Um teste bem sucedido é aquele que descobre o
maior número de erros existentes.
• Deve ser utilizado em conjunto com técnicas de
inspeção
– O teste deve identificar o erro
– A inspeção analítica (rastreamento ou depuração) deve localizar e corrigir o erro
Engenharia de Software, Jair C Leite
Fundamentos
• Seja P um programa, D o domínio (valores iniciais) e I a imagem (valores resultantes). Por simplicidade, vamos considerar P que se comporta com uma função D -> I.
• Seja R os valores resultantes desejáveis determinados durante a especificação. Seja d dados do domínio D, dizemos que P(d) refere-se aos possíveis resultados de P para d.
• Dizemos que um programa está correto se P(d) satisfaz R. P está correto se e somente se para todo dado d, P(d) satisfaz R. Dizemos que um programa não está correto se o programa não termina de executar, ou se termina mas P(d) não satisfaz R.
• A presença de um erro é demonstrada pela existência de dados d, tal que P(d) não satisfaz R. Muitas vezes é impossível
verificar P(d) para todos os dados d do domínio D. Nestas situações é importante elaborar casos de testes.
• Um caso de teste é um elemento d de D. Um conjunto de
casos de teste T é um subconjunto de D. Um conjunto de teste T é dito ideal se, sempre que P for incorreto, existe um d
O problema da geração de casos de
testes
• Testes exaustivos são impraticáveis.
• Escolher bons casos de testes (dados de entrada e
comportamento esperado) é fundamental para que um teste seja bem sucedido, isto é, detecte os erros existentes.
• Exemplo:
– Considere um programa (ou trecho de programa) que deve determinar o maior entre dois números inteiros: MAX(x,y) – O conjunto de casos testes exaustivos é infinito. Um possível
conjunto de casos de testes poderia ser:
• { (1,0)->1; (-2,-5)->-2; (9,3)->9; (34,25)->34; (0,-1)->0; (1,1)->1; (100,99)->100; (-11,-45)->-11; } read(x,y); If (x>y) then max:=x; else max:=x; print(max);
–Inspecione o código deste programa ao lado: –Aplicando-se os casos de testes acima,
conclui-se que o programa não tem erros. –No entanto, bastariam apenas três casos de testes para concluir-se que o programa tem erros.
Engenharia de Software, Jair C Leite
Geração de casos de testes
• Os casos de testes são derivados da especificação funcional (p. ex., casos de uso)
• Cada caso de teste deve definir
– Um conjunto de dados de entrada – dados de teste – O comportamento esperado do sistema
• Existem dois tipos de abordagens para determinar os casos de testes
– Testes caixa-preta – baseado na especificação do sistema
– Testes caixa-branca (transparente) – baseados na estrutura do programa
Testes caixa-preta
• São chamados testes funcionais.
• O programa é uma caixa preta cujo comportamento é determinado estudando-se as suas entradas e saídas. • Os casos de testes são
derivados da especificação funcional.
• A escolha dos dados de entrada podem ser feitas com várias técnicas:
– Partição de domínio – Grafos de causa-efeito
Engenharia de Software, Jair C Leite
Partição de domínio (equivalência)
• Inicialmente determina-se entre entradas válidas (pertencentes ao domínio) e inválidas para verificar como o sistema
comporta-se com as últimas.
• Para o domínio de dados de entradas válidas devem ser
identificadas partições (classes) para os quais o sistema tenha comportamento semelhante.
Partição de domínio – exemplo 1/2
• As partições podem ser determinadas da seguinte forma:
– Entradas que estão de acordo com o pré-requisito
– Entradas que NÃO estão de acordo com o pré-requisito – Entradas nas quais o elemento chave é membro do array
– Entradas nas quais o elemento chave NÃO é membro do array
procedure Search (Key : ELEM ; T: ELEM_ARRAY; Found : in out BOOLEAN;
L: in out ELEM_INDEX) ;
Pré-condição
-- o array tem pelo menos 1 elemento T’FIRST <= T’LAST
Pós-condição
-- o elemento é encontrado e é referenciado por L ( Found and T (L) = Key)
or
-- o elemento não está no array
( not Found and not (exists i, T’FIRST >= i <= T’LAST, T (i) = Key ))
Engenharia de Software, Jair C Leite
Partição de domínio – exemplo 2/2
• Casos de testes: • Testar com seqüências que tenham apenas 1 valor e de diferentes tamanhos
• Force o teste para que os elementos do início, meio e fim da seqüência sejam acessados • Teste com seqüência de tamanho zero.
Grafos causa-efeito
• Esta técnica oferece um representação
concisa das condições lógicas e das ações
correspondentes.
• A técnica segue 4 passos:
– Causas (condições de entrada) e efeitos (ações)
são relacionados para um módulo e um
identificador é atribuído a cada um.
– Um grafo de causa-efeito (descrito a seguir) é
desenvolvido.
– O grafo é convertido numa tabela de decisão.
– As regras da tabela são convertidas em casos de
teste.
Engenharia de Software, Jair C Leite
Grafos causa-efeito – exemplo 1/3
• Programa de cobrança de chamadas telefônicas.
– Os valores de cada chamadas são contabilizados de acordo com a duração, local de destino da chamada e faixa de
horário.
– Se o local de destino for o mesmo da origem (chamada local) e a faixa de horário for das 6:00 às 23:59 então valor do minuto é R$ 1,00.
– Se chamada local e a faixa for 0:00 às 5:59 o valor do minuto de cada chamada é R0,50.
– Se o local for um outro estado no país (chamada
interurbana) e a faixa de horário for das 9:00 às 21:00 então o valor do minuto é calculado de acordo com o valor básico por estado.
– Se chamada interurbana e faixa de horário for das 21:00 às 9:00 o valor do minuto é fixo, sendo R$1,00.
– Se chamada internacional o valor não depende de faixa de horário e é calculado de acordo com o valor básico por país.
Grafos causa-efeito – exemplo 2/3
• Para o programa
cobrança temos então as causas
– tipo da chamada: local (CL), interurbana (DDD) e internacional (DDI) – faixa de horário: 6-24,
0-6, 9-21, 21-9
– estado ou país: AC,AM, AP, ... (estados do
Brasil), EUA, RU, JP, ...
• Os efeitos esperados são os cálculos de cobrança conforme especificado – F1= duração*R$1,00 – F2= R$0,50 – F3= duração*valor_localidad e ^ - e lógico v - ou lógico
Engenharia de Software, Jair C Leite
Grafos causa-efeito – exemplo 3/3
• Com base no grafo podemos derivar cinco casos de
teste para verificar se para as entradas
correspondentes (causas) o programa realiza os
cálculos correspondentes (efeitos).
– Caso1: {tipo_da_chamada=CL, faixa_de_horário=6-24, valor_localidade=X}
– Caso2: {tipo_da_chamada=DDD, faixa_de_horário=21-9, valor_localidade=X}
– Caso3: {tipo_da_chamada=CL, faixa_de_horário=0-6, valor_localidade=X}
– Caso4: {tipo_da_chamada=DDD, faixa_de_horário=9-21, valor_localidade=X}
– Caso5: {tipo_da_chamada=DDI, faixa_de_horário=Y, valor_localidade=X}
Teste caixa-branca (estrutural)
• Analisa a estrutura do programa para determinar os casos de teste
• Exemplo: teste do caminho básico
– Visa determinar um conjunto de casos de teste que garanta que todos os caminhos (fluxos) através do programa sejam percorridos. – Utiliza-se um grafo de fluxo de programa onde cada nó representa
uma decisão e cada arco um caminho possível.
– O grafo é usado como base para determinar a complexidade ciclomática do programa
Engenharia de Software, Jair C Leite class BinSearch {
// This is an encapsulation of a binary search function that takes an array of // ordered objects and a key and returns an object with 2 attributes namely // index - the value of the array index
// found - a boolean indicating whether or not the key is in the array
// An object is returned because it is not possible in Java to pass basic types by // reference to a function and so return two values
// the key is -1 if the element is not found
public static void search ( int key, int [] elemArray, Result r ) {
int bottom = 0 ;
int top = elemArray.length - 1 ; int mid ;
r.found = false ; r.index = -1 ; while ( bottom <= top )
{
mid = (top + bottom) / 2 ; if (elemArray [mid] == key) { r.index = mid ; r.found = true ; return ; } // if part else {
if (elemArray [mid] < key) bottom = mid + 1 ; else top = mid - 1 ; } } //while loop } // search } //BinSearch
Testes de caminho – exemplo
Complexidade ciclomática = 11 – 9 + 2 = 4 •Caminhos independentes:•1, 2, 3, 8, 9
•1, 2, 3, 4, 6, 7, 2 •1, 2, 3, 4, 5, 7, 2
•1, 2, 3, 4, 6, 7, 2, 8, 9