8
Functional Validation Driven by Automated Tests Validação Funcional Dirigida por Testes Automatizados Thiago Delgado Pinto Departamento de Informática Centro Federal de Educação Tecnológica, CEFET/RJ Nova Friburgo, Brasil [email protected] Arndt von Staa Departamento de Informática Pontifícia Universidade Católica, PUC-Rio Rio de Janeiro, Brasil [email protected] ResumoA qualidade funcional de um software pode ser avaliada por quão bem ele atende aos seus requisitos funcionais. Estes requisitos são muitas vezes descritos por intermédio de casos de uso e verificados por testes funcionais que checam sua correspondência com as funcionalidades observadas pela interface com o usuário. Porém, a criação, a manutenção e a execução destes testes são trabalhosas e caras, enfatizando a necessidade de ferramentas que as apoiem e realizem esta forma de controle de qualidade. Neste contexto, o presente artigo apresenta uma abordagem totalmente automatizada para a geração, execução e análise de testes funcionais, a partir da descrição textual de casos de uso. A ferramenta construída para comprovar sua viabilidade, chamada de FunTester, é capaz de gerar casos de teste valorados junto com os correspondentes oráculos, transformá-los em código-fonte, executá-los, coletar os resultados e analisar se o software está de acordo com os requisitos funcionais definidos. Avaliações preliminares demonstraram que a ferramenta é capaz de eficazmente detectar desvios de implementação e descobrir defeitos no software sob teste. Abstract The functional quality of any software system can be evaluated by how well it conforms to its functional requirements. These requirements are often described as use cases and are verified by functional tests that check whether the system under test (SUT) runs as specified. There is a need for software tools to make these tests less laborious and more economical to create, maintain and execute. This paper presents a fully automated process for the generation, execution, and analysis of functional tests based on use cases within software systems. A software tool called FunTester has been created to perform this process and detect any discrepancies from the SUT. Also while performing this process it generates conditions to cause failures which can be analyzed and fixed. Keywords functional validation; automated functional tests; use cases; business rules; test data generation; test oracle generation; test case generation and execution; I. INTRODUÇÃO A fase de testes é sabidamente uma das mais caras da construção de um software, correspondendo a 35 a 50% de seu custo total quando feito da forma tradicional [1] e de 15 a 25% quando desenvolvido com uso de técnicas formais leves [2]. Quando feita de forma manual, a atividade de teste se torna ineficiente e tediosa [3], usualmente apoiada em práticas ad hoc e dependente da habilidade de seus criadores. Assim, torna-se valioso o uso de ferramentas que possam automatizar esta atividade, diminuindo os custos envolvidos e aumentando as chances de se entregar um software com menor quantidade de defeitos remanescentes. Em geral, é entendido que um software de qualidade atende exatamente aos requisitos definidos em sua especificação [4]. Para verificar este atendimento, geralmente são realizados testes funcionais que observam a interface (gráfica) do software visando determinar se este realmente executa tal como especificado. Evidentemente supõe-se que os requisitos estejam de acordo com as necessidades e expectativas dos usuários. Como isso nem sempre é verdade, torna-se necessária a possibilidade de redefinir a baixo custo os testes a serem realizados. Para simular a execução destes testes, é possível imitar a operação de um usuário sobre a interface, entrando com ações e dados, e verificar se o software se comporta da maneira especificada. Esta simulação pode ser realizada via código, com a combinação de arcabouços de teste unitário e arcabouços de teste de interface com o usuário. Entretanto, para gerar o código de teste de forma automática, é preciso que a especificação do software seja descrita com mais formalidade e de maneira estruturada ou, pelo menos, semiestruturada. Como casos de uso são largamente utilizados para documentar requisitos de um software, torna-se interessante adaptar sua descrição textual para este fim. A descrição textual de casos de uso, num estilo similar ao usado por Cockburn [5], pode ser descrita numa linguagem restrita e semiestruturada, como o adotado por Días, Losavio, Matteo e Pastor [6] para a língua espanhola. Esta formalidade reduz o número de variações na interpretação da descrição, facilitando a sua transformação em testes. Trabalhos como [7, 8, 9, 10, 11, 12], construíram soluções para apoiar processos automatizados ou semiautomatizados para a geração dos casos de teste. Entretanto, alguns aspectos importantes não foram abordados, deixando de lado, por exemplo, a geração dos valores utilizados nos testes, a geração dos oráculos e a combinação de cenários entre múltiplos casos de uso, que são essenciais para sua efetiva aplicação prática. 2013 27th Brazilian Symposium on Software Engineering /13 $31.00 © 2013 IEEE DOI 10.1109/SBES.2013.18 41

[IEEE 2013 27th Brazilian Symposium on Software Engineering (SBES) - Brasilia, Brazil (2013.10.1-2013.10.4)] 2013 27th Brazilian Symposium on Software Engineering - Functional Validation

Embed Size (px)

Citation preview

Page 1: [IEEE 2013 27th Brazilian Symposium on Software Engineering (SBES) - Brasilia, Brazil (2013.10.1-2013.10.4)] 2013 27th Brazilian Symposium on Software Engineering - Functional Validation

Functional Validation Driven by Automated Tests Validação Funcional Dirigida por Testes Automatizados

Thiago Delgado Pinto Departamento de Informática

Centro Federal de Educação Tecnológica, CEFET/RJ Nova Friburgo, Brasil

[email protected]

Arndt von Staa Departamento de Informática

Pontifícia Universidade Católica, PUC-Rio Rio de Janeiro, Brasil [email protected]

