• Aucun résultat trouvé

O segundo estudo de caso com o EvolUniT teve como principal objetivo validar a geração automática de código proporcionada pela ferramenta, no sentido de medir o esforço poupado por um desenvolvedor de software. Para esta comparação, serão adotados 4 critérios: (1) a cobertura de decisões, como no estudo anterior, porque esta tem que ser pelo menos tão boa quanto a conseguida de forma manual; (2) o número de casos de teste (indivíduos no caso do EvolUnit) necessários para se atingir a cobertura máxima considerada; (3) o número de gerações necessárias para se atingir a cobertura máxima, pois esta medida é diretamente proporcional ao tempo gasto para se atingir essa cobertura; e (4) a diferença do número de linhas de código entre a abordagem manual e a automática, sendo essa a mais importante para medir o esforço poupado.

As avaliações com os critérios (1), (2) e (4) podem ser feitas de forma quantitativa. O critério de número de gerações será analisado de forma qualitativa, já que na abordagem manual não há necessidade de gerações. Esta será utilizada apenas para substituir o tempo gasto para chegar ao resultado almejado, já que este não é medido nos nossos estudos.

Para medir de forma coerente o esforço poupado pela ferramenta EvolUniT, foi selecionado um sistema desenvolvido por um grupo da Motorola do Brasil, utilizado para automação de seu processo de testes. O nome da ferramenta é TaRGeT, apresentada na próxima seção.

5.2.1 Ferramenta TaRGeT

A TaRGeT (Test and Requirements Generation Tool) se trata de uma ferramenta baseada em MBT (Model Based Testing) para geração automática de casos de teste a partir de casos de uso escritos em linguagem natural [Nogueira et., al, 2007]. MBT é uma abordagem que se baseia no modelo de uma aplicação sendo testada para realizar tarefas comuns a testes, como geração de casos de teste e validação de resultados de testes [Jorgensen, 1995].

A ferramenta utiliza uma estratégia que consiste na obtenção de um modelo comportamental LTS (Labeled Transitions Systems) formal a partir de casos de uso, e em um algoritmo de extração para a geração dos casos de teste. Um modelo LTS fornece uma descrição global e monolítica do conjunto de todos os possíveis comportamentos do sistema, onde um caminho nesse modelo pode ser tomado como uma seqüência de teste [Cartaxo et al., 2007].

Essa ferramenta foi desenvolvida pelo grupo de pesquisa do Brazil Test Center [Torres et., al, 2007], que consiste em uma parceria entre o Centro de Informática (CIn) da UFPE, o Departamento de Sistemas e Computação (DSC) da UFCG, e do Brazil Test

Center (BTC) da Motorola Industrial Ltda, com o objetivo de melhorar a qualidade de

software, além de reduzir os custos de processo de testes.

Conforme dito anteriormente, essa ferramenta foi escolhida para realização do estudo de caso com foco no esforço poupado. Os motivos que levaram a essa escolha vêem do fato de que a TaRGeT é uma aplicação industrial, de fato usada pelo BTC da Motorola. Além disso, o acesso a determinadas classes de seu código fonte foi possível. As informações sobre as classes selecionadas da TarGeT para a realização deste segundo estudo estão expostas na próxima seção.

5.2.2 Objetos de Teste

Para a comparação entre os casos de teste escritos manualmente, e dos gerados de forma automática pelo EvolUniT, foram selecionadas 6 classes da TarGeT para serem os objetos de teste. Essas classes foram escolhidas por serem básicas na ferramenta TarGeT, por trabalharem com tipos primitivos e objetos String, e por possuírem loops e fluxos

condicionais. O quadro 5.1 mostra as características relevantes sobre os 6 objetos de teste para o estudo de caso, que são: o nome da classe, qual o propósito na aplicação, o número de linhas de código (LOC) e o número de métodos públicos presentes. O código das classes não pôde ser exposto nesta dissertação por motivo de política de segurança da Motorola Industrial Ltda.

Quadro 5.1 Características das classes de teste.

Classe Descrição LOC Mét. Pub.

Feature Representa uma característica de um requisito 181 9 Flow Representa um fluxo de um caso de uso 179 9 FlowStep Representa um passo em um fluxo de caso de uso 115 7 PhoneDocument Representa um documento de caso de uso completo 166 10 StepId Representa um Id de um FlowStep 126 6 UseCase Representa um artefato de requisito de caso de uso 162 9

A próxima seção mostra os resultados atingidos pelos casos de teste escritos manualmente e os gerados automaticamente.

5.2.3 Geração dos Casos de Teste

Como dito anteriormente, os casos de teste do EvolUniT foram avaliados com ênfase apenas na capacidade do seu AG de atingir melhores coberturas que a forma aleatória. Agora o foco é avaliar se os casos de teste do EvolUniT podem substituir os escritos de forma manual por um desenvolvedor de software que participou da construção do sistema e detém conhecimento sobre o software. Para tanto, será observada tanto a cobertura de decisões atingida, quanto o número de linhas de código que o desenvolvedor teve que escrever, e o número de casos de teste e gerações do AG necessárias para se atingir a máxima cobertura conseguida. Vale lembrar que a geração de código do EvolUniT tem suas limitações quando se trata de tipos não primitivos, fazendo com que em determinados casos o usuário tenha que completar os casos de teste de forma manual.

