Técnicas de Testes

Nesta seção discutiremos sobre as técnicas para os projetos de casos de teste de software, esta enfoca um conjunto de técnicas para a criação de casos de teste, que satisfazem aos objetivos globais e as estratégias de testes já discutidas.


-->
As técnicas de testes são diretrizes sistemáticas para projetar testes que exercitam a lógica e as interfaces de cada componente, através dos domínios de entrada e saída do programa para descobrir erro na função, no componente e no desempenho do programa.
Responsáveis: Nos primeiros estágios dos testes um engenheiro realiza todos os testes, a medida que os testes progridem, especialistas podem ser envolvidos.
Importância: O programa deve ser executado antes de chegar ao cliente, com o objetivo especifico de encontrar e remover todos os erros, testes devem ser conduzidos sistematicamente, para isto casos de testes devem ser projetados usando técnicas disciplinadas.
Passos: Nas aplicações convencionais o software é testado sob duas perspectivas diferentes: Caixa-Branca – a lógica interna do programa é exercitada usando técnicas de projeto de casos de teste. Caixa-Preta – requisitos de software são exercitados por meio de projeto de casos de teste. Obs.: para aplicações orientadas a objetos o teste começa antes da existência do código. Nos dois casos o objetivo é encontrar o maior número de erros com a menor quantidade de esforço e tempo. Casos de uso ajudam no projeto de testes para descobrir erros no âmbito da validação do software.
Produtos: Um conjunto de casos de teste é projetado para exercitar a lógica interna, interfaces, colaborações de componentes e os requisitos externos são projetados e documentados, os resultados esperados são definidos e os resultados reais são registrados.

TESTES CAIXA-PRETA 

-->
Refere-se a testes que são conduzidos na interface do software, este examina algum aspecto fundamental do sistema, sem se preocupar com a estrutura lógica interna do software.
Também conhecido como teste comportamental, este tipo de teste tenta encontrar erros nas seguintes categorias:
Funções incorretas ou omitidas;
Erros de interface;
Erros de estrutura de dados ou de acesso a base de dados externa;
Erros de comportamento ou desempenho;
Erros de iniciação e término.
Aplicado durante os últimos estágios do teste, a atenção é focada no domínio da informação.
-->
Esta aplicação deriva um conjunto de casos de teste que satisfazem os seguintes critérios: casos de teste que reduzem, de um valor que é maior do que 1, o número adicional de casos de teste que precisam ser projetados para atingir um teste razoável e casos de teste que nos dizem algo sobre a presença ou ausência de classes de erros, em vez de um erro associado somente com o teste especifico em mãos.
 
MÉTODOS DE TESTE BASEADO EM GRAFO 

-->
Neste tipo de teste o primeiro passo é entender os objetos (objetos de dados, componentes tradicionais (módulos) e elementos orientados a objetos de software de computador) que estão modelados no software e as relações que conectam esses objetos, em seguida definir uma série de testes que verifica se “todos os objetos têm a relação esperada uns com os outros”. Para isto o engenheiro de software cria um grafo, uma coleção de nós que representam objetos representados por círculos; ligações que representam as relações entre objetos, representadas por setas; pesos de nó que descrevem as propriedades de um nó.  Com as seguintes ligações:
-->
Ligação direcionada – uma seta indica que a relação se move em apenas uma direção.
Ligação bidirecional (ligação simétrica) – a relação é aplicada em ambas as direções.
Ligações paralelas – usadas quando diversas relações diferentes são estabelecidas entre nós de grafos.
Beizer [BEI95] descreve alguns métodos de teste de comportamento que podem fazer o uso de grafos:
 
-->
Modelagem de fluxo de transação – os nós representam passos em alguma transação (por exemplo, os passos necessários para fazer uma reserva em uma linha aérea usando o serviço on-line), use o diagrama de fluxo de dados (DFD) para criar grafos desse tipo.
Modelagem de estado finito – os nós representam diferentes estados do software observáveis pelo usuário (exemplo cada uma das telas abertas no momento que o usuário realiza uma operação), as ligações representam transições que ocorrem para ir de um estado para outro. Diagrama de Estado podem ser usados para representar esta modelagem.
Modelagem de fluxo de dados – nós são objetos de dados e as ligações são transformações que ocorrem para traduzir um objeto de dados em outro.
Modelagem de tempo - nós são objetos de programas e as ligações são conexões seqüências entre estes objetos. Os pesos das ligações são usados para especificar o tempo de execução necessário para o programa ser executado.