Resumo—A qualidade funcional de um software pode ser avaliada por quão bem ele atende aos seus requisitos funcionais. Estes requisitos são muitas vezes descritos por intermédio de casos de uso e verificados por testes funcionais que checam sua correspondência com as funcionalidades observadas pela interface com o usuário. Porém, a criação, a manutenção e a execução destes testes são trabalhosas e caras, enfatizando a necessidade de ferramentas que as apoiem e realizem esta forma de controle de qualidade. Neste contexto, o presente artigo apresenta uma abordagem totalmente automatizada para a geração, execução e análise de testes funcionais, a partir da descrição textual de casos de uso. A ferramenta construída para comprovar sua viabilidade, chamada de FunTester, é capaz de gerar casos de teste valorados junto com os correspondentes oráculos, transformá-los em código-fonte, executá-los, coletar os resultados e analisar se o software está de acordo com os requisitos funcionais definidos. Avaliações preliminares demonstraram que a ferramenta é capaz de eficazmente detectar desvios de implementação e descobrir defeitos no software sob teste.

Abstract – The functional quality of any software system can be evaluated by how well it conforms to its functional requirements. These requirements are often described as use cases and are verified by functional tests that check whether the system under test (SUT) runs as specified. There is a need for software tools to make these tests less laborious and more economical to create, maintain and execute. This paper presents a fully automated process for the generation, execution, and analysis of functional tests based on use cases within software systems. A software tool called FunTester has been created to perform this process and detect any discrepancies from the SUT. Also while performing this process it generates conditions to cause failures which can be analyzed and fixed.

Keywords – functional validation; automated functional tests; use cases; business rules; test data generation; test oracle generation; test case generation and execution;

I. INTRODUÇÃO

A fase de testes é sabidamente uma das mais caras da construção de um software, correspondendo a 35 a 50% de seu custo total quando feito da forma tradicional [1] e de 15 a 25% quando desenvolvido com uso de técnicas formais leves [2]. Quando feita de forma manual, a atividade de teste se torna

ineficiente e tediosa [3], usualmente apoiada em práticas adhoc e dependente da habilidade de seus criadores. Assim, torna-se valioso o uso de ferramentas que possam automatizar esta atividade, diminuindo os custos envolvidos e aumentando as chances de se entregar um software com menor quantidade de defeitos remanescentes.

Em geral, é entendido que um software de qualidade atende exatamente aos requisitos definidos em sua especificação [4]. Para verificar este atendimento, geralmente são realizados testes funcionais que observam a interface (gráfica) dosoftware visando determinar se este realmente executa tal como especificado. Evidentemente supõe-se que os requisitos estejam de acordo com as necessidades e expectativas dos usuários. Como isso nem sempre é verdade, torna-se necessária a possibilidade de redefinir a baixo custo os testes a serem realizados.

Para simular a execução destes testes, é possível imitar a operação de um usuário sobre a interface, entrando com ações e dados, e verificar se o software se comporta da maneira especificada. Esta simulação pode ser realizada via código,com a combinação de arcabouços de teste unitário e arcabouços de teste de interface com o usuário. Entretanto, para gerar o código de teste de forma automática, é preciso que a especificação do software seja descrita com mais formalidade ede maneira estruturada ou, pelo menos, semiestruturada. Como casos de uso são largamente utilizados para documentar requisitos de um software, torna-se interessante adaptar sua descrição textual para este fim.

A descrição textual de casos de uso, num estilo similar ao usado por Cockburn [5], pode ser descrita numa linguagem restrita e semiestruturada, como o adotado por Días, Losavio, Matteo e Pastor [6] para a língua espanhola. Esta formalidade reduz o número de variações na interpretação da descrição, facilitando a sua transformação em testes.

Trabalhos como [7, 8, 9, 10, 11, 12], construíram soluções para apoiar processos automatizados ou semiautomatizados para a geração dos casos de teste. Entretanto, alguns aspectos importantes não foram abordados, deixando de lado, por exemplo, a geração dos valores utilizados nos testes, a geração dos oráculos e a combinação de cenários entre múltiplos casos de uso, que são essenciais para sua efetiva aplicação prática.

2013 27th Brazilian Symposium on Software Engineering

/13 $31.00 © 2013 IEEE

DOI 10.1109/SBES.2013.18

41

Page 2: [IEEE 2013 27th Brazilian Symposium on Software Engineering (SBES) - Brasilia, Brazil (2013.10.1-2013.10.4)] 2013 27th Brazilian Symposium on Software Engineering - Functional Validation

TABELA I. PANORAMA SOBRE AS FERRAMENTAS

# Questão [9] [11] [12] [7] [10] FunTester

1 Usa somente casos de uso como fonte para os testes?

sim sim sim sim sim sim1

2 Qual a forma de documentação dos casos de uso?

PRS IRS IRS IRS UCML VRS

3 Controla a declaração de casos de uso?

sim não não não não Sim

4 Dispensa a declaração de fluxos alternativos que avaliam regras de negócio?

não não não não não Sim

5 Gera cenários automaticamente?

sim sim sim sim sim Sim

6 Há um cenário cobrindo cada fluxo?

sim sim sim sim sim sim

7 Há cenários que verifiquem regras de negócio para um mesmo fluxo?

não sim não não não sim

8 Há cenários que combinam fluxos?

não sim sim sim sim sim

9 Há cenários que incluem mais de um caso de uso?

não não não não não sim

10 Há métricas para cobertura dos cenários?

não não não sim sim sim

11 Gera casos de teste semânticos?

não sim não não sim sim

12 Gera valores para os casos de teste automaticamente?

não não não não não sim

13 Gera oráculos automaticamente?

não não não não não sim

14 Casos de teste são gerados para um formato independente de linguagem ou framework?

não sim não não sim sim

15 Gera código de teste?

sim não sim sim não sim

16 Os resultados da execução do código gerado são rastreados?

sim N/A não não N/A sim

a. N/A=Não se aplica; PRS=Português Restrito Semiestruturado; IRS=Inglês Restrito Semiestruturado; UCML=Use Case Markup Language; VRS=Vocabulário Restrito Semiestruturado independente

de idioma.

No processo de geração de casos de teste automatizados criam-se primeiro os casos de teste abstratos. Estes determinam as condições que cada caso de teste deve satisfazer (por exemplo, os caminhos a serem percorridos). A partir deles determinam-se os casos de teste semânticos, isto é, casos de teste independentes de arcabouço de testes. Estes levam em conta as condições que os dados de entrada devem satisfazer de

1 As regras de negócio, descritas adicionalmente em relação às outras

soluções, ainda pertencem aos casos de uso.

modo que os testes abstratos sejam realizados. A seguir selecionam-se os valores dos dados de entrada, gerando os casos de teste valorados. Aplicando a especificação aos casos de teste valorados determinam-se os oráculos, obtendo-se assim os casos de teste úteis. Estes, finalmente são traduzidos para scripts ou código a ser usado por ferramentas ou arcabouços de teste automatizado.

Este artigo descreve um processo totalmente automatizado que trata muitos dos problemas não resolvidos por trabalhos anteriores (como a geração automática de dados de teste, oráculos e cenários que combinam mais de um caso de uso) eintroduz novas abordagens para aumentar sua aplicação prática e realizar uma validação funcional de alta eficácia.

As próximas seções são organizadas da seguinte forma: A Seção II apresenta trabalhos correlatos. A Seção III detalha o novo processo definido. A Seção IV expõe brevemente a arquitetura da solução. A Seção V retrata uma avaliação preliminar da ferramenta. Por fim, a Seção VI apresenta as conclusões do trabalho.

II. TRABALHOS CORRELATOS

Esta seção realiza uma avaliação de alguns trabalhos correlatos, com foco na descrição textual de casos de uso como principal fonte para a geração dos testes.

A Tabela I apresenta um panorama sobre os trabalhos que construíram ferramentas para este propósito, incluindo a ferramenta que materializa a abordagem discutida neste artigo, chamada de FunTester (acrônimo para Funcional Tester). Nela, é possível observar que FunTester apresenta uma solução mais completa, implementando avanços que permitem sua aplicação prática em projetos reais.

III. PROCESSO

A Figura 1 apresenta o processo realizado na abordagem apresentada e seguido pela ferramenta construída.

Fig. 1. Processo seguido pela ferramenta

42

Page 3: [IEEE 2013 27th Brazilian Symposium on Software Engineering (SBES) - Brasilia, Brazil (2013.10.1-2013.10.4)] 2013 27th Brazilian Symposium on Software Engineering - Functional Validation

Neste processo, o usuário participa apenas das etapas de descrição dos casos de uso e de suas regras de negócio, sendo as demais totalmente automatizadas. As etapas 1, 2, 3, 4, 5 e 9 são realizadas pela ferramenta em si, enquanto as etapas 6, 7 e8 são realizadas por extensões da ferramenta, para a linguagem e arcabouço de testes alvo. A seguir, será realizada uma descrição de cada uma delas.

A. Descrição textual de casos de uso (Etapa 1) Nesta etapa, o usuário realiza a especificação do software

através de casos de uso, auxiliado pela ferramenta. A descrição textual segue um modelo similar ao de Cockburn [5]. Aferramenta usa somente alguns dos campos desta descrição para a geração de testes. As pré-condições e pós-condições são usadas para estabelecer as dependências entre casos de uso,numa espécie de máquina de estados. Dos fluxos (disparador, principal e alternativos) são obtidos os cenários de execução. De seus passos são extraídas as ações executadas pelo ator e pelo sistema, que junto a outras informações do caso de uso (como a indicação se ele pode ser disparado somente através de outro caso de uso), são usadas para a geração dos testes úteis,na etapa 5.

A ferramenta permite definir um vocabulário composto pelos termos esperados por sua extensão para a transformação dos testes úteis em código-fonte e pelos termos correspondentes, usados na descrição textual dos casos de uso. Isto permite tanto documentar o software usando palavras ou até idiomas diferentes do vocabulário usado para geração dos testes quanto adaptar esse último para diferentes arcabouços de teste.

A sintaxe de um passo numa gramática livre de contexto (GLC) similar à Backus-Naur Form (BNF) é descrita a seguir: <passo> ::= <disparador> <ação> <alvo>+

| <disparador> <documentação> <disparador> ::= "ator" | "sistema" <alvo> ::= <elemento> | <caso-de-uso> <elemento> ::= <widget> | <URL> | <comando>

| <tecla> | <tempo> <ação> ::= string <documentação> ::= string <caso-de-uso> ::= string <widget> ::= string <URL> ::= string <comando> ::= string <tecla> ::= string <tempo> ::= integer

O ator ou o sistema dispara uma ação sobre um ou mais alvos ou sobre uma documentação. Cada alvo pode ser um elemento ou um caso de uso. Um elemento pode ser um widget, uma URL, um comando, uma tecla ou um tempo (em milissegundos, que é geralmente usado para aguardar um processamento).

O tipo de alvo e o número de alvos possíveis para uma ação podem variar conforme a configuração do vocabulário usado. O tipo de elemento também pode variar conforme a ação escolhida.

B. Detalhamento das regras de negócio (Etapa 2) Esta etapa é um dos importantes diferenciais da ferramenta

e permite que o usuário detalhe os elementos descritos ao

