Diretrizes: Teste Unitário Tópicos
O teste unitário é implementado com base no menor elemento testável (unidades) do software e implica em testar a estrutura interna (como fluxo lógico e de dados), a função da unidade e os comportamentos observáveis. O design e a implementação de testes com ênfase na estrutura interna de uma unidade se baseiam no conhecimento da implementação da unidade (abordagem caixa branca). No entanto, o design e a implementação de testes com a finalidade de verificar os comportamentos observáveis e as funções da unidade não se baseiam no conhecimento da implementação; por isso, são conhecidas como abordagem caixa preta.
As duas abordagens são usadas para projetar e implementar os diferentes tipos de testes (consulte Conceitos: Tipo de Testes) necessários para testar as unidades de forma completa e correta.
Além das considerações individuais de cada tipo de teste e das duas abordagens mencionadas aqui, existem várias considerações de design e de implementação que se aplicam somente ao teste unitário, a saber:
Informações adicionais sobre esses tópicos são fornecidas nas seções a seguir.
Consulte também Diretrizes: Caso de Teste para obter informações adicionais sobre como gerar casos de teste para o teste unitário.
Uma abordagem de teste caixa branca deve ser realizada para verificar a estrutura interna de uma unidade. Teoricamente, cada caminho possível ao longo do código deve ser testado, mas isso só pode ser feito em unidades muito simples. Você deve testar cada caminho de decisão-a-decisão (caminho DD) pelo menos uma vez, pois assim estará executando todas as instruções ao menos uma vez. Em geral, uma decisão é uma instrução if, e um caminho DD é aquele que une duas decisões.
Para obter esse nível de cobertura de teste, é recomendável que você escolha os dados de teste de modo que cada decisão seja avaliada de todas as formas possíveis.
Use as ferramentas de cobertura de código para identificar o código não experimentado pelo teste caixa branca. O teste de confiabilidade deve ser realizado simultaneamente com o teste caixa branca.
Consulte Diretrizes: Caso de Teste para obter informações adicionais.
A finalidade de um teste da caixa preta é verificar a função especificada e o comportamento observável da unidade sem que seja necessário saber como a unidade os implementa. Os testes caixa preta se concentram e se baseiam na entrada e saída da unidade.
A geração de testes unitários com base na abordagem da caixa preta utiliza os argumentos de entrada e saída das operações da unidade e/ou o estado de saída para avaliação. Por exemplo, a operação pode incluir um algoritmo (requerendo dois valores como entrada e retornando um terceiro como saída) ou iniciar a alteração no estado de um objeto ou componente, como a inclusão ou exclusão de um registro de banco de dados. Ambos devem ser testados por completo. Para testar uma operação, você deve obter casos de teste suficientes para verificar se:
- para cada valor aceito utilizado como entrada, um valor apropriado foi retornado pela operação
- para cada valor não aceito utilizado como entrada, somente um valor apropriado foi retornado pela operação
- para cada estado de entrada válido, ocorre um estado de saída apropriado
- para cada estado de entrada inválido, ocorre um estado de saída apropriado
Use as ferramentas de cobertura de código para identificar o código não experimentado pelo teste caixa branca. O teste de confiabilidade deve ser realizado simultaneamente com o teste caixa preta.
Consulte Diretrizes: Caso de Teste para obter informações adicionais.
Se uma operação herdada não funcionar na classe descendente, ela será classificada como um problema de interação entre a classe descendente e a classe ascendente. Você pode verificar a interação entre unidades ao testar os casos de uso. Não teste as operações herdadas durante o teste das unidades. Elas serão testadas durante o teste dos casos de uso.
Uma operação herdada pode falhar em duas situações: - Quando a classe descendente modifica as variáveis de instância (ou participante) para as quais a operação herdada assume determinados valores.
- Quando as operações na classe ascendente disparam uma operação implementada na classe descendente.
Você pode evitar a primeira situação proibindo as classes ascendentes de modificar as variáveis de instância (ou participante) herdadas, a não ser que isso seja feito através das operações herdadas. Você pode evitar a segunda situação testando completamente as operações disparadas.
É claro que as classes que não são instanciadas, mas que existem somente para que outros as herdem, devem ser testadas. Como o teste de instâncias não é expressivo, a conseqüência exata disso pode não ser óbvia, já que, por definição, uma classe abstrata não possui instâncias. No entanto, uma classe abstrata pode ser herdada, e as instâncias de suas classes descendentes podem ser criadas. Por isso, uma das metas do teste dessas classes é determinar se a herança é possível e se existem instâncias de classes descendentes. Uma segunda meta é determinar se possíveis chamadas para a própria classe abstrata (this em C++, self em Smalltalk) acontecerão. Para testar isso, deixe que o programa de teste crie uma classe descendente que herde a classe abstrata. Esse programa testará a unidade testando a classe descendente.

O programa de teste criará uma classe descendente da unidade de testada.
O polimorfismo é um conceito de linguagem de programação que torna mais fácil alterar o código, mas que dificulta o processo de teste. No exemplo a seguir, não é possível testar o código com cada subclasse de Shape. Isso deve ser feito durante o teste dos casos de uso.
Um efeito interessante do polimorfismo em linguagens orientadas a objetos é que cada envio de mensagem em Smalltalk e cada chamada de função em C++ é uma instrução CASE em potencial.
Exemplo:
Suponhamos que você tenha a seguinte hierarquia de classe e que a classe Shape tenha uma operação Draw.

Copyright © 1987 - 2001 Rational Software Corporation
|