PARTICIONAMENTO DE EQUIVALÊNCIA 
-->

Este teste divide o domínio de entrada de um programa em classes de dados, das quais os casos de teste podem ser derivados. Um caso de teste ideal descobre sozinho uma classe de erros que poderia de outra forma exigir que muitos casos fossem executados antes que um erro geral fosse observado. Buscando definir um caso de teste que descobre classes de erros, reduzindo assim o número total de casos de testes que precisam ser criados.
O projeto de casos de teste para este tipo de teste é baseado em uma avaliação das classes de equivalência para uma condição de entrada, se o conjunto de objetos puder ser ligado por relações simétricas, transitivas e reflexivas, uma classe de equivalência estará presente. Uma classe de equivalência representa um conjunto de estados válidos ou inválidos para condições de entrada que é um valor numérico especifico, um intervalo de valores, um conjunto de valores relacionados ou uma condição booleana. 
  -->
Veja as diretrizes:
1 Se uma condição de entrada especifica um intervalo, uma classe de equivalência válida e duas inválidas devem ser definidas;
2 Se uma condição de entrada exige um valor específico, uma classe de equivalência válida e duas inválidas são definidas;
3 Se uma condição de entrada especifica o membro de um conjunto, uma classe de equivalência válida e uma inválida são definidas;
4 Se uma condição de entrada é booleana, uma classe de equivalência válida e uma inválida são definidas.
Veja um exemplo:
Dividir todas as combinações possíveis em classes. Em um sistema de gestão de contratos, a idade dos clientes varia de 18 a 120 anos.
  

ANÁLISE DE VALOR LIMITE 

