4. Capítulo 4 – A Diversidade Como uma Técnica de Teste de Software
4.2. A Diversidade no Teste de Software
4.2.1. Uma Visão Intuitiva da Diversidade
Quando uma tarefa de projetar casos de teste é alocada a um(a) analista de teste, é esperado que ele(a) crie um conjunto de casos de teste (e procedimentos de execução desses casos de teste) que sejam abrangentes e representativos do conjunto de funcionalidades do software. Espera-se que a execução deste conjunto de casos de teste permita revelar defeitos associados às diferentes funcionalidades e também ganhar confiança de que o software satisfaz os seus requisitos.
Naturalmente, pode haver a necessidade de um teste mais restrito, abordando apenas um subconjunto das funcionalidades do software ou alguma característica específica. Caso
121
haja algum motivo para focar a atenção em certa funcionalidade do software, ou em certa parte específica do código, este objetivo deve ser explicitado nas fases de planejamento do teste e de projeto do teste. Isto ocorre, por exemplo, quando o objetivo é avaliar unicamente uma parte do código que sofreu mudanças recentes, ou quando se deseja avaliar se certas características desejáveis estão presentes ou não no software (requisitos não funcionais, tais como: nível de desempenho, segurança, capacidade de carga, facilidade de uso, etc.).
No entanto, na maior parte dos casos, há a necessidade de se testar o software de uma maneira abrangente. Informações sobre o software 6 devem ser consideradas para a criação de um conjunto de casos de teste que exercitem o software tão completamente quanto possível, considerando as limitações dos recursos disponíveis. Neste contexto, recursos dizem respeito ao tempo e ao esforço necessários para definir os dados de teste e os respectivos resultados esperados (os casos de teste); executar esses casos de teste no software sob teste; e avaliar as saídas produzidas.
Uma premissa fundamental para a estratégia de criar casos de teste com alta variedade – ou diversidade – é que não se saiba a priori com grande confiança qual parte do software (em termos de funcionalidades, ou de módulos de código fonte) possui defeitos associados. Caso esta informação sobre a localização de defeitos esteja disponível, devem ser realizados testes específicos, restritos às funcionalidades associadas aos defeitos (ou restrito a módulos do código fonte propensos a tê-los) visando revelá-los e removê-los do código. Neste caso, pode-se também realizar a inspeção do código fonte para a identificação e a correção do defeito. É importante destacar que, na prática, raramente se sabe com segurança onde estão os defeitos do software; portanto, a premissa anterior é bastante realista e pouco restritiva.
Como uma ilustração, vamos considerar a situação levantada no início desta seção: alocar aos analistas de teste a tarefa de definir conjuntos de casos de teste para um software. Vamos supor ainda que se trata de um software de apoio ao funcionamento de bibliotecas, com funcionalidades para o cadastro do acervo; o cadastro de funcionários da biblioteca; o
6 Informações podem ser relacionadas aos requisitos do software, a modelos construídos ao longo do
122
cadastro de usuários da biblioteca; e o registro de empréstimos, devoluções e reservas. Cada uma dessas funcionalidades naturalmente possui uma série de detalhamentos sobre informações a serem fornecidas, variações de comandos a serem acionados, e o comportamento esperado do sistema em cada situação. Um(a) analista de teste “A”, ao se confrontar com esta tarefa, gastou o tempo disponível para criar um conjunto de 100 casos de teste que avaliem minuciosamente a funcionalidade de empréstimos de livros, incluindo casos de teste para: realizar diversos empréstimos de livros diferentes; empréstimos de diferentes exemplares de um mesmo livro; empréstimos para vários diferentes usuários com pendências, etc. Um(a) analista de teste “B” gastou o tempo disponível para criar também 100 casos de teste; mas “B” distribuiu os casos de teste nos vários módulos, exercitando os aspectos principais de cada um dos módulos. Os casos de teste de “B” envolvem a inclusão e consulta de um funcionário, inclusão e consulta de livros e periódicos, cadastro de usuários, e operações de reserva, empréstimo e devolução de itens.
A situação descrita no parágrafo anterior busca ilustrar, de maneira informal, uma intuição relacionada às atividades de teste: considerando que o objetivo do teste seja avaliar o software de uma maneira global, a variabilidade/diversidade dos casos de teste utilizados é um aspecto importante a ser considerado para a seleção ou avaliação de um conjunto de dados de teste. Ao se adotar uma estratégia “conservadora” e precavida, não é adequado selecionar vários dados de teste muito semelhantes entre si; estes dados exercitam bem uma pequena parte do software, deixando as partes restantes pobremente exercitadas e mal testadas. Este foi o comportamento do (a) analista “A”, que criou um conjunto com vários casos de teste semelhantes e exercitou cuidadosamente a funcionalidade de empréstimos de livros. Se “A” fez um “bom trabalho” no projeto desses casos de teste, provavelmente esta funcionalidade foi bem exercitada, embora isto não seja garantido. Por exemplo, “A” poderia, com o objetivo de terminar rápido o trabalho, criar 100 casos de teste praticamente idênticos, todos realizando um empréstimo de algum livro disponível para algum usuário sem pendências. Neste último caso, mesmo esta única funcionalidade considerada no teste teria sido mal testada, devido à pouca variedade dos dados de teste utilizados. Obviamente, como as outras funcionalidades do software não foram testadas (além da funcionalidade
123
“empréstimos de livros”), os defeitos nelas existentes, mesmo que “grosseiros” 7, não têm como ser descobertos.
Ainda sobre esta situação ilustrada, o analista “B” utilizou os recursos de teste para exercitar cada um dos módulos, e teve chance de encontrar defeitos em todos os módulos. No entanto, como os casos de teste foram distribuídos entre estes módulos, é possível que nenhum deles tenha sido exercitado de forma severa o suficiente e, portanto, alguns defeitos podem não ter sido descobertos.
O que se buscou ilustrar no exemplo anterior é que a qualidade de um teste realizado pode ser avaliada (ou presumida) por meio da análise conjunta de dois fatores:
• O número de casos de teste utilizados;
• A diversidade – ou variedade – dos casos de teste utilizados.
O primeiro fator (número de casos de teste) pode ser entendido por meio do seguinte raciocínio: se o software possui defeitos, existe uma chance maior do que zero de que o software falhe ao ser executado com um caso de teste. Portanto, cada novo caso de teste contribui para aumentar a chance de que o software em teste falhe; quanto maior o número de casos de teste, maior será a chance de ocorrerem falhas.
O segundo fator (diversidade dos casos de teste), por sua vez, pode ser compreendido a partir da seguinte ideia: se não há certezas sobre a ausência de defeitos em alguma parte do software, deve-se distribuir os casos de teste de forma a exercitar todas as funcionalidades (ou módulos) que estão no escopo do teste. Neste ponto, identifica-se uma relação entre estes dois fatores: para que um teste abrangente (de alta diversidade) exercite satisfatoriamente o software, é necessário que o número de casos de teste seja adequado (ou grande o suficiente) para assegurar um bom teste 8.
7 O termo “grosseiros” visa caracterizar esses defeitos como sendo relativamente fáceis de serem descobertos;
por exemplo, por estarem associados a funções do software muito utilizadas, ou ainda por estarem associados a uma grande porção do domínio de entrada – o conceito de defeitos semanticamente grandes.
8 Neste contexto, não vamos nos estender na discussão de como encontrar um tamanho adequado para o
conjunto de teste. Embora este seja um ponto importante associado a técnicas de teste – quando se deve parar de testar –, não é o foco deste trabalho.
124
Importante notar também que esses dois fatores, relativos aos dados de teste, devem ser considerados levando-se em conta o objeto do teste. A complexidade do software em teste, avaliada do ponto de vista dos requisitos ou do ponto de vista do código fonte, em última análise, determina o número de casos de teste e o nível de diversidade recomendados.
Profissionais de teste de software geralmente usam as suas experiências anteriores e a intuição para identificar um grande número de variações de situações a serem avaliadas no teste. Esta é uma diretriz utilizada informalmente e que encontra respaldo em registros de “melhores práticas”. Conceitos relacionados à diversidade/variação estão subjacentes em algumas técnicas de teste e também em áreas como confiabilidade de software e tolerância a defeitos.
Exemplos de ideias relacionadas à importância da variação/diversidade no teste: • Uma das 28 melhores práticas que contribuem para a qualidade do teste de software,
em um relatório da IBM, aborda a criação dos casos de teste: “Criar diferentes variações de testes para cobrir o espaço de estados do programa tanto quanto seja necessário” e “Compreender como criar variações de dados de teste e alcançar uma cobertura que seja adequada o suficiente para testar de forma completa uma função” (Chillarege, 1999).
• O Teste Exploratório é caracterizado pelo “simultâneo aprendizado, projeto e execução”. Isto é, o testador realiza o projeto dos testes e, à medida que esses testes são executados, a informação obtida é usada para projetar novos testes e testes melhores (Bach, 2003), (Bach, 2005). Segundo Kaner et al (2001), o teste exploratório se caracteriza por: interatividade, concorrência de cognição e execução; e orientação a resultados rápidos. Uma ideia essencial é a confiança na “habilidade dos testadores de usar heurísticas e experiências prévias para criar ideias diversas para o teste” (Kaner et al., 2001).
• O “paradoxo do pesticida” descrito por Beizer (1990): “todo método usado para prevenir ou encontrar defeitos deixa um resíduo de defeitos sutis para os quais esses
125
métodos são ineficazes”. Essa afirmação faz menção à possibilidade de uma fração da população de insetos desenvolver tolerância ao pesticida específico, fazendo com que ele seja ineficaz se usado repetidamente nesta população.
A analogia é que, ao longo do teste, o software pode tornar-se “imune” aos testes realizados, de forma análoga à imunidade adquirida pelos insetos ao pesticida. O paradoxo do pesticida é frequentemente associado à ideia de que as técnicas de teste tendem a revelar defeitos de determinados tipos e que, portanto, a utilização de diferentes técnicas no teste de um software tende a aumentar o número de defeitos revelados. Utilizar diferentes técnicas de teste para revelar mais defeitos seria equivalente a utilizar diferentes pesticidas para matar mais insetos.
Uma maior diversidade existente nos insetos da população tende a propiciar uma maior chance de que alguns insetos resistam ao pesticida. Do ponto de vista do fazendeiro, a informação útil é que variar o pesticida usado tende a melhorar a eficácia no extermínio dos insetos, visto que o novo pesticida pode atuar nos insetos que toleraram o pesticida anterior. Analogamente, do ponto de vista do teste, a informação útil é que assegurar uma alta variação/diversidade dos novos cenários de teste, em relação aos cenários testados anteriormente, tende a aumentar a chance de revelar novos defeitos no software, “imunes” aos testes anteriores.
• Na mesma linha da ideia anterior de Beizer, mas de maneira formal, Littlewood et al (2000) modelam o efeito de combinar técnicas de teste diversas. Adotar uma segunda (ou terceira) técnica para selecionar casos de teste é uma maneira bem conhecida de introduzir esta variação/diversidade no teste. Littlewood et al mostram que, quando se utilizam conjuntamente várias técnicas diferentes, a eficácia do teste depende da interação de dois aspectos: a eficácia individual de cada técnica; e a dependência entre as técnicas. Por meio de medidas de eficácia para revelar defeitos e de diversidade de técnicas, os autores identificaram que o efeito de aplicar repetidamente técnicas similares não aumenta significativamente a eficácia do teste. Ao contrário, combinar técnicas de teste diversas tende a ampliar
126
significativamente esta eficácia. A conclusão é de que aplicar conjuntamente técnicas de teste diversas é uma boa prática, a ser utilizada sempre que possível.