preencher os passos dos fluxos. Este detalhamento possibilitasaber o que representa cada elemento, extrair as informações necessárias para sua conversão em widgets, inferir seus possíveis valores e formatos e extrair as informações necessárias para a geração de oráculos. A introdução das regras de negócio também permite reduzir o número de fluxos alternativos necessários para tratar erros de uso, uma vez que a ferramenta gerará automaticamente casos de teste para isto. Isto permite reduzir consideravelmente o número de caminhos no uso do software (introduzidos pela combinação dos fluxos), diminuindo o número de cenários, casos de teste e consequentemente o tempo de execução dos testes.

A sintaxe definida para as regras de negócio permite determinar regras tanto para dados contínuos quanto para dados discretos. O detalhamento de um elemento e de suas regras é exposto a seguir (em GLC): <elemento> ::= <nome><tipo><nome-interno>

| <nome><tipo><nome-interno><regra>+ <tipo> ::= "widget" | "url" | "comando"

| "teclas" | "tempo" <nome> ::= string <nome-interno> ::= string <regra> ::= <tipo-dado><espec-valor>+ <tipo-dado> ::= "string" | "integer" | "double"

| "date" | "time" | "datetime" <espec-valor> ::= <tipo-espec><mensagem> <tipo-espec> ::= "valor-min" <ref-valor> | "valor-max" <ref-valor>

| "comprimento-min" <ref-valor> | "comprimento-max" < ref-valor> | "formato" <ref-valor> | "igual-a" <ref-valor>+ | "diferente-de" <ref-valor>+

<mensagem> ::= string <ref-valor> ::= <valor>+|<elemento>

Um elemento – que seria equivalente ao widget da

descrição do passo – possui um nome (que é o exibido para o usuário na documentação), um tipo (ex.: uma janela, um botão, uma caixa de texto, etc.) e um nome interno (que é usado internamente para identificar o widget no SST). Se for definido como editável (se recebe entradas de dados do usuário), pode conter uma ou mais regras de negócio. Cada regra define o tipo de dado admitido pelo elemento e uma ou mais especificações de valor, que permitem definir valores limítrofes, formatos, lista de valores admissíveis ou não admissíveis, além (opcionalmente) da mensagem esperada do SST caso alguma destas definições seja violada (ex.: valor acima do limítrofe).Cada especificação de valor pode ser proveniente de definição manual, de definição a partir de outro elemento ou a partir de consulta parametrizável a um banco de dados (obtendo seus parâmetros de outra definição, se preciso), fornecendo flexibilidade para a construção das regras.

A definição de regras com valores obtidos através de consulta a banco de dados permite utilizar dados criados com o propósito de teste. Estes dados podem conter valores idênticos aos esperados pelo sistema, permitindo simular condições de uso real, o que é desejável em ferramentas de teste.

C. Geração de cenários para cada caso de uso (Etapa 3) Nesta etapa, a ferramenta combina os fluxos de cada caso

de uso, gerando cenários. Cada cenário parte do fluxo

43

Page 4: [IEEE 2013 27th Brazilian Symposium on Software Engineering (SBES) - Brasilia, Brazil (2013.10.1-2013.10.4)] 2013 27th Brazilian Symposium on Software Engineering - Functional Validation

principal, possivelmente passando por fluxos alternativos, retornando ao fluxo principal ou caindo em recursão (repetindo a passagem por um ou mais fluxos).

Como os casos de recursão potencializam o número de combinações entre fluxos, o número de recursões deve ser mantido baixo, para não inviabilizar a aplicação prática da geração de cenários. Para isso, a ferramenta permite parametrizar o número máximo de recursões, limitando aquantidade de cenários gerados.

A geração de cenários realizada cobre a passagem por todos os fluxos do caso de uso, bem como a combinação entre todos eles, pelo menos uma vez. Em cada fluxo, todos os passos são cobertos. Isto garante observar defeitos relacionados à passagem por determinados fluxos ou ocasionados por sua combinação. Segundo o critério de cálculo de cobertura de caso de uso adotado por Hassan e Yousif [13], que divide o total de passos cobertos pelo teste pelo total de passos do caso de uso, a cobertura atingida é de 100%.

D. Combinação de cenários entre casos de uso (Etapa 4) Esta etapa realiza a combinação entre cenários, levando em

conta os estados definidos nas pré-condições e pós-condições, bem como as chamadas a casos de uso, que podem ocorrer em passos de certos fluxos. Quando uma pré-condição referencia uma pós-condição gerada por outro caso de uso, é estabelecida uma relação de dependência de estado. Logo, os cenários do caso de uso do qual se depende devem ser gerados primeiro, para então realizar a combinação. O mesmo ocorre quando existe uma chamada para outro caso de uso.

Para representar a rede de dependências entre os casos de uso do SST e obter a ordem correta para a geração dos cenários, é gerado um grafo acíclico dirigido dos casos de uso e então aplicada uma ordenação topológica [14]. Antes de combinar dois cenários, entretanto, é preciso verificar se os fluxos de um geram os estados esperados pelo outro. Caso não gerem, os cenários não são combinados, uma vez que acombinação poderá gerar um novo cenário incompleto ou incorreto, podendo impedir que a execução alcance o caso de uso alvo do teste. Assim, na versão atual da ferramenta, para combinar dois casos de uso, X e Y, onde X depende de Y, são selecionados de Y somente os cenários que terminem com sucesso, isto é, que não impeçam a execução do caso de uso Xconforme previsto.

Para garantir a correta combinação dos cenários de um caso de uso, sem que se gerem cenários incompletos ou incorretos, realiza-se primeiro a combinação com os cenários de casos de uso chamados em passos; depois com os cenários de fluxos disparadores do próprio caso de uso; e só então com cenários de casos de uso de pré-condições.

Dados A e B dois casos de uso quaisquer do conjunto de casos de uso do software, CDU, seja C� o número de cenários do caso de uso A, C� o número de cenários do caso de uso B,CS� o número de cenários de sucesso de B, se A depende de B, então a cobertura dos cenários de A, CO�, pode ser calculada como:

CO� =CS� × C�

C� × C�

=CS�

C�

Se, por exemplo, um caso de uso B tiver 5 cenários, sendo 3 de sucesso, e outro caso de uso, A, que depende de B, tiver 8 cenários, a cobertura total seria de 40 combinações, enquanto a cobertura alcançada seria de 24 combinações, ou 60% do total. Apesar de esta cobertura não ser total (100%), acredita-se que ela seja eficaz para testes de casos de uso, uma vez que ageração de cenários incorretos ou incompletos pode impedir o teste do caso de uso alvo.

É importante notar que a combinação entre cenários é multiplicativa, ou seja, a cada caso de uso adicionado, seu conjunto de cenários é multiplicado pelos atuais. Foram consideradas algumas soluções para este problema, cuja implementação está entre os projetos futuros, discutidos na Seção V.

E. Geração de casos de teste úteis (Etapa 5) Nesta etapa, a ferramenta gera os casos de teste úteis

(formados por comandos, dados valorados e oráculos) utilizando os cenários e as regras de negócio. Estas regras permitem inferir os valores válidos e não válidos para cada elemento e gerá-los automaticamente, de acordo com o tipo de teste. Os oráculos são gerados com uso da definição das mensagens esperadas para quando são fornecidos valores não válidos, de acordo com o tipo de verificação desejada para o teste.

Como cada descrição de expectativa de comportamento do sistema é transformada em comandos semânticos e estes (posteriormente) em comandos na linguagem usada pelo arcabouço de testes, quando um comando não é executado corretamente por motivo do SST não corresponder à sua expectativa, o teste automaticamente falhará. Assim, não é necessário haver oráculos que verifiquem a existência de elementos de interface, exceto a exibição de mensagens. Segundo Meyers [15], o teste de software torna-se mais eficaz se os valores de teste são gerados baseados na análise das "condições de contorno" ou "condições limite". Ao utilizar valores acima e abaixo deste limite, os casos de teste exploram as condições que aumentam a chance de encontrar defeitos. De acordo com o British Standard 7925-1 [16], o teste de software torna-se mais eficaz se os valores são particionados ou divididos de alguma maneira, como, por exemplo, ao meio. Além disto, é interessante a inclusão do valor zero (0), que permite testar casos de divisão por zero, bem como o uso de valores aleatórios, que podem fazer o software atingir condições imprevistas. Portanto, levando em consideração as regras de negócio definidas, para a geração de valores considerados válidos, independentes do tipo, são adotados os critérios de: (a) valor mínimo; (b) valor imediatamente posterior ao mínimo; (c) valor máximo; (d) valor imediatamente anterior ao máximo; (e) valor intermediário; (f) zero, se dentro da faixa permitida; (g) valor aleatório, dentro da faixa permitida. E para a geração de valores considerados não válidos, os critérios de: (a) valor imediatamente anterior ao mínimo; (b) valor aleatório anterior ao mínimo; (c) valor imediatamente posterior ao máximo; (d) valor aleatório posterior ao máximo; (e) formato de valor incorreto.

44

Page 5: [IEEE 2013 27th Brazilian Symposium on Software Engineering (SBES) - Brasilia, Brazil (2013.10.1-2013.10.4)] 2013 27th Brazilian Symposium on Software Engineering - Functional Validation

A Tabela II exibe os tipos de teste gerados na versão atual da ferramenta, que visam cobrir as regras de negócio definidas.Baseado neles, podemos calcular a quantidade mínima de casos de teste úteis gerados por cenário, QM, como:

QM = 8 + 4E + O + F�

Onde E é o número de elementos editáveis, O é o número de elementos editáveis obrigatórios e F é o número de elementos editáveis com formato definido. Para cada cenário de um caso de uso simples, por exemplo, com 5 elementos, sendo 3 obrigatórios e 1 com formatação, existirão 32 casos de teste.

TABELA II. TIPOS DE TESTE GERADOS

Descrição Conclui caso de uso

Testes

Somente obrigatórios Sim 1Todos os obrigatórios exceto um Não 1 por elemento

editável obrigatório

Todos com valor/tamanho mínimo Sim 1Todos com valor/tamanho posterior ao mínimo

Sim 1

Todos com valor/tamanho máximo Sim 1Todos com valor/tamanho anterior ao máximo

Sim 1

Todos com o valor intermediário, dentro da faixa

Sim 1

Todos com zero, ou um valor aleatório dentro da faixa, se zero não for permitido

Sim 1

Todos com valores aleatórios dentro da faixa

Sim 1

Todos com valores aleatórios dentro da faixa, exceto um, com valor imediatamente anterior ao mínimo

Não 1 por elemento editável

Todos com valores aleatórios dentro da faixa, exceto um, com valor aleatório anterior ao mínimo

Não 1 por elemento editável

Todos com valores aleatórios dentro

da faixa, exceto um, com valor imediatamente posterior ao máximo

Não 1 por elemento editável

Todos com valores aleatórios dentro

da faixa, exceto um, com valor

aleatório posterior ao máximo

Não 1 por elemento editável

Todos com formato permitido, exceto

um

Não 1 por elemento com formato

definido