-->
A análise de valor limite (BVA - boundary value analysis) leva a seleção de casos de teste que exercitam os valores limítrofes (erros que ocorre nas fronteiras do domínio de entrada em vez de no “centro”.
É uma técnica de projeto de casos de teste que completa o particionamento de equivalência. Em vez de selecionar qualquer elemento de uma classe de equivalência, a BVA leva a seleção de casos de teste nas “bordas” da classe. Em vez de focalizar somente as condições de entrada, ela deriva casos de teste também para o domínio de saída.
Veja as diretrizes:
1 Se uma condição de entrada especifica um intervalo limitado pelos valores a e b, casos de teste devem ser projetados com os valores a e b, e imediatamente acima e abaixo de a e b;
2 Se uma condição de entrada especifica vários valores, casos de teste devem ser desenvolvidos para exercitar os números mínimos e máximos. Valores imediatamente acima e abaixo devem ser testados;
3 Aplique as condições 1 e 2 às condições de saída. Casos de teste devem ser projetados para criar um relatório de saída que produza o número máximo (e mínimo) admissível de entradas na tabela;
4 Se as estruturas de dados internas do programa tem limites prescritos (exemplo: um vetor tem um limite definido de 100 entradas), elabore um caso de teste para exercitar a estrutura de dados no seu limite.
A maioria dos engenheiros de software realiza a BVA intuitiva em um certo grau. Aplicando estas diretrizes, o teste de limite será mais completo, tendo assim uma maior probabilidade de detecção de erros.
Veja um exemplo:


TESTE DE MATRIZ ORTOGONAL 

-->
Este tipo de teste é aplicado a problemas nos quais o domínio de entrada é relativamente pequeno, mas grande demais para acomodar o teste exaustivo, é útil para encontrar erros associados com falhas de regiões – uma categoria de erros associada com lógica defeituosa em um componente de software.
Exemplo: considere um sistema que tem três itens de entrada: X, Y e Z, cada um desses itens de entrada possui três valores discretos associados a eles. Há então 3^3 = 27 possíveis casos de teste.
Quando o teste de matriz ortogonal ocorre, é criada uma matriz ortogonal L9 de casos de teste, com a propriedade de balanceamento.
A avaliação dos resultados de um caso de teste utilizando a matriz L9 ocorre do seguinte modo:
Detecta e isola todas as falhas de modo singular – uma falha de modo singular é um problema consistente com qualquer nível de qualquer parâmetro singular, exemplo se todos os casos de teste do fator P1 = 1 causam um erro de condição, temos uma falha de modo singular. Pela análise da informação sobre quais testes revelam erros, pode-se identificar quais valores de parâmetros causam a falha, este tipo de isolamento é importante para corrigir a falha.
Detecta todas as falhas de modo duplo – falha de modo duplo consiste se existe um problema consistente quando níveis específicos de dois parâmetros ocorrem simultaneamente. É uma indicação de incompatibilidade do par ou de interações danosas entre dois parâmetros de teste.
Falhas de multímodo – tais matrizes podem garantir a detecção apenas de falhas de modo singular e duplo. No entanto, muitas falhas de multímodo são também detectadas por esses testes.
Vale ressaltar que este tipo de teste permite projetar casos de teste que fornecem máxima cobertura com um número razoável de casos de teste, do que a estratégia exaustiva.
 


TESTES ORIENTADOS A OBJETOS 

-->
A arquitetura Orientada a Objetos resulta em uma série de subsistemas em camadas que encapsulam classes de colaboração, sendo que cada uma dessas classes executam funções que ajudam a satisfazer aos requisitos do sistema.
É necessário testar um sistema OO em uma variedade de níveis diferentes para descobrir erros que podem ocorrer a medida que classes colaboram umas com as outras e subsistemas se comunicam entre as camadas arquiteturais.
Este tipo de teste é estrategicamente similar ao teste de sistemas convencionais, mas taticamente diferente.
Modelo de análise e projeto OO são similares na estrutura e no conteúdo para o programa OO, assim o “teste” pode começar com a revisão desses modelos. Após gerar o código, o teste OO real começa no “varejo” com testes elaborados para exercitar operações de classes e examinar se existem erros quando uma classe colabora com outras classes. Ao integrar estas classes formando um subsistema, o teste baseado no uso, com abordagens tolerantes a falhas, é aplicado para exercitar as classes que colaboram entre si.
Os casos de uso são usados para descobrir erros no nível de validação do software.
O projeto de caso de teste no método convencional aborda uma visão de software de entrada-processo-saída ou detalhes algorítimicos de módulos individuais, já teste orientado a objetos enfoca o projeto de seqüência apropriadas de operações para exercitar os estados de uma classe.
Como os atributos e operações são encapsulados, o teste de operações fora da classe é geralmente improdutivo. Apesar do encapsulamento ser um conceito de projeto essencial para OO, ele pode criar um pequeno obstáculo quando o teste é conduzido.
Vale ressaltar que a herança também leva a desafios adicionais para o projetista de casos de teste. Cada contexto de uso exige retestagem, mesmo que o reuso tenha sido concebido.
Se subclasses instanciadas de uma superclasse são usadas no mesmo domínio do problema, é provável que o conjunto de casos de teste derivado para a superclasse possa ser usado para testar a subclasse.
 


APLICAÇÃO DE MÉTODOS CONVENCIONAIS DE PROJETO DE CASOS DE TESTE


-->
Os métodos de teste caixa-branca podem ser aplicados a operações definidas para uma classe, no entanto a estrutura concisa de muitas operações de classe faz alguns argumentarem que o esforço aplicado a este tipo de teste poderia ser mais bem redirecionado para testes do nível da classe.
Já os métodos de teste caixa-preta são adequados para sistemas OO.
Veja os tipos de testes que contém a arquitetura OO:

TESTE BASEADO EM ERRO 

--> -->
Objetivo projetar testes que tenham uma grande probabilidade de descobrir erros plausíveis. Aqui casos de teste são projetados para exercitar o projeto ou o código. O sistema deve satisfazer aos requisitos do cliente, o planejamento pré-liminar para criação de testes baseados em erros começa com o modelo de análise.
O teste de integração procura erros plausíveis na chamada de operações ou nas conexões de mensagens, sendo que três tipos de erros são encontrados neste contexto: resultado inesperado, uso da operação/mensagem errada e invocação incorreta. Este teste é aplicado tanto a atributos quanto a operações. A determinação de erros plausíveis deve ser feita quando funções (operações) são invocadas, o comportamento da operação deve ser examinado. O teste de integração tenta encontrar erros no objeto cliente, não no servidor, o foco é determinar se existem erros no código que chama, não no código chamado.
Este tipo de teste não encontra dois tipos principais de erros: especificações incorretas, ou seja, o produto não faz o que o cliente deseja, pode fazer a coisa errada ou pode omitir funcionalidade importante e ocorrem erros associados com a interação de subsistemas quando o comportamento de um subsistema cria circunstâncias (eventos, fluxo de dados) que provoquem a falha do outro subsistema.       
-->
Concluímos aqui que a efetividade dessa técnica depende de como os testadores consideram um erro plausível. Se erros reais em um sistema OO são considerados não plausíveis, então tal abordagem não é realmente melhor do que qualquer técnica aleatória. Se os modelos análise e projeto puderem fornecer conhecimento aprofundado sobre o que é provável dar errado, dessa forma o teste baseado em erros pode encontrar um número significativo de erros com esforço relativamente baixo. 

TESTE COM BASE EM CENÁRIO 

--> -->
O teste baseado em cenário concentra-se no que o usuário faz, não no que o produto faz, detecta as tarefas por meio de casos de uso, que o usuário precisa realizar depois aplicá-las, bem como suas variantes, aos testes. Vai descobrir erros que ocorrem quando qualquer ator interage com o software.
Cenários descobrem erros de interação, mas para isto os casos de teste precisam ser mais complexos e mais realísticos do que os testes baseados em erro.
Este tipo de teste exercita múltiplos subsistemas em um único teste, os usuários não se limitam ao uso de um subsistema de cada vez.

TESTE DA ESTRUTURA SUPERFICIAL E DA ESTRUTURA PROFUNDA 

-->
A estrutura superficial refere-se à estrutura de um programa OO externamente observável, a estrutura que é imediatamente obvia a um usuário final, os testes são baseados nas tarefas do usuário, captar estas tarefas envolve entender, observar e falar com usuários representativos e não representativos.
Assim os melhores testes são originados quando o projetista olha o sistema de um modo novo ou não convencional. Aqui o projeto de casos de teste deve usar tanto os objetos quanto as operações como indícios que levem a tarefas despercebidas.
A estrutura profunda refere-se aos detalhes técnicos internos de um programa OO, a estrutura é entendida pelo exame do projeto e/ou código. Este tipo de teste é projetado para exercitar dependências, comportamentos e mecanismos de comunicação estabelecidos como parte do projeto do sistema de objetos do software OO. Aqui os modelos de análise e projeto são usados como base para o teste de estrutura profunda. O diagrama de colaboração UML ou o modelo de implantação mostram as colaborações entre objetos e subsitemas que podem não ser externamente visíveis. 

MÉTODOS DE TESTE APLICÁVEIS AO NÍVEL DE CLASSE 

-->
O teste aleatório e de partição são métodos que podem ser usados para exercitar uma classe durante o teste OO. 
Veja a seguir os métodos: 

TESTE ALEATÓRIO PARA CLASSE OO 

-->
Para cada classe defini as possíveis operações da mesma aplicando algumas restrições de acordo com a natureza do problema, mesmo com tais restrições existe  muitas permutações das operações. Gerando assim uma variedade de diferentes seqüências de operação que pode ser gerada aleatoriamente.
Para este tipo de teste o número de permutações possíveis pode ficar muito grande, aplicar o teste de matriz ortogonal pode ajudar a melhorar a eficiência deste teste.
 


TESTE DE PARTIÇÃO NO NÍVEL DE CLASSE
 
-->
Este tipo de teste reduz o número de casos de teste necessários para exercitar a classe de um modo semelhante ao da partição de equivalência para software convencional. Entrada e saída são categorizadas e casos de testes são projetados para exercitar cada categoria. Veja as categorias de partição:


Partição baseada em estado – categoriza as operações de classes com base na sua capacidade de mudar o estado da classe. Os testes são projetados de modo que exercitem, separadamente as operações que mudam o estado e aquelas que não mudam o estado.


Partição baseada em atributo - categoriza as operações de classes com base nos atributos que elas usam que podem ser divididas em: operações que usam, operações que modificam e operações que não usam e nem modificam.


Seqüências de teste são então projetadas para cada partição.


Partição baseada em categoria - categoriza as operações de classes com base na função genérica que cada uma realiza.

PROJETO DE CASOS DE TESTE INTERCLASSE 

-->
Quando a integração do sistema OO tem início o projeto de casos de teste torna-se mais complicado. É nesse estágio que deve começar o teste das colaborações entre classes.
Como o teste das classes individuais, o teste de colaboração de classes pode ser conseguido aplicando-se os métodos aleatórios e de particionamento, bem como o teste baseado em cenário e teste comportamental.
            Veja abaixo técnicas relacionadas:


 TESTE DE VÁRIAS CLASSES 

-->
A abordagem para o teste de partição de várias classes é semelhante à abordagem usada para o teste de partição de classes individuais, sendo uma única classe particionada. A seqüência de teste são expandidas para incluir aquelas operações invocadas por meio de mensagens para as classes colaboradoras, onde uma abordagem alternativa particiona os testes com base nas interfaces de uma classe particular.


Segue abaixo uma seqüência de passos para gerar casos de teste aleatórios para várias classes:


Para cada classe cliente, use a lista de operações de classe para gerar uma série de seqüências de teste aleatório. As operações vão enviar mensagens para outras classes servidoras.


Para cada mensagem gerada, determine a classe colaboradora e a operação correspondente no objeto servidor.


Para cada operação no objeto servidor (que foi invocado por mensagens enviadas pelo objeto cliente), determine as mensagens que ele transmite.


Para cada uma das mensagens, determine o nível seguinte de operações que são invocadas e incorpore-as à seqüência de teste.

 
 TESTES DERIVADOS DOS MODELOS DE COMPORTAMENTO 

-->
O diagrama de estado de uma classe pode ser usado para ajudar a originar as seqüências de testes que vão exercitar o comportamento dinâmico da classe e daquelas classes que colaboram com ela.
Os testes a ser projetados devem cobrir todos os estados, ou seja, as seqüências de operações devem fazer a classe realizar transição entre todos os estados permitidos.
Em situações nas quais o comportamento da classe resulta em uma colaboração com uma ou mais classes, diagramas de estado múltiplos são usados para rastrear o fluxo de comportamento do sistema.
O modelo de estados pode ser percorrido em forma de “inclusão progressiva” neste contexto implica um caso de teste exercitar uma única transição e, quando uma nova transição tiver de ser testada, são usadas apenas aquelas previamente testadas.
 


TESTE DE AMBIENTES, ARQUITETURAS E APLICAÇÕES ESPECIALIZADAS 

-->
A seguir serão abordadas diretrizes para teste de ambientes, arquiteturas e aplicações especializadas comumente encontradas por engenheiros de software.
 


TESTE DE IGU


-->
Interfaces gráficas com o usuário (IGU) ou Graphical User Interfaces (GUI), mostra desafios interessantes para os engenheiros de software. O uso de componentes reusáveis como parte de ambientes de desenvolvimento IGU, a criação de interface com o usuário tornou-se menos demorada e precisa, mas ao mesmo tempo, a complexidade das IGU cresceu, levando a dificuldades no projeto e na execução de casos de teste.
Aqui grafos de modelagem de estados finitos podem ser usados para derivar uma série de testes que tratam de objetos de dados e programa específicos, relevantes para a IGU. Este tipo de teste deve ser conduzido usando-se ferramentas automatizadas.





TESTE DE ARQUITETURA CLIENTE/SERVIDOR


-->
Este tipo de teste é um desafio para os testadores de software. A natureza distribuída de ambientes cliente/servidor, os aspectos de desempenho, associados com processamento de transações, a presença potencial de várias plataformas de hardware diferentes, as complexidades de redes de comunicação, a necessidade de atender a muitos clientes por uma base de dados centralizada (ou distribuída) e os requisitos de coordenação impostos ao servidor são indicativos que torna difícil o teste de software do que em aplicações isoladas.
O teste cliente/servidor ocorre em três níveis:
Aplicações clientes individuais são testadas no modo “não conectado”, a operação do servidor e a rede subjacente não são consideradas;
O software cliente e as aplicações do servidor associadas são testadas em conjunto, mas as operações da rede não são explicitamente exercitadas;
A arquitetura completa cliente/servidor, incluindo operações e desempenho da rede, é testada.
As seguintes abordagens de teste são comumente encontradas para aplicações cliente/servidor:
Teste de função da aplicação – a aplicação é testada de modo isolado.
Teste de servidor – o desempenho do servidor (tempo de resposta global e vazão de dados (throughpu) é também considerado.
Teste de banco de dados – a precisão e a integridade dos dados armazenados pelo servidor são testadas. As transações são examinadas para garantir que os dados sejam armazenados, atualizados, recuperados e arquivados adequadamente.
Teste de transação – uma série de testes é criada para garantir que cada classe de transações seja processada de acordo com os requisitos. Podemos abordar aqui tempo de processamento e volume de transação.
Teste de comunicação em rede – verifica se a comunicação entre os nós da rede ocorre corretamente e se a passagem de mensagens, transações e tráfego de rede relacionado ocorre sem erro. Testes de segurança da rede podem também ser conduzidos como parte desses testes.


Recomenda-se o desenvolvimento de perfis operacionais derivados de cenários de uso cliente/servidor. Um perfil operacional indica como diferentes tipos de usuário interoperam com o sistema cliente/servidor, os perfis fornecem um “padrão de uso” que pode ser aplicado quando testes são projetados e executados.

TESTE DA DOCUMENTAÇÃO E DISPOSITIVOS DE AJUDA 

-->
Erros na documentação pode ser tão grave para a aceitação do programa quanto erros nos dados ou código-fonte. Nada é mais frustrante que seguir exatamente um guia do usuário ou um documento de ajuda on-line e obter resultados ou comportamentos que não coincidem com aqueles previstos pela documentação. Assim o teste de documentação deve ser uma parte significativa de todo o plano de teste de software.
Este teste pode ser abordado em duas fases: revisão e inspeção examina o documento quanto a clareza editorial e teste ao vivo usa a documentação em conjunto com o uso do programa real.
 


TESTE DE SISTEMAS DE TEMPO REAL 

-->
O motivo que nos leva a este tipo de teste é que em muitas situações, dados de testes fornecidos vão resultar em processamento adequado, quando um sistema de tempo real está em um estado, enquanto os mesmos dados fornecidos quando o sistema está em um estado diferente podem levar a erro.
          Além do mais teste de software devem considerar o impacto de falhas do hardware no processamento de software. Estas falhas podem ser extremamente difíceis de simular com realismo.
Segue abaixo uma estratégia de quatro passos:

Teste de tarefa – testa cada tarefa independente. Os testes convencionais são projetados e executados para cada tarefa, detectando assim erros de lógica e de função.

Teste comportamental – examina seu comportamento como conseqüência de eventos externos, com o uso de ferramentas automatizadas. Este tipo de teste pode servir de base para projetos de casos de teste usados após a construção do software.

Teste de inter-tarefas – tarefas assíncronas que se comunicam umas com as outras são testadas com diferentes taxas de dados e carga de processamento para detectar se erros de sincronização inter-tarefas vão ocorrer.
           Teste de sistema – descobrir erros na interface software/hardware. Com uso do diagrama de estados e a especificação de controle, o testador desenvolve uma lista de todas as possíveis interrupções e do processamento que ocorre em conseqüência das interrupções, projetando testes para avaliar as seguintes características do sistema:

- Se as prioridades de interrupção estão atribuídas adequadamente e propriamente manipuladas.

- O processamento para cada interrupção foi conduzido corretamente.

- Verificar o desempenho (tempo de processamento) de cada procedimento de manipulação de interrupção se está de acordo com os requisitos.

- Se um alto volume de interrupções chegando em tempos críticos cria problemas de função ou desempenho.

Áreas globais de dados, usadas para transferir informação no processamento de interrupções, devem ser testadas para avaliar o potencial de geração de efeitos colaterais.

Fechamos aqui os métodos que compreende a técnica de testes de caixa-preta, abordaremos a seguir os métodos aplicados nos testes caixa-branca.

TESTES CAIXA-BRANCA - CX de Vidro

-->
Baseado em um exame rigoroso do detalhe procedimental. Caminhos lógicos internos ao software e colaborações entre componentes são testados definindo-se casos de testes que exercitam conjuntos específicos de condições e/ou ciclos. A forma exaustiva de definir todos os caminhos lógicos, desenvolver casos de teste para exercitá-los e avaliar os resultados, não pode levar a descartá-lo, um número limitado de caminhos lógicos importantes podem ser selecionado e exercitado, estruturas de dados também podem ser submetidas à prova quanto à validade.
Conhecido também como teste caixa de vidro ou teste estrutural, nos casos de teste usa a estrutura de controle descrita como parte do projeto ao nível de componentes. Neste contexto derivam-se os seguintes casos de teste: Garantir que todos os caminhos independentes de um módulo tenham sido exercitados pelo menos uma vez, exercitar todas as decisões lógicas em seus lados verdadeiros e falsos, executam todos os ciclos nos seus limites e dentro de seus intervalos operacionais, exercitarem as estruturas de dados internas para garantir sua validade.
Segue abaixo técnicas de Teste de Caixa-Branca:
Os testes a seguir são considerados teste de Estrutura de Controle.

TESTE DE CAMINHO BÁSICO


-->
Este tipo de teste permite ao projetista de casos de testes originar uma medida da complexidade lógica de um projeto sentimental e usar essa medida como guia para definir um conjunto básico de caminhos de execução, estes executam com garantia cada comando do programa pelo menos uma vez durante o teste.


 NOTAÇÃO DE GRAFO DE FLUXO 

-->
Este grafo mostra o fluxo de controle lógico, cada circulo chamado de nó do grafo de fluxo representa um ou mais comandos procedimentais. As setas chamadas de arestas ou ligações representam o fluxo de controle e são análogas às setas de fluxograma. As áreas limitadas por arestas e nós são chamadas de regiões. Vale ressaltar que um grafo de fluxo deve ser desenhado somente quando a estrutura lógica de controle de um componente é complexa, permitindo seguir mais facilmente os caminhos do programa.
O nó que contém uma condição é chamado de nó predicado e é caracterizado por duas ou mais arestas saindo dele.
 

 CAMINHOS INDEPENDENTES DE PROGRAMA 

-->
É qualquer caminho ao longo do programa que introduz pelo menos um novo conjunto de comandos de processamento ou uma nova condição, este caminho deve pelo menos incluir uma aresta que não tenha sido atravessada antes do caminho ser definido. O mesmo é obtido mediante o grafo de fluxo.


Os caminhos constituem o conjunto-base, onde testes são projetados para forçar a execução desses caminhos, onde todo comando do programa terá sido executado pelo menos uma vez e cada condição executada no seu lado verdadeiro e falso.


Complexidade ciclomática – este cálculo mostra quantos caminhos deve-se procurar. É uma métrica de software que fornece uma medida quantitativa da complexidade lógica de um programa.

              A complexidade ciclomática tem sua fundamentação na teoria dos grafos e pode ser calculada de três maneiras:

1. O número de regiões corresponde a complexidade ciclomática;
2. A complexidade ciclomática V(G), para um grafo de fluxo G, é definida como:
V(G) = E – N + 2
E: número de arestas (E-edges)
N: número de nós (N-nodes)
3. Pode ser definida como:
V(G) = P + 1
P: número de nós predicados (P-Predicate nodes).

Esta métrica pode ser útil tanto para planejamento de teste quanto para projeto de casos de teste. Fornecendo o limite superior de número de casos de teste que precisam ser executados, para garantir que cada comando de um componente tenha sido executado pelo menos uma vez.
 

MÉTODO DE PROJETO DE CASOS DE TESTE

O método de teste do caminho básico pode ser aplicado a um projeto procedimental ou a um código fonte.

Os seguintes passos podem ser aplicados para originar o conjunto-base:

1. Usando o projeto ou código como base, desenhe o grafo de fluxo correspondente. Usando os símbolos e regras de construção apresentados na seção 7.2.1.2. A criação do grafo se dá enumerando os comandos PDL que serão mapeados nos nós correspondentes do grafo;

2. Determine a complexidade ciclomática do grafo de fluxo resultante. A complexidade pode ser determinada sem desenvolver um grafo de fluxo através da contagem de todos os comandos condicionais na PDL;

3. Determine um conjunto-base de caminhos linearmente independentes. Os nós predicados ajudam na definição de casos de teste.

4. Prepare casos de teste que vão forçar a execução de cada caminho de conjunto-base.

Cada caso de teste é executado e comparado aos resultados esperados, uma vez completados todos os casos, o testador pode ter certeza que todos os comandos do programa foram executados pelo menos uma vez.

É importante observar que alguns caminhos independentes não podem ser testados de um modo individual, nestes casos esses caminhos são testados como parte de outro teste de caminho.

MATRIZ DE GRAFO

Para originalizar o grafo de fluxo e determinar um conjunto de caminhos básicos através de mecanização através de uma ferramenta é usada uma estrutura de dados chamada matriz de grafo (é uma matriz quadrada onde o número de linhas e de colunas é igual ao número de nós do grafo de fluxo. Onde cada linha e coluna corresponde a um nó identificado, e as entradas na matriz correspondem as conexões (aresta) entre nós.

Adicionando um peso de ligação a cada entrada da matriz, esta pode tornar uma possante ferramenta para avaliar a estrutura de controle, fornecendo informação adicional sobre o fluxo de controle. Assim temos o peso de ligação 1 (existe uma conexão) ou 0 (não existe uma conexão), estes mesmos pesos podem ser atribuídos a outras propriedades mais interessantes como:

- A propriedade de uma aresta será executada.

- O tempo de processamento gasto durante o percurso de uma ligação.

- A memória necessária durante o percurso de uma ligação.

- Os recursos necessários durante o percurso de uma ligação.

E um rigoroso tratamento de outros algoritmos matemáticos que podem ser aplicados a matrizes. Com estas técnicas, a análise necessária para projetar casos de teste pode ser parcial ou totalmente automatizada.

Segue abaixo outras variações do teste da estrutura de controle, elas ampliam a cobertura de teste e melhora a qualidade de teste caixa-branca.



TESTE DE CONDIÇÃO
 
Este tipo de teste exercita as condições lógicas contidas em um módulo de programa, onde podemos ter uma:

Condição simples – uma variável booleana ou uma expressão relacional, possivelmente precedida por um operador Não.

Condição Composta – formada de duas ou mais condições simples, operadores booleanos e parênteses.

Uma condição sem expressões relacionais é referida como expressão booleana.

Dessa forma os tipos de elementos possíveis em uma condição booleana incluem um operador booleano (OU, E, NÃO), uma variável booleana, um par de parênteses (envolvendo uma condição simples ou composta), um operador operacional ou uma expressão aritmética.

Sendo que se uma condição está incorreta, pelo menos um componente da condição está incorreto. Assim os tipos de erros em uma condição se referem aos elementos citados anteriormente. Este tipo de teste focaliza o teste de cada condição do programa para garantir que não contém erros.
TESTE DE FLUXO DE DADOS

Este tipo de teste seleciona caminhos de teste e um programa de acordo com a localização das definições e dos usos das variáveis no programa, onde a cada comando de um programa é atribuído um número de comando único e que cada função não modifica seus parâmetros ou variáveis globais.

TESTE DE CICLO (LOOPS)



Ciclos considerados como pedra fundamental da grande maioria de todos algoritmos implementados em software, porém freqüentemente é dado a eles pouca atenção na fase de testes.

Este teste focaliza exclusivamente a validade de construções de ciclo, aqui quatro diferentes classes de ciclos: ciclos simples, concatenados, aninhados e desestruturados.

Ciclos simples – este conjunto de testes pode ser aplicado a ciclos simples em que n é o número máximo de passagens permitidas pelo ciclo.

Ciclos aninhados – neste caso o número de testes possíveis cresceria geometricamente, à medida que o nível de aninhamento crescesse, resultando em um número de testes impraticável. Existe uma abordagem que ajuda a reduzir este número de teste:

1. Comece no ciclo mais interno, ajustando todos os outros ciclos para os valores mínimos.

2. Conduza testes de ciclo simples para o ciclo mais interno enquanto mantém os ciclos externos nos seus valores mínimos do parâmetro de iteração (exemplo, contador de ciclo). Adicione outros testes para os valores fora do intervalo ou excluídos.

3. Trabalhe em direção ao exterior, conduzindo testes para o ciclo seguinte, mas mantendo todos os outros ciclos externos nos valores mínimos e os outros ciclos aninhados em valores “típicos”.

4. Continue até que todos os ciclos tenham sido testados.

Ciclos concatenados – estes podem ser testados usando a abordagem definida para ciclos simples, se cada um dos ciclos é independente do outro. Se dois ciclos são concatenados e o contador de ciclo, para o ciclo 1, é usado como valor inicial para o ciclo 2, então os ciclos não são independentes, dessa forma a abordagem aplicada a ciclos aninhados é recomendada.

Ciclos desestruturados – essa classe de ciclos deve ser reprojetada para refleti o uso de construções de programação estruturada.

Encerra aqui as técnicas referentes as Caixa-Branca.

Um comentário: