Diretriz: Idéias de Teste para Diagramas de Estados e Fluxogramas
As idéias de teste são baseadas em defeitos de software plausíveis e em como esses defeitos podem ser melhor resolvidos. Essa diretriz mostra como identificar idéias de teste a partir de diagramas de estado e outras estruturas de design, como gráficos.
Relacionamentos
Elementos Relacionados
Descrição Principal

Introdução

Esta diretriz mostra como identificar idéias de teste a partir de diagramas de estados e outras estruturas de design que consistem principalmente de nós conectados por arcos e que mostram parte dos possíveis fluxos de controle de um programa. A principal meta desse teste é percorrer todos os arcos em algum teste. Caso nunca tenha testado um arco, por que você acha que ele funcionará quando um cliente fizer isso?

Teste e Implementação

Considere este diagrama de estados:

Diagrama descrito na legenda.

Fig1: Diagrama de Estados HVAC

A seguir está uma primeira lista de idéias de teste:

  • O estado Ocioso recebe o evento Muito Quente
  • O estado Ocioso recebe o evento Muito Frio
  • O subestado Inicialização do estado Refrigeração recebe o evento Compressor Funcionando
  • O subestado Pronto do estado Refrigeração recebe o evento Ventilador Funcionando
  • O subestado Funcionando do estado Refrigeração recebe o evento OK
  • O subestado Funcionando do estado Refrigeração recebe o evento Falha
  • O estado Falha recebe o evento Falha Solucionada
  • O estado Calefação recebe o evento OK
  • O estado Calefação recebe o evento Falha

Todas essas idéias de teste poderão ser experimentadas em um único teste ou você poderá criar vários testes para que cada um experimente algumas dessas idéias. Assim como no design do teste, procure um equilíbrio entre a facilidade de implementação de várias tarefas simples e a capacidade adicional de localizar defeitos proporcionada por testes complexos. (Consulte "design de teste utilizando a lista" na página Conceito: Lista de Idéias de Teste.) Se houver cenários de caso de uso que descrevam determinados caminhos pelo diagrama de estados, dê preferência a testes que sigam esses caminhos.

Qualquer que seja a situação, os testes devem certificar-se de que todas as ações exigidas pelo diagrama de estados ocorram realmente. Por exemplo, o alarme é iniciado quando o dispositivo entra no estado Falha e pára quando ele sai desse estado?

O teste também deve verificar se a transição leva ao próximo estado correto. Esse poderá ser um problema difícil quando os estados forem invisíveis do exterior. A única maneira de detectar um estado incorreto é injetar alguma seqüência de eventos que resultem em uma saída incorreta. Mais precisamente, seria necessário construir uma seqüência de eventos de acompanhamento cujos resultados externamente visíveis para o estado correto diferem daqueles que seriam provocados pela mesma seqüência em cada possível estado incorreto.

No exemplo acima, como saber se o evento Falha Solucionada no estado Falha levou corretamente ao estado Ocioso, em vez de permanecer no estado Falha? Você poderia confiar no fato de que a interrupção do Alarme significa que a transição foi feita, mas talvez seja melhor verificar diminuindo a temperatura o suficiente para acionar o aquecedor ou aumentando-a o suficiente para ativar a refrigeração. Se algo acontecer, você ficará mais seguro de que a transição foi realizada de forma correta. Se nada acontecer, é provável que o dispositivo tenha permanecido no estado Falha.

De qualquer forma, determinar se o estado resultante está correto complica o design do teste. Geralmente, é mais conveniente explicitar a máquina de estado e tornar seus estados visíveis para os testes.

Outras Construções de Gráfico de Estado

Os diagramas de estados não incluem apenas arcos e setas. A seguir está uma lista dos elementos dos diagramas de estados e o respectivo efeito na lista de idéias de teste.

Ações de evento, de entrada e de saída

Essas não geram idéias de teste por si só. Em vez disso, os testes devem verificar se as ações apresentam o comportamento especificado. Se as ações representarem programas substanciais, esses programas deverão ser testados. As idéias de teste para os programas podem ser combinadas com as do diagrama de estados, mas provavelmente é mais fácil gerenciá-las separadamente. Tome a decisão com base no esforço envolvido e na suspeita de que talvez haja interações entre os eventos. Ou seja, se uma ação específica em um arco não puder compartilhar dados com uma ação em outro arco, não haverá motivo para experimentar as duas ações no mesmo teste (como você faria se elas fizessem parte do mesmo caminho em um teste do diagrama de estados).

Condições de Proteção

Condições de guarda são boolean expressions. As idéias de teste para condições de guarda são derivadas como descrito em Diretriz do Produto de Trabalho: Idéias de Teste para Booleanos e Limites.

No exemplo anterior, a transição Muito Frio do estado Inativo é guardada com [tempo de reinício >= 5 min]. Isso resulta em duas idéias de teste separadas:

  • O estado Ocioso recebe o evento Muito Frio quando o tempo de reinício é de 5 minutos (transição feita)
  • O estado Ocioso recebe o evento Muito Frio quando o tempo de reinício é um pouco menor que 5 minutos (transição bloqueada)

Nos dois casos, qualquer teste que use a idéia de teste deverá verificar se o estado correto é atingido.

Transições internas

Uma transição interna adiciona a uma lista de idéias de teste o mesmo tipo de idéias que uma transição externa adiciona. Simplesmente o estado seguinte é igual ao estado original. Convém configurar um teste de forma que as ações de entrada e de saída do estado ocasionem um efeito observável se forem acionadas incorretamente.

Estados aninhados

Ao criar testes, configure-os de modo que os eventos de entrada e de saída do estado composto tenham efeitos observáveis. Convém reparar se eles foram ignorados.

Subestados simultâneos

O teste de simultaneidade foge ao escopo dos testes do desenvolvedor.

Eventos adiados

Se suspeitar que um evento poderá ser manipulado de forma diferente, dependendo de onde ele for adiado e enfileirado em vez de gerado enquanto o programa estiver efetivamente no estado de recebimento, você poderá testar esses dois casos.

Se o evento no estado de recebimento tiver uma condição de guarda, considere as ramificações de mudanças nas variáveis da condição entre a hora em que o evento foi gerado e a hora em que foi recebido.

Se mais de um estado puder manipular um evento adiado, considere a possibilidade de testar o adiamento para cada um dos possíveis estados de recebimento. Talvez a implementação considere que o estado "óbvio" manipulará o evento.

Estados do Histórico

A seguir está um exemplo de um estado de histórico:

Diagrama descrito na legenda.

Fig2: Exemplo de Estado de Histórico

A transição para o estado de histórico representa três transições reais e, portanto, três idéias de teste:

  • O evento BackUp no estado Comando leva ao estado Coletando
  • O evento BackUp no estado Comando leva ao estado Copiando
  • O evento BackUp no estado Comando leva ao estado Limpando
Estados de Cadeia

Os estados de cadeia não parecem ter qualquer implicação no design de teste, porém introduzem mais ações que precisam ser verificadas.

Testando o Design

A abordagem anterior concentra-se em verificar se a implementação corresponde ao design. Mas o design também pode estar incorreto. Ao examinar o design para localizar idéias de teste, verifique também a existência de dois tipos de problemas:

Eventos ausentes. O diagrama de estados mostra a resposta de um estado a eventos que o designer previu que poderiam chegar a esse estado. Não é raro os designers ignorarem eventos. Por exemplo, neste diagrama de estados (repetido do início da página), talvez o designer tenha se esquecido de que poderá ocorrer uma falha no subestado Pronto da Refrigeração, e não apenas quando o ventilador estiver Funcionando.

Diagrama descrito na legenda.

Fig3: Diagrama de Estado HVAC

Por esse motivo, convém perguntar, para cada estado, se qualquer um dos eventos que se aplicam a outros estados poderá se aplicar a este. Se descobrir que um deles pode, corrija o design.

Condições de guarda incompletas ou ausentes. De modo semelhante, talvez as condições de guarda em uma transição sugiram condições de guarda em outras. Por exemplo, o diagrama de estados acima procura não reiniciar o aquecedor com muita freqüência, mas não há esse tipo de restrição no sistema de refrigeração. Será que deveria haver?

Também é possível que as variáveis usadas em uma condição de guarda sugiram que outras condições de guarda sejam muito simples.

Testando Interações

Testar todos os arcos de um gráfico não significa de forma alguma que o teste está completo. Por exemplo, suponha que o estado de início inicialize uma variável como 0, o estado Definidor a defina como 5 e o estado Divisor a divida por 100 (100/variável). Se houver um caminho do estado de início para o Divisor que não passe pelo Definidor, haverá uma exceção de divisão por zero. Se o diagrama de estados tiver vários estados, o simples teste de cada arco poderá ignorar esse caminho.

É inviável testar todos os caminhos, exceto os diagramas de estados muito simples. Na prática, os testes complexos e que correspondem a cenários de caso de uso geralmente são suficientes. Se desejar testes mais potentes, considere a possibilidade de exigir um caminho de cada estado em que um dado recebe um valor para cada estado que o utiliza.