Para utilizar o TRANSMUT-Spark, este tem que ser adicionado como um plugin em um projeto que utiliza o SBT. Após isso, é necessário criar um arquivo de con- figuração da ferramenta chamado transmut.conf na raiz do projeto. Esse arquivo de configurações deve conter os nomes de arquivo dos códigos fonte que possuem os programas que serão modificados (sources), e os nomes dos métodos que encapsulam os programas
(programs). Estabelecemos que um programa Spark que vai passar pelo processo de teste
de mutação com o TRANSMUT-Spark deve estar encapsulado em um método. Dessa forma, apenas os métodos indicados na configuração é que serão modificados no processo. Os nomes de arquivo dos códigos fonte e programas são as configurações mínimas para que a ferramenta execute o processo, mas também é possível inserir configurações adicionais, como indicar os operadores de mutação que serão aplicados (mutation-operators), que por padrão são todos, indicar quais classes de teste devem ser executadas (test-only), que por padrão são executadas todas disponíveis no projeto, e indicar se o módulo redutor de mutantes deve ser executado ou não (enable-reduction). Um exemplo de configuração
considerando o programa apresentado na Figura 7.3 pode ser visto na Figura 7.5.
1 transmut { 2 sources: [ "NasaApacheWebLogsAnalysis.scala" ], 3 programs: [ "unionLogsProblem" ], 4 mutation-operators: [ "STR" ], 5 test-only: [ "example.NasaApacheWebLogsAnalysisTest" ] 6 }
Figura 7.5 – Exemplo de arquivo de configuração do TRANSMUT-Spark. Além do programa Spark ter que estar encapsulado em um método, também estabelecemos que 1) todos os conjuntos de dados (RDDs) do programa devem possuir referências próprias (devem ser declarados como parâmetros de entrada, variáveis ou va- lores); 2) apenas uma operação Spark pode ser chamada por vez em uma declaração de código do programa; 3) todas as referências (parâmetros, variáveis e valores) devem possuir nomes únicos no código fonte; e 4) funções anônimas (lambda) devem ter seus pa- râmetros de entrada explicitamente tipados, apesar de Scala permitir tipagem implícita. As duas primeiras restrições estão relacionadas com a forma em que fazemos a análise do programa. Para aplicar nossos operadores de mutação, precisamos identificar os con- juntos de dados (RDDs) e transformações de um programa, assim como identificar como o seu fluxo de dados é definido. Essas restrições visam a facilitar a identificação desses elementos no programa. As duas últimas restrições foram impostas devido a limitações da biblioteca Scalameta que utilizamos para fazer a análise sintática e semântica do código. O programa apresentado na Figura 7.3 está seguindo o padrão de programas Spark que estabelecemos para o TRANSMUT-Spark.
Para executar o TRANSMUT-Spark, é necessário executar o comando sbt transmut de dentro da pasta do projeto no terminal de linhas de comando. Esse co- mando dispara a execução do processo de teste de mutação seguindo o fluxo de trabalho que foi apresentado na Figura 7.1. Quando a execução é finalizada, são gerados relató- rios com os resultados do processo. A ferramenta gera relatórios nos formatos HTML e JSON, além de exibir um relatório com um resumo dos resultados na interface de linhas de comando. Os relatórios gerados pelo TRANSMUT-Spark possuem todas as informações necessárias para a completa análise do processo do teste de mutação. As Figuras 7.6, 7.7, 7.8, 7.9 e 7.10 apresentam parte do relatório HTML gerado pelo TRANSMUT-Spark para o programa apresentado na Figura 7.3. Dentre as informa- ções que podem ser encontradas nesses relatórios, podemos ver métricas sobre o programa (Figura 7.6); uma representação gráfica do fluxo de dados formado pelo programa (Fi- gura 7.7); informações sobre os mutantes gerados (Figura 7.8); detalhes de um mutante, como seu status e códigos do programa original e mutante para fim de comparação (Fi- gura 7.9); e métricas gerais sobre os operadores de mutação (Figura 7.10).
Figura 7.6 – Parte do relatório HTML gerado pelo TRANSMUT-Spark com métricas sobre os programas.
Figura 7.7 – Parte do relatório HTML gerado pelo TRANSMUT-Spark com a repre- sentação gráfica do fluxo de dados do programa.
Figura 7.8 – Parte do relatório HTML gerado pelo TRANSMUT-Spark com informa- ções sobre os mutantes gerados.
Figura 7.9 – Parte do relatório HTML gerado pelo TRANSMUT-Spark com os detalhes e resultados de um mutante específico.
Figura 7.10 – Parte do relatório HTML gerado pelo TRANSMUT-Spark com métricas sobre os operadores de mutação.
Os relatórios gerados pelo TRANSMUT-Spark permitem que os mutantes so- breviventes sejam analisados para que se verifique se esses são equivalentes ou não. Isso permite que seja verificado se é necessário dar continuidade com o processo de teste de mutação para que o escore de mutação estabelecido seja atingido. Para dar suporte a todo esse processo, o TRANSMUT-Spark possui o comando transmutAlive que faz com que o processo seja executado novamente apenas para os mutantes sobreviventes da última execução. Esse comando permite que mutantes que foram identificados como equi- valentes sejam marcados no relatório. Isso é feito através da inserção dos identificadores dos mutantes equivalentes nas configurações da ferramenta no campo equivalent-mutants. Além disso, esse comando também permite que novos casos de teste sejam adicionados nas classes de teste e que apenas os mutantes sobreviventes sejam executados novamente. O comando transmutAlive também permite com que mutantes que tenham sido remo- vidos pelo módulo redutor (informação que também está presente nos relatórios quando for o caso) possam ser forçados a serem executados caso o usuário considere que algum dos mutantes removidos seja relevante e deva ser executado. Dessa forma, um novo rela- tório é gerado com as métricas e resultados atualizados. Mais detalhes sobre a utilização do TRANSMUT-Spark e suas configurações podem ser encontrados no repositório da ferramenta.
7.4
Discussões
O TRANSMUT-Spark é uma ferramenta que dá suporte ao teste de mutação de programas Spark e implementa os operadores de mutação de fluxo de dados e trans- formações que foram apresentados neste trabalho. As funcionalidades do TRANSMUT- Spark implementam os requisitos básicos que uma ferramenta para teste de mutação deve fornecer segundo (DELAMARO; MALDONADO, 1996). Para esses autores, uma ferramenta para teste de mutação deve 1) lidar com os casos de teste (test case handling), o que envolve a execução, inclusão e exclusão de casos de teste; 2) lidar com os mutantes
(mutant handling), que envolve a geração, seleção, execução e análise dos mutantes; e 3) fazer uma análise de adequação (adequacy analysis), o que envolve calcular o escore de mutação e gerar relatórios. Esses três requisitos são implementados no TRANSMUT- Spark, fazendo com que a ferramenta automatize as principais e mais laboriosas etapas do processo. Dessa forma, o TRANSMUT-Spark torna viável a completa execução do processo de teste de mutação em programas Spark.
A ferramenta possui algumas limitações em relação a alguns aspectos do geren- ciamento de casos de teste e mutantes. Com relação à manipulação dos casos de teste, a ferramenta opera no nível da classe de teste, que pode conter a implementação de um ou mais casos de teste. Dessa forma, a ferramenta permite que sejam definidas quais classes de teste devem ser executadas ou não no processo, mas não permite a seleção de casos de teste específicos dentro dessas classes. Com relação ao gerenciamento dos mutantes, a ferramenta permite a seleção dos mutantes no nível do operador de mutação, de forma que podem ser definidos quais operadores vão ser aplicados ou não no processo, mas não permite a seleção e execução de mutantes de forma individual. Essa limitação está re- lacionada com a forma em que o TRANSMUT-Spark executa o processo de teste de mutação, que é feito de forma única com todas as etapas sendo executadas de maneira sequencial, como detalhado na Figura 7.1. Dessa forma, não temos uma etapa interme- diária na execução da ferramenta, entre as etapas de geração e execução dos mutantes, para que possa ser feita a seleção dos mutantes que serão executados.
Apesar de não permitir uma seleção individual, a ferramenta oferece a possibili- dade de execução parcial dos mutantes após uma primeira execução da ferramenta. Essa funcionalidade permite que o processo seja re-executado apenas para os mutantes sobre- viventes da última execução, assim como permite que mutantes sejam marcados como equivalentes caso sejam identificados. Essa funcionalidade facilita a análise dos mutantes vivos porque não exige que todos os mutantes gerados sejam executados novamente. Além disso, essa funcionalidade também permite com que testes sejam adicionados de forma incremental ao processo, de modo que novos testes podem ser desenvolvidos para matar mutantes que não haviam sido mortos por testes anteriores, não exigindo que mutantes já mortos tenham que ser executados novamente. Isso reduz o tempo de execução do processo porque apenas os mutantes necessários são executados.
Uma outra limitação está relacionada com o formato do programa Spark su- portado pela ferramenta. Estabelecemos algumas restrições para o código do programa que são relacionadas com a forma em que analisamos o programa e com limitações da biblioteca que utilizamos para a análise do código. Essas restrições fazem com que pro- gramas Spark que não tenham sido desenvolvidos utilizando o padrão suportado pela ferramenta tenham que ser refatorados para que possam passar pelo processo de teste de mutação com o TRANSMUT-Spark. Apesar de ser uma restrição para a aplicação
da ferramenta, consideramos que o padrão suportado pelo TRANSMUT-Spark favo- rece a testabilidade de programas Spark. Isso ocorre porque facilita a controlabilidade, ao permitir que o programa possa ser executado de forma independente do contexto. Além disso, também favorece a observabilidade, permitindo que o comportamento do programa, assim como seus elementos (conjuntos de dados e transformações) possam facilmente ser analisados nos testes. Essas características são fundamentais para que testes possam ser automatizados (AMMANN; OFFUTT, 2017).
7.5
Considerações Finais
Este capítulo apresentou como contribuição o projeto e implementação do TRANSMUT-Spark, uma ferramenta que dá suporte ao processo de teste de mutação de programas Spark. Foram descritas as principais funcionalidades da ferramenta e seu fluxo de trabalho, detalhando como o processo de teste de mutação é executado pela fer- ramenta. Além disso, também apresentamos detalhes técnicos sobre o desenvolvimento da ferramenta, como sua arquitetura geral. Dessa forma, discutimos algumas escolhas de implementação e descrevemos como alguns aspectos importantes, como a geração do meta-mutante, foram implementados.
Descrevemos como o TRANSMUT-Spark pode ser utilizado para aplicar o teste de mutação em um programa Spark e apresentamos exemplos dos relatórios gerados, mostrando que os resultados da ferramenta possibilitam uma análise completa do processo. Por fim, discutimos aspectos em relação aos requisitos essenciais para ferramentas de teste de mutação que foram implementados pelo TRANSMUT-Spark e algumas de suas limitações. O desenvolvimento do TRANSMUT-Spark foi essencial para possibilitar a aplicação automática de todos os operadores de mutação que foram propostos neste trabalho. Isso faz com que a aplicação do teste de mutação em programas Spark se torne viável dado que todas as etapas laboriosas e propensas a erro do processo de teste de mutação são automatizadas pelo TRANSMUT-Spark.
8 Avaliando a Abordagem de Mutação de
Transformações para Programas Spark
Esse capítulo apresenta dois estudos de avaliação da abordagem de mutação de transformações para teste de programas Spark que foi apresentada neste trabalho. O objetivo geral é demonstrar a aplicabilidade e viabilidade da abordagem. O primeiro estudo teve como foco avaliar os operadores de mutação propostos no Capítulo 6 na aplicação do teste de mutação em programas Spark. Esse primeiro estudo foi realizado antes do desenvolvimento da ferramenta TRANSMUT-Spark, por isso o processo foi realizado de forma manual. O segundo estudo teve como foco avaliar a aplicabilidade e custos da aplicação do processo do teste de mutação de programas Spark com suporte da ferramenta TRANSMUT-Spark que foi apresentada no Capítulo 7, assim como comparar os resultados obtidos com a ferramenta com os resultados do primeiro estudo.
Este capítulo está organizado da seguinte forma: a Seção 8.1 apresenta os objeti- vos e metodologia aplicada nos dois estudos de avaliação; a Seção 8.2 apresenta a primeira avaliação da abordagem de mutação de transformações; a Seção 8.3 apresenta a segunda avaliação da abordagem e da ferramenta TRANSMUT-Spark, assim como discussões e comparações com o primeiro estudo; a Seção 8.4 discute algumas limitações e amea- ças à validade dos nossos experimentos de avaliação; por último, a Seção 8.5 apresenta considerações finais sobre os resultados das duas avaliações.