8º Congresso de Pós-Graduação ANÁLISE DE CUSTOS DO TESTE DE MUTANTES Autor(es) REGINA HELENA MORETTI Orientador(es) PLINIO ROBERTO SOUZA VILELA 1. Introdução O teste é uma das atividades que compõe o ciclo de desenvolvimento de software. Existem diversas maneiras de se executar esta atividade, mas independente de como ela é feita, seu principal objetivo é produzir evidências de que o programa que está sendo testado não está correto. Ao se atingir este objetivo (ou seja, quando defeitos são detectados), as atividades de identificação da origem do defeito e de sua correção são então iniciadas. Portanto, a atividade de teste está extremamente ligada à garantia da qualidade do software e é também uma atividade essencial no processo de desenvolvimento. Apesar de sua importância, o teste de software é geralmente uma atividade negligenciada devido à percepção de seu alto custo. Segundo (SOMMERVILLE, 2007), o custo desta atividade gira em torno de 40% do total do desenvolvimento. Com o avanço tecnológico, o custo computacional associado às diversas técnicas de testes vem constantemente caindo. Por outro lado, se destacam cada vez mais como fatores determinantes para o custo as atividades executadas manualmente, como a criação de casos de teste, que basicamente consiste em dados de entrada e determinar as saídas esperadas segundo a especificação do programa. Sistematizar sua aplicação e aumentar o entendimento de como seu custo é composto é essencial para promover a atividade de teste entre os praticantes do desenvolvimento de software. Um dos pontos fundamentais no custo do teste de software é definir se a quantidade de testes executados foi suficiente. Testes em excesso podem custar caro, testes a menos podem custar mais ainda. O critério de teste tem sido tradicionalmente utilizado como um importante ponto de apoio para a decisão de quando podemos parar. O critério provê uma medida da cobertura dos testes feitos, influenciando, portanto, esta decisão. A análise de mutantes é um critério que mede a eficácia de um conjunto de casos de teste. Esta técnica foi originalmente proposta por (DEMILLO; LIPTON; SAYWARD, 1978) e desde então vem sendo intensamente estudada. A idéia básica do processo de teste de mutantes, graficamente representado na figura 1, é que após submeter um programa P a um determinado conjunto de casos de testes T e efetuar as correções necessárias para remover os defeitos encontrados, é determinada uma medida que indica o quão adequadamente os dados de teste testaram P. Para determinar esta medida, chamada de escore de mutação, são gerados mutações do programa original P, através da introdução de uma única variação sintática. Para cada variação sintática, existe uma chance de que uma variação semântica seja produzida. Estas modificações sintáticas são inseridas no programa original através da aplicação de um conjunto de regras chamadas de operadores de mutação. Em geral, os operadores de mutação são dependentes da linguagem de programação utilizada, mas costumam variar entre 50 e 80 operadores. A aplicação por completo do conjunto de operadores em um programa pode levar a criação de um número substancialmente grande de mutantes. Um conjunto de dados de testes capaz de diferenciar um grande um grande número de mutantes é considerada adequada para testar P. Para diferenciar o programa original e um mutante, ambos são submetidos ao mesmo conjunto de dados de entrada. Se os resultados diferem, o mutante é marcado como morto; e a confiança nos dados de teste aumenta. Caso o resultado seja o mesmo, então podemos chegar a duas situações: ou o mutante é funcionalmente equivalente ao programa original e sempre irá produzir a mesma saída ou o mutante pode ser eliminado, mas o conjunto de testes utilizados não foi suficiente para fazê-lo (OFFUTT, 1995). Neste caso, o mutante é dito vivo. A pontuação de mutação MS é dada pela seguinte fórmula (DEMILLO; OFFUTT, 1993): MS(P,T) = K / (M – E) (1) onde K é o número de mutantes eliminados, E é o número de mutantes equivalentes e M é o total de mutantes gerados. Toda vez que chegamos a uma pontuação de mutação não suficiente, então novos casos de testes são acrescentados ao conjunto original, e todo o processo é refeito, aumentando a qualidade dos casos de testes e da atividade de testes como um todo. A técnica de teste de mutantes se baseia em duas hipóteses fundamentais (DEMILLO; LIPTON; SAYWARD, 1978): 1) Teoria do Programador Competente: considerando-se que os programadores são competentes, a tendência é que sejam produzidos programas muito próximos ao programa correto. 2) Efeito de Acoplamento: dados de teste capazes de distinguir todas as possíveis variações de um programa (geradas através da introdução de defeitos simples) . 2. Objetivos O entendimento de como o custo do teste de software é composto é essencial para que se possam identificar as atividades onde economias podem ser feitas. O objetivo deste trabalho é apresentar um modelo de custo para o teste de software e aplicá-lo qualitativamente na análise da técnica de teste de mutantes. 3. Desenvolvimento Modelo de Custo de Testes A equação apresentada abaixo (baseada no modelo de custo para técnicas de testes de regressão de (MALISHEVSKY; ROTHERMEL; ELBAUM, 2002)) representa os custos de testes de um dado programa P: C = Ca(T) + Ce(T) + Cc(T) (2) onde: C é o custo total do teste de software; T é o conjunto de teste; Ca é o custo de análise (geração) dos casos de teste. Ce é o custo de execução; Cc é o custo de checagem de resultados. O componente de custo de análise Ca pode ainda ser subdivido em duas partes, uma representando o custo de geração dos dados de entrada para o teste (Cag) e outra representando o custo para determinar os resultados esperados (Car). Desta forma, podemos reescrever a equação (2): C = Cag(T) + Car(T) + Ce(T) + Cc(T) (3) Aplicação do Modelo de Custos de Testes à Análise de Mutantes O primeiro componente do custo é o custo de análise Ca(T). Esta é uma atividade crucial para o teste de software como um todo e engloba dois passos bem específicos: a) geração dos dados de entrada para os testes e b) determinação dos resultados esperados. No caso do processo de testes de mutantes, o conjunto de testes T é gerado manualmente, portanto, o custo Cag(T) está ligado ao tempo que o analista de testes leva para a geração dos dados. É um componente caro na equação, por se tratar de atividade manual. O componente Car(T), relacionado à determinação de resultados, é composto por uma atividade manual, e é diretamente proporcional ao tamanho do conjunto de dados de entrada para o teste. Este componente do custo, portanto, também é um dos mais caros da equação, e se tratar de uma atividade que não pode ser automatizada e requer a existência de um oráculo humano, capaz de determinar o resultado esperado. No teste de mutantes, o custo de execução ds testes Ce é composto a partir das atividades de execução dos casos de testes T sobre o programa P (chamaremos este componente de Cep) e de execução dos casos de testes T sobre o conjunto M de mutantes de P (Cem). Portanto, esse componente está ligado a tempo computacional. Com o avanço tecnológico e o aumento da capacidade de processamento das máquinas, este componente se tornará cada vez mais irrelevante no custo total de teste. Já o terceiro termo da equação, Cc é composto pelos custos ligados à verificação dos resultados da execução dos casos de testes T sobre o programa P (Ccp) e sobre o conjunto M de mutantes de P (Ccm). Além disso, consideram-se também os custos de validação dos mutantes que se mantiveram vivos, para se verificar se eles são funcionalmente equivalentes ao programa original, ou seja, se eles sempre produzirão os mesmos resultados independentemente da entrada a que foram submetidos (Cce). A atividade de checagem dos resultados pode ser parcialmente automatizada; a única parte desta atividade que ainda precisa ser executada manualmente é a validação dos mutantes equivalentes. 4. Resultado e Discussão Substituindo os termos acima na equação original (2), chegamos a: C = Cag(T) + Car(T) + Cep(T) + Cem(T) + Ccp(T) + Ccm(T) + Cce(T) (4) Diversos estudos foram conduzidos com a intenção de reduzir os custos das tarefas automatizadas presentes no teste de mutantes. (Jia; Harman, 2009) classificam as técnicas resultantes destes estudos em: a) Redução do número total de mutantes gerados: o principal objetivo deste conjunto de técnicas é reduzir o tempo total gasto na execução e verificação dos resultados dos mutantes através da redução do número de mutantes gerados. b) Redução do custo de execução: este conjunto de técnicas otimiza o processo de execução dos mutantes com os dados de entrada para os testes. Considerando isto e o fato de que o custo computacional é relativamente baixo quando comparado ao custo humano, podemos reduzir a equação (4) a: C = Cag(T) + Car(T) + Cce(T) (5) Portanto, os principais ganhos de custo que podem ser obtidos, quando analisamos a técnica de análise de mutantes, estão naquelas atividades onde o componente humano ainda é o principal fator: geração dos dados de entrada para os testes, determinação dos resultados esperados e identificação dos mutantes equivalentes. Esta última atividade é menos custosa que as duas primeiras, pois apenas uma parcela pequena dos mutantes se mantém viva ao final de uma bateria de testes. 5. Considerações Finais A principal contribuição deste trabalho está na aplicação de um modelo de custo à técnica de testes de mutantes; a partir desta análise se pode concluir que, considerando-se o custo computacional como um custo quase irrelevante quando comparado ao custo humano, as principais atividades passíveis de ganho econômico são a geração de dados de entrada para os testes e a determinação dos resultados esperados. A utilização de geração automática de dados de teste juntamente com a técnica de mutantes pode ser um caminho promissor, desde que se garanta a eficácia dos dados de teste gerados e que o tamanho do conjunto seja suficientemente pequeno, a ponto de não aumentar o custo das demais atividades diretamente dependentes do tamanho deste conjunto. Referências Bibliográficas DEMILLO, Richard; LIPTON, Richard; SAYWARD, Frederick. Hints on Test Data Selection: Help for the Practicing Programmer. Computer, v. 11, n. 4, p. 34–41., abril 1978. DEMILLO, Richard; OFFUTT, A. Jefferson. Experimental Results From an Automatic Test Case Generator. ACM Transactions on Software Engineering and Methodology, v. 2, n. 2, p. 109–127., abril 1993 MALISHEVSKY, Alexey; ROTHERMEL, Gregg; ELBAUM, Sebastian. Modeling the Cost-Benefits Tradeoffs for Regression Testing Techniques. Proceedings of the 18th International Conference on Software Maintenance, p. 204-213., 2002 JIA, Yue; HARMAN, Mark. An Analysis and Survey of the Development of Mutation Testing. CREST King’s College London, Technical Report TR-09-06, 2009 OFFUTT, A. Jefferson. A Practical System for Mutation Testing: Help for the Common Programmer. Proceedings of the IEEE International Test Conference, p. 824-830, 1995 SOMMERVILLE, Ian. Software Engineering. 8ª edição. São Paulo: Addison Wesley, 2007 Anexos