Os testes gerados cobrem todas as regras de negóciodefinidas, explorando seus valores limítrofes e outros. Como o total de testes possíveis para um caso de uso não é conhecido, acredita-se que com a cobertura acumulada, unindo todas ascoberturas descritas até aqui, espera-se exercitar consideravelmente o SST na busca por defeitos, obtendo alta eficácia.

Atualmente os casos de teste úteis são exportados para a JavaScript Object Notation (JSON), por ser compacta,independente de linguagem de programação e fácil de analisar gramaticalmente.

F. Transformação em código-fonte (Etapa 6) Esta etapa e as duas seguintes utilizam a extensão da

ferramenta escolhida pelo usuário, de acordo o software a ser testado.

A extensão da ferramenta lê o arquivo JSON contendo os testes úteis e os transforma em código-fonte, para a linguagem e arcabouços de teste disponibilizados por ela. Atualmente, há uma extensão que os transforma em código Java e os arcabouços TestNG2 e FEST3, visando o teste de aplicações com interface gráfica Swing.

Para facilitar o rastreamento de falhas ou erros nos testes, a extensão construída realiza a instrumentação do código-fonte gerado, indicando, com comentários de linha, o passo semântico correspondente à linha de código. Esta instrumentação será utilizada na Etapa 8, para pré-análise dos resultados.

G. Execução do código-fonte (Etapa 7) Nesta etapa, a extensão da ferramenta executa o código-

fonte de testes gerado. Para isto, ela usa linhas de comando configuradas pelo usuário, que podem incluir a chamada a um compilador, ligador (linker), interpretador, navegador web, ou qualquer outra aplicação ou arquivo de script que dispare a execução dos testes.

Durante a execução, o arcabouço de testes utilizado gera um arquivo com o log de execução dos testes. Este arquivo será lido e analisado na próxima etapa do processo.

H. Conversão e pré-análise dos resultados de execução (Etapa 8) Nesta etapa, a extensão da ferramenta lê o log de execução

dos testes e analisa os testes que falharam ou obtiveram erro, investigando: (a) a mensagem de exceção gerada, para detectar o tipo de problema ocorrido; (b) o rastro da pilha de execução, para detectar o arquivo e a linha do código-fonte onde a exceção ocorreu e obter a identificação do passo semântico correspondente (definida pela instrumentação realizada na Etapa 6), possibilitando rastrear o passo, fluxo e cenário correspondentes; (c) comparar o resultado esperado pelo teste semântico com o obtido.

O log de execução e as informações obtidas da pré-análise são convertidos para um formato independente de arcabouço de testes e exportados para um arquivo JSON, que será lido e analisado pela ferramenta na próxima etapa.

I. Análise e apresentação dos resultados (Etapa 9) Por fim, a ferramenta realiza a leitura do arquivo com os

resultados da execução dos testes e procura analisá-los para rastrear as causas de cada problema encontrado (se houverem).Nesta etapa, o resultado da execução é confrontado com a especificação do software, visando identificar possíveis problemas.

2 http://testng.org3 http://fest.easytesting.org

45

Page 6: [IEEE 2013 27th Brazilian Symposium on Software Engineering (SBES) - Brasilia, Brazil (2013.10.1-2013.10.4)] 2013 27th Brazilian Symposium on Software Engineering - Functional Validation

Fig. 2. Arquitetura da solução

IV. ARQUITETURA

A Figura 2 apresenta a arquitetura da solução construída, indicando seus componentes e a ordem de interação entre os mesmos, de forma a fornecer uma visão geral sobre como o processo descrito é praticado.

É interessante observar que, em geral, o código gerado fará uso de dois arcabouços de teste: um para automatizar a execução dos testes e outro para testar especificamente o tipo de interface (com o usuário) desejada. Esse arcabouço de automação dos testes que irá gerar os resultados da execução dos testes lidos pela extensão da ferramenta.

V. AVALIAÇÃO

Uma avaliação preliminar da eficácia da ferramenta foi realizada com um software construído por terceiros, coletado da Internet. O software avaliado contém uma especificação derequisitos por descrição textual de casos de uso, realiza acesso a um banco de dados MySQL4 e possui interface Swing.

A especificação encontrada no software avaliado estava incompleta, faltando, por exemplo, alguns fluxos alternativos e regras de negócio. Quando isso ocorre, dá-se margem para que a equipe de desenvolvedores do software complete a especificação conforme sua intuição (e criatividade), muitas vezes divergindo da intenção original do projetista, que tenta mapear o problema real. Como isto acabou ocorrendo no software avaliado, optou-se por coletar os detalhes não

4 http://www.mysql.com/

presentes na especificação a partir da implementação do software. Desta forma, são aumentadas as chances da especificação estar próxima da implementação, acusando menos defeitos deste tipo.

Para testar a eficácia da ferramenta, foram geradas: (a) uma versão da especificação funcional do SST com divergências;(b) duas versões modificadas do SST, com emprego de mutantes.

Para gerar as versões com empregos de mutantes, levou-se em consideração, assim como no trabalho de Gutiérrez et al.[7], o modelo de defeitos de caso de uso introduzido por Binder [17], que define operadores mutantes para casos de uso. O uso desses operadores é considerado mais apropriado para testes funcionais (do que os operadores "clássicos"), uma vez que seu objetivo não é testar a cobertura do código do SST em si, mas gerar mudanças no comportamento do SST que possam ser observadas por testes funcionais. Nesse contexto, o termo "mutante" possui uma conotação diferente do mesmo termo aplicado a código. Um mutante da especificação funcional tem o poder de gerar uma variedade de casos de teste que reportarão falhas. Da mesma forma, um mutante de código tem o poder de gerar falhas em uma variedade de casos de teste gerados a partir da especificação funcional.

