Teste de Software
Engenharia de Software 2o. Semestre de 2005
UNIVERSIDADE ESTADUAL PAULISTA
INSTITUTO DE BIOCIÊNCIAS, LETRAS E CIÊNCIAS EXATAS
Testes para a detecção de defeitos
●
Testar programas para
estabelecer a presença de
defeitos no sistema.
Tópicos
● Testes para a detecção de defeitos
● Testes de integração
O processo de teste
● Testes de componentes
• Testes de componentes de programas individuais.
• Usualmente os programadores assumem a responsabilidade pelo teste de seu código (exceto em caso de sistemas
críticos).
• Testes são derivados da experiência do desenvolvedor.
● Testes de integração
• Testes de grupos de componentes integrados para formar subsistemas ou sistemas completos.
• Uma equipe independente de teste fazem o teste de integração.
Teste para detecção de defeitos
● O objetivo de testes para a detecção de
defeitos é revelar defeitos latentes nos programas.
● Um teste bem sucedido é aquele que revela a
presença de um defeito (faz com que o
programa se comporte de maneira anômala)
● Testes mostram a presença e não a ausência
● A única maneira de mostrar que um programa está
correto é o teste exaustivo. Contudo, teste exaustivo é teste exaustivo impraticável
impraticável.
● Testes devem ser baseados em um subconjunto de subconjunto
possíveis casos de teste.
● Políticas devem ser utilizadas para escolher esse
conjunto.
• Ex: todas as declarações do programa devem ser testadas pelo menos uma vez
• Todas as funções de sistema acessados por meio de menus devem ser testadas, etc.
●
● Dados de teste entradas criadas para testar o Dados de teste
sistema.
●
● Casos de teste Entradas para testar o sistema Casos de teste
e saídas esperadas para essas entradas (
quando o sistema opera de acordo com suas especificações) .
Processo de teste para a detecção
de defeitos
Design test
cases Prepare testdata with test dataRun program Compare r esultsto test cases Test cases Test data Test results Test reports Casos de teste Casos de teste Dados de teste Dados de teste Resultados de teste Resultados de teste Relatórios de teste Relatórios de teste Projetar casos de teste Projetar casos
de teste Preparar dados
de teste
Preparar dados
de teste Executar programa
com dados de teste
Executar programa
com dados de teste Comparar resultados
com os casos de teste
Comparar resultados com os casos de teste
Teste de caixa preta
● Uma abordagem de teste onde o programa é
considerado como uma “caixa-preta”.
● Os casos de teste para testar o programa são
baseados na especificação do sistema.
● O planejamento dos testes podem começar nos
Teste Caixa preta
Ie Entrada de
Dados de teste
Saída dos resultados de
teste Oe
SISTEMA
SISTEMA
Entradas que provocam comportamento anômalo
Saídas que revelam a presença de defeitos
Problema: selecionar entradas ÎIe
Particionamento de equivalência
(abordagem sistemática para seleção de dados de teste)
● Dados de entrada e resultados de saída caem
em diferentes classes onde todos os membros de uma classe são relacionados
● Cada uma dessas classes é uma partição de
equivalência onde o programa se comporta de uma maneira equivalente para cada membro da classe
● Casos de teste devem ser escolhidos de cada
(abordagem sistemática para seleção de dados de teste)
Particição de Equivalência
S y ste m
Ou tput s
● Entradas e saídas do sistema são particionadas
em “conjuntos de equivalência”
• Se a entrada é um inteiro de 5 dígitos entre 10.000 e 99.999, partições de equivalência são números < 10.000, números entre 10.000 e 99. 999 e números > 99. 999
● Escolher casos de teste nos limites das
partições:
• 00000, 09.999, 10.000, 50.0000, 99.999, 100.000
(abordagem sistemática para seleção de dados de teste)
(abordagem sistemática para seleção de dados de teste)
Partições de equivalência
Betw een 10 00 0 an d 99 99 9 Less th an 1 00 00 M o re than 99 99 9 9 99 9 1 00 00 5 00 00 1 00 00 0 9 99 99 Inp ut valu es Betw een 4 an d 10 Less th an 4 M o re than 10 3 4 7 1 1 1 0Nu m ber of inp ut v alu es
O programa aceita entre 4 a 10 entradas, que são números inteiros de cinco dígitos, maiores do que 10.000 e menores que 99.999
Especificação de uma rotina de
busca
procedure Search (Key : ELEM ; T: ELEM_ARRAY; Found : in out BOOLEAN; L: in out ELEM_INDEX) ; Pré-condição
-- a seqüência tem pelo menos um elemento T’FIRST <= T’LAST
Pós-condição
-- O elemento é encontrado e é referenciado por L ( Found and T (L) = Key)
ou
-- O elemento não está na seqüência ( not Found and
● Entradas que estão de acordo com a pré
condição: seqüência com no mínimo um elemento.
● Entradas onde a pré condição não vale.
● Entradas onde o elemento chave é um
elemento da seqüência.
● Entradas onde o elemento chave não é um
membro da seqüência.
Rotina de busca - partições de
entrada
Diretrizes de testes (no caso do
exemplo usado)
● Teste o software com seqüências que possuem
somente um único valor.
● Use diferentes seqüências, de diferentes
tamanhos, em diferentes testes.
● Derive testes de maneira que o primeiro, o
médio e o último elemento da seqüência sejam acessados.
Rotina de busca - partições de
equivalência
V e t o r E l e m e n t o V a l o r ú n i c o E s t á n a s e q ü ê n c i a V a l o r ú n i c o N ã o e s t á n a s e q ü ê n c i a M a i s q u e 1 v a l o r P r i m e i r o e l e m e n t o e s t á n a s e q ü ê n c i a M a i s q u e 1 v a l o r Ú l t i m o e l e m e n t o e s tá n a s e q ü ê n c i a M a i s q u e 1 v a l o r E l e m e n t o m é d i o e s tá n a s e q ü ê n c i a M a i s q u e 1 v a l o r N ã o e s tá n a s e q ü ê n c iaSeqüência de entradas (T) Chave (key) Saídas (Found, L)
17 17 Verdadeiro, 1 17 0 Falso, ?? 17, 29, 21, 23 17 Verdadeiro, 1 41, 18, 9, 31, 30, 16, 45 45 Verdadeiro, 7 17, 18, 21, 23, 29, 41, 38 23 Verdadeiro, 4 21, 23, 29, 33, 38 25 Falso, ??
● Algumas vezes chamado testes de “caixa
branca”.
● Derivação de casos de teste de acordo com a
estrutura do programa. O conhecimento do programa é usado para identificar casos de testes adicionais.
• Exemplo: exercitar todas as declarações do programa.
Testes caixa branca
Co mpo nent cod e Test o utputs Test d ata Derives Tests Co mpo nent cod e Test o utputs Test d ata Derives Tests Dados de teste Dados de teste Código de componente Código de componente Saídas do teste Saídas do teste Testa DerivaTestes de Caminho
● O objetivo dos testes de caminho é garantir que
o conjunto de casos de teste é tal que cada caminho do programa é executado no mínimo uma vez.
● Para o teste de caminho, elabora-se um grafo
de fluxo de programa, onde os nós, representam os pontos de decisão do
programa, e os arcos representam o fluxo de controle.
● Modelo em esqueleto de todos os caminhos do
programa.
● Consiste em nós que representam decisões e
em ramos que mostram o fluxo de controle.
● É construído através do código fonte, onde
substitui-se os comandos por nós e desvios nós
pelos arcos (ou ramos) do grafo.arcos
● Declarações seqüenciais são ignoradas na
construção do grafo de fluxo.
● Em um comando condicional, cada ramo é
mostrado como um caminho separado, e laços são indicados por uma seta fazendo o loop de volta para o nó de condição do laço.
● Usado como base para calcular o número de
caminhos independentes no programa.
● Caminho independente - caminho que
atravessa pelo menos um novo ramo no grafo de fluxo.
● O número de caminhos independentes no
código é igual à complexidade complexidade ciclomática.ciclomática
● Cálculo da Complexidade ciclomática:
CC = Número de ramos - Número de nós + 2.
● Complexidade ciclomática determina o número
de casos de teste mínimo para testar adequadamente todos os caminhos independentes do programa.
class BinSearch {
// Esse é um encapsulamento de uma função de busca
// binária que considera um vetor de objetos ordenados e uma chave // e retorna um objeto com 2 atributos, chamados
// index – o valor do índice de vetor
// found – um booleano que indica se uma chave está ou não no vetor // A chave será –1 se o elemento não for encontrado
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 ; }
Grafo de fluxo para Busca Binária 1 2 3 4 6 5 7 w hile bo ttom < = to p
if (elem A rray [m id] == k ey
(i f (elemA rray [mi d]< key 8
9 b otto m > top
● 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
● Casos de teste devem ser projetados para
executar todos esses caminhos.
Exercício: elaborar um conjunto de dados que execute os caminhos independentes acima.
● Útil se usado com cuidado.
● Não implica que o programa foi
adequadamente testado - embora todos os caminhos independentes são executados,
todas as combinações possíveis de caminhos não são executadas.
Testes de integração
● Testes feitos em sistemas completos ou
subsistemas, compostos de componentes integrados.
● Testes de integração devem ser desenvolvidos
a partir da especificação do sistema.
● A maior dificuldade é a localização de erros.
Testes de integração incremental
T3 T2 T1 T4 T5 A B C D T2 T1 T3 T4 A B C T1 T2 T3 A BTest s equ ence 1
Test s equ ence 2
Test s equ ence 3
Seqüência de teste 1
Seqüência
Abordagens para o teste de
integração
● Teste de integração top-down
• Começa com os componentes de alto nível de um sistema, e a integração se dá de cima para baixo em uma hierarquia de componentes. Componentes individuais em um nível mais baixo na hierarquia são representados por stubs.
● Teste de integração bottom-up
• Envolve integrar e testar os módulos de nível inferior na
hierarquia e, então, subir na hierarquia de módulos, até que o módulo final seja testado.
● Na prática, a maioria das integrações envolve a
Testes de integração Top-down
Level 2 Le vel 2
Level 2 Level 2
Level 1 Testin g Level 1 seq uen ce Le vel 2 stu bs Le vel 3 stubs . . . Seqüência de testes Stubs do nível 2 Stubs do nível 3
Testes de integração bottom-up
Lev el N Lev el N Le vel N Level N Lev el N Lev el N– 1 Lev el N– 1 Level N– 1 Testin g s eq uen ce Test d rivers Test d riv ers Seqüência de testes Drivers de teste Drivers de testeSlide 34
Vantagens e desvantagens das
abordagens de teste
● Validação da arquitetura
• Os testes top-down oferecem maior probabilidade de
descobrir erros na arquitetura de sistema, em um estágio inicial do processo de desenvolvimento.
● Demonstração do sistema
• Os testes de integração top-down permite a demonstração de um sistema de trabalho limitado em uma fase inicial do
desenvolvimento.
● Implementação de teste
• Testes top-down são mais difíceis de implementar pois é necessário a produção de stubs (programas que simulam níveis inferiores)
● Observação de teste
● Ocorrem quando módulos ou subsistemas são
integrados para criar sistemas maiores.
● Objetivo é detectar erros devido a erros ou
suposições inválidas sobre interfaces.
● Particularmente importante para o
desenvolvimento orientado a objeto, uma vez que os objetos são definidos por suas
interfaces
Testes de Interface
Test cases B A CDiretrizes para os testes de
interface
● Projete conjunto de testes em que o valor dos
parâmetros para os componentes externos esteja nos limites extremos.
● Sempre teste parâmetros ponteiros com ponteiros
nulos.
● Em sistemas de passagem de mensagem, projete
testes que gerem muito mais mensagens que é provável ocorrer na prática (teste de estresse).estresse)
● Em um sistemas de memória compartilhada, varie a
Testes de estresse
● Exercitam o sistema além de sua carga máxima
de projeto, até o sistema falhe.
● Testa o comportamento de falha do sistema. É
importante que a falha não cause a corrupção de dados ou a perda inesperada de serviços do usuário.
● Particularmente relevantes para sistemas
distribuídos, que podem exibir uma degradação severa quando a rede se torna sobrecarregada.
● Os componentes a serem testados são classes
de objetos que são instanciadas como objetos.
● Diferentes de teste funcional, pois:
• Objetos individuais são, muitas vezes, maiores do que funções isoladas. Abordagens de teste de caixa-branca devem ser estendidas.
• Testadores podem não ter acesso ao código fonte do componente para análise, no caso de reuso de objetos
• Não existe um nível superior óbvio para integração e teste top-down.
4 Níveis de teste
● Testar as operações associadas com os
objetos.
● Testar classes de objetos individuais.
● Testar agrupamentos de objetos que cooperam
entre si.
Testes de classes de objetos
● A cobertura completa de testes deve incluir
• Testar todas as operações associadas com um objeto • Estabelecimento e a interrogação de todos os atributos
associados com o objeto
• Exercitar o objeto em todos os estados possíveis (simular todos os eventos que provoquem mudança de estado no objeto)
● Herança dificulta o projeto de testes de classe
de objetos. Quando uma superclasse fornece operações herdadas por subclasses, todas
Integração de objetos
● Níveis de integração são menos distintos em
sistemas orientados a objetos.
● Testes de clusters se ocupam com a integração
e teste de objetos que cooperam entre si.
● Clusters devem ser identificados utilizando-se o
conhecimento de suas operações e as
características do sistema implementadas por esses clusters.
Pontos chave
● É mais importante testar as partes do sistema
mais comumente utilizadas do que as partes que são exercitadas raramente.
●
● Partição de equivalênciaPartição de equivalência é uma maneira de
derivar casos de teste. Partições são conjuntos de dados onde o programa deve se comportar de maneira equivalente.
●
● Teste de caixa pretaTeste de caixa preta é baseado na especificação
do sistema. Não precisa analisar o código fonte.
●
Pontos chave
● Os testes de integração se concentram no testes de integração
teste das interações entre os componentes.
● Os testes de interface procuram descobrir testes de interface
defeitos nas interfaces ou nos módulos.
● Para testar as classes de objetos, deve-se testar as classes de objetos
testar todas as operações, atributos e estados.
● Sistemas orientados à objetos devem ser
integrados