A tabela 5.16 mostra os resultados obtidos a partir da escrita manual de classes de teste para as 6 classes do TarGeT. Essa tabela mostra respectivamente: o nome da classe de teste implementada; a cobertura de decisões máxima atingida pela classe de teste; o número

apenas nos corpos vazios dos métodos de teste, dos métodos setUp e tearDown e os Java

Annotations acima de cada método; e as linhas de código que foram inseridas manualmente

para que a cobertura máxima fosse atingida.

Tabela 5.16 - Resultados dos testes manuais nas classes do TarGeT.

Classe de Teste Cobertura(%) LOC Total LOC Ger. LOC Ins. Man.

FeatureTest 100 122 64 58 FlowTest 100 140 68 72 FlowStepTest 100 97 53 44 PhoneDocumentTest 100 127 68 59 StepIdTest 100 80 49 31 UseCaseTest 100 127 63 64

Os resultados das gerações e execuções automáticas das 6 classes escolhidas para serem testadas encontram-se na tabela 5.17, que mostra respectivamente: o nome da classe de teste gerada pelo EvolUniT; a máxima cobertura de decisões atingida, o número de gerações necessárias para atingir a cobertura máxima; o número de indivíduos que atingiram a cobertura máxima e o número de indivíduos total por geração; o número de linhas de código geradas automaticamente para a classe de teste; e o número de linhas de código que foram necessárias serem inseridas de forma manual, para completas a classe de teste.

Tabela 5.17 - Resultados dos testes automáticos nas classes do TarGeT.

Classe de Teste Cobertura(%) Nº Ger. Nº Ind. LOC Total LOC Ger. Aut. LOC Ins. Man. FeatureTest 100 1 3 / 5 204 198 6 FlowTest 100 1 5 / 5 213 205 8 FlowStepTest 100 1 5 / 5 149 147 2 PhoneDocumentTest 100 1 5 / 5 360 352 8 StepIdTest 100 3 2 / 5 197 197 0 UseCaseTest 100 1 5 / 5 228 218 10

Para todos os testes o tamanho dos indivíduos foi configurado para 4, o número de indivíduos para 5, a taxa de cruzamento para 70% e a taxa de mutação para 30%. As linhas que foram inseridas de forma manual correspondem a comandos necessários para o preenchimento dos parâmetros dos construtores das classes, quando estes possuem tipos

não primitivos e / ou coleções. Trata-se de uma seqüência de instanciações de outras classes e execuções de métodos necessários para deixar objetos no estado desejado, antes de chamar o método de teste. Essa seqüência é necessária em alguns casos desde que o EvolUniT ainda não gera automaticamente dados de tipo Objeto, nem os evolui, com exceção de Strings.

Após as elaborações e execuções dos testes, os resultados foram analisados para comparar o esforço das duas abordagens de teste, levando em consideração as linhas de código inseridas de forma manual. Para as duas abordagens não foram levados em consideração os test oracles, já que tanto na abordagem automática do EvolUniT quanto na manual, com a ajuda do wizard do JUnit, as asserções precisam ser inseridas manualmente para a avaliação dos métodos conforme os requisitos. Também não foi levado em consideração os esforços de configuração anteriores à geração dos testes. Levando isso em consideração, a tabela 5.18 foi elaborada com base nos resultados expostos nas seções anteriores. A tabela mostra o esforço, em termos de porcentagem de linhas de código inseridas manualmente em relação ao total, tanto das gerações automáticas quanto das escritas manuais dos casos de teste.

Tabela 5.18 - Resultados dos esforços manuais das duas abordagens de teste, em termos de

LOC.

Classe de Teste Esforço Teste Manual - LOC (%) Esforço Teste Automático -LOC (%)

FeatureTest 47,54 2,94 FlowTest 51,42 3,75 FlowStepTest 45,36 1,34 PhoneDocumentTest 46,45 2,22 StepIdTest 38,75 0 UseCaseTest 50,39 4,38

Pode-se observar que a diferença de esforço entre as duas abordagens é grande, mesmo com a utilização do wizard do JUnit que gera algumas vezes até metade das linhas de código. Para medir a diferença destes esforços em apenas um percentual, podemos fazer uma média aritmética entre os valores do teste manual e do teste automático, para as 6 classes consideradas. Isso nos dá uma média de esforço de 46,65 % de inserção manual de linhas de código na abordagem manual e uma média de 2,44 % de inserção manual na abordagem automática. Sendo assim, para este estudo de caso, foi calculada uma média de 44,21 pontos percentuais de esforço poupado quando se utiliza a ferramenta EvolUniT para

pelas duas abordagens. O pequeno esforço manual por parte da abordagem semi-automática exige também uma análise do código sendo testado (conhecimento do testador) para que os complementos resultem em 100% de cobertura.

Com relação ao número de gerações e o número de indivíduos necessários para os resultados automáticos, não houve nenhum caso em que o esforço gasto com a re- configuração dos parâmetros do AG compensou o esforço ganho com as linhas de código. Com exceção do teste da classe StepId, que precisou de 3 gerações para que algum indivíduo (no caso 2) chegasse a 100% de cobertura, todos os outros testes só precisaram de apenas 1 geração, e todos os testes utilizaram a configuração inicial.