Na versão da especificação do SST com divergências, foram introduzidas novas regras de negócio, visando verificar se os testes gerados pela ferramenta seriam capazes de identificar as respectivas diferenças em relação ao SST. Naprimeira versão modificada do SST, foi usado o operador

46

Page 7: [IEEE 2013 27th Brazilian Symposium on Software Engineering (SBES) - Brasilia, Brazil (2013.10.1-2013.10.4)] 2013 27th Brazilian Symposium on Software Engineering - Functional Validation

mutante para casos de uso "substituição de regras de validação ou da admissão de um dado como correto" (SRV). Com ele, operadores condicionais usados no código de validação de dados do SST foram invertidos, de forma a não serem admitidos como corretos. E na segunda versão do SST, foiutilizado operador mutante de casos de uso "informação incompleta ou incorreta mostrada pelo sistema" (I3). Com ele, as mensagens mostradas pelo sistema quando detectado um dado inválido foram modificadas, de forma a divergirem da esperada pela especificação.

A Tabela III apresenta a quantidade de modificações realizadas nos três principais cenários analisados e a Tabela IV, o número testes que obtiveram falha, aplicando-se estas modificações.

Com o total de 7 modificações na especificação original,mais 9 testes obtiveram falha em relação ao resultado original. Com o emprego de 22 mutações com o primeiro mutante(SRV), mais 51 testes obtiveram falha. E com o emprego de 10 mutações com o segundo mutante (I3), mais 12 testes falharam.

TABELA III. MODIFICAÇÕES NOS TRÊS PRINCIPAIS CENÁRIOS

Cenário Modificações na

especificação funcional

Mutações com

mutanteSRV

Mutações com

mutanteI3

Cenário 1 2 2 4Cenário 2 3 14 4Cenário 3 2 6 2

TOTAL 7 22 10

TABELA IV. NÚMERO DE TESTES QUE FALHARAM

Cenário Número de testes que falharam

SSToriginal

SST frente à especificação

funcionalcom

divergências

SST com mutante

SRV

SST com mutante I3

Cenário 1 4 10 8 10Cenário 2 35 40 59 37Cenário 3 37 35 60 41

TOTAL 76 85 127 88Assim, além de corretamente detectar defeitos na versão

original, geradas por entradas de dados não válidos e por diferenças na especificação, os testes gerados pela ferramenta foram capazes de observar as mudanças realizadas, tanto em relação à especificação quanto em relação à implementação do SST.

VI. CONCLUSÕES

O presente artigo apresentou uma nova abordagem para a geração e execução automática de testes funcionais, baseada na especificação de requisitos através da descrição textual de casos de uso e do detalhamento de suas regras de negócio.

Os resultados preliminares obtidos com o emprego da ferramenta foram bastante promissores, uma vez que se pôde perceber que ela é capaz de atingir alta eficácia em seus testes, encontrando corretamente diferenças entre a especificação e a implementação do SST.

Além disso, seu uso permite estabelecer um meio de aplicar Test-Driven Development no nível de especificação, de forma que o software seja construído, incrementalmente, para passar nos testes gerados pela especificação construída. Ou seja, uma equipe de desenvolvimento pode criar a especificação funcional de uma parte do sistema, gerar os testes funcionais a partir desta especificação, implementar a funcionalidade correspondente e executar os testes gerados para verificar se afuncionalidade corresponde à especificação. Isto, inclusive, pode motivar a criação de especificações mais completas e corretas, uma vez que compensará fazê-lo.

A. Principais contribuições Dentre as principais contribuições da abordagem construída

destacam-se: (a) Apresentação de um processo completo e totalmente automatizado; (b) Uso da descrição de regras de negócio na especificação dos casos de uso, permitindo gerar osvalores e oráculos dos testes, bem como tornar desnecessário descrever uma parcela significativa dos fluxos alternativos; (c) Uso de fontes de dados externas (ex.: banco de dados) na composição das regras de negócio, permitindo a simulação de condições reais de uso; (d) Geração de cenários que envolvem repetições de fluxos (loops) com número de repetições parametrizável; (e) Geração de cenários que envolvem mais de um caso de uso; (f) Geração de testes semânticos com nomes correlatos ao tipo de verificação a ser realizada, permitindo que o desenvolvedor entenda o que cada teste verifica, facilitando sua manutenção; e (g) Uso de vocabulário configurável, permitindo realizar a descrição textual em qualquer idioma e diferentes arcabouços de teste.

B. Principais restrições As principais restrições da abordagem apresentada

atualmente são: (a) Não simulação de testes para fluxos que tratam exceções (ex.: falha de comunicação via rede, falha da mídia de armazenamento, etc.), uma vez que exceções tendem a ser de difícil (senão impossível) simulação através de testes funcionais realizados através da interface com o usuário; (b) As regras de negócio atualmente não suportam o uso de expressões que envolvam cálculos, fórmulas matemáticas ou o uso de expressões condicionais (ex.: if-then-else); (c) Aabrangência dos tipos de interface gráfica passíveis de teste pela ferramenta é proporcional aos arcabouços de testes de interface utilizados. Assim, é possível que determinados tipos de interface com o usuário, como as criadas para games ou aplicações multimídia, possam não ser testadas por completo, se o arcabouço de testes escolhido não suportá-los, ou não suportar determinadas operações necessárias para seu teste.

C. Trabalhos em andamento Atualmente outros tipos de teste estão sendo acrescentados

à ferramenta, aumentando seu potencial de verificação. Acapacidade de análise automática dos problemas ocorridos, de acordo com os resultados fornecidos pelo arcabouço de testesalvo, também está sendo ampliada.

Testes mais rigorosos da ferramenta estão sendo elaborados para verificar a flexibilidade e eficácia da ferramenta em diferentes situações de uso prático.

47

Page 8: [IEEE 2013 27th Brazilian Symposium on Software Engineering (SBES) - Brasilia, Brazil (2013.10.1-2013.10.4)] 2013 27th Brazilian Symposium on Software Engineering - Functional Validation

D. Trabalhos futuros A atual geração de cenários combina todos os fluxos do

caso de uso pelo menos uma vez, garantindo um bom nível de cobertura para a geração de testes. Isto é um atributo desejável para verificar o SST antes da liberação de uma versão para o usuário final. Durante seu desenvolvimento, entretanto, pode ser interessante diminuir a cobertura realizada, para que o processo de execução de testes ocorra em menor tempo. Para isto, propõe-se o uso de duas técnicas: (a) atribuir um valor de importância para cada fluxo, que servirá como como filtro para a seleção dos cenários desejados para teste; e (b) realizar a indicação da não influência de certos fluxos em outros, evitando gerar cenários que os combinem. Esta última técnica deve ser empregada com cuidado, para evitar a indicação de falsos negativos (fluxos que se pensa não influenciar o estado de outros, mas na verdade influencia).

Para diminuir a cobertura realizada pela combinação de cenários, com intuito de acelerar a geração dos cenários para fins de testes rápidos, pode-se empregar a técnica de uso do valor de importância, descrita anteriormente, além de uma seleção aleatória e baseada em histórico. Nesta seleção, o combinador de cenários realizaria a combinação entre dois casos de uso escolhendo, pseudoaleatoriamente, um cenário compatível (de acordo com as regras de combinação descritas na Etapa 4) de cada um. Para esta seleção não se repetir, seria guardado um histórico das combinações anteriores. Dessa forma, a cobertura seria atingida gradualmente, alcançando acobertura completa ao longo do tempo.

Para reduzir o número de testes gerados, também se pode atribuir um valor de importância para as regras de negócio, de forma a gerar testes apenas para as mais relevantes. Também se poderia adotar a técnica de seleção gradual aleatória (descrita anteriormente) para as demais regras, a fim de que a cobertura total das regras de negócio fosse atingida ao longo do tempo.

Por fim, pretende-se criar versões dos algoritmos construídos (não discutidos neste artigo) que executassem em paralelo, acelerando o processo. Obviamente, também serão criadas extensões para outros arcabouços de teste, como Selenium5 ou JWebUnit6 (que visam aplicações web),aumentando a abrangência do uso da ferramenta.

REFERÊNCIAS

[1] MILER, Keith W., MORELL, Larry J., NOONAN, Robert E., PARK, Stephen K., NICOL, David M., MURRIL, Branson W., VOAS, Jeffrey M., "Estimating the probability of failure when testing reveals no failures", IEEE Transactions on Software Engineering, n. 18, 1992, pp 33-43.

[2] BENDER, Richard, "Proposed software evaluation and test KPA", n. 4, 1996, Disponível em: http://www.uml.org.cn/test/12/softwaretestingmaturitymodel.pdf

[3] MAGALHÃES, João Alfredo P. "Recovery oriented software", Tese de Doutorado, PUC-Rio, Rio de Janeiro, 2009.

[4] CROSBY, Philip B., "Quality is free", McGraw-Hill, New-York, 1979. [5] COCKBURN, Alistar. "Writing effective use cases", Addison-Wesley,

2000.

5 http://seleniumhq.org6 http://jwebunit.sourceforge.net/

[6] DÍAS, Isabel, LOSAVIO, Francisca, MATTEO, Alfredo, PASTOR, Oscar, "A specification pattern for use cases", Information & Management, n. 41, 2004, pp. 961-975.

[7] GUTIÉRREZ, Javier J., ESCALONA, Maria J., MEJÍAS, Manuel, TORRES, Jesús, CENTENO, Arturo H, "A case study for generating test cases from use cases", University of Sevilla, Sevilla, Spain, 2008.

[8] CALDEIRA, Luiz Rodolfo N., "Geração semi-automática de massas de testes funcionais a partir da composição de casos de uso e tabelas de decisão", Dissertação de Mestrado, PUC-Rio, Rio de Janeiro, 2010.

[9] PESSOA, Marcos B., "Geração e execução automática de scripts de teste para aplicações web a partir de casos de uso direcionados por comportamento", Dissertação de Mestrado, PUC-Rio, Rio de Janeiro, 2011.

[10] KASSEL, Neil W., "An approach to automate test case generation from structured use cases", Tese de Doutorado, Clemson University, 2006.

[11] JIANG, Mingyue, DING, Zuohua, "Automation of test case generation from textual use cases", Zhejiang Sci-Tech University, Hangzhou, China, 2011.

[12] BERTOLINI, Cristiano, MOTA, Alexandre, "A framework for GUI testing based on use case design", Universidade Federal de Pernambuco, Recife, Brazil, 2010.

[13] HASSAN, Hesham A., YOUSIF, Zahraa E., "Generating test cases for platform independent model by using use case model", International Journal of Engineering Science and Technology, vol. 2, 2010.

[14] KAHN, Arthur B., "Topological sorting of large networks", Communications of the ACM 5, 1962, pp. 558–562.

[15] MEYERS, Glenford J., "The art of software testing", John Wiely & Sons, New York, 1979.

[16] BRITISH STANDARD 7925-1, "Software testing: vocabulary", 1998. [17] BINDER, Robert V., "Testing object-oriented systems: models, patterns

and tools", Addison-Wesley, 2000.

48