Baixe o app para aproveitar ainda mais
Prévia do material em texto
1 Universidade Estadual de Campinas Faculdade de Engenharia Elétrica e Computação Critérios de Teste de Software Orientado a Objetos Autores: Eder Ignatowicz e Liniquer K. Vieira Professor: Mario Jino 2 3 Sumário 1 Lista de Figuras ................................................................................................................................. 4 Lista de Tabelas ........................................................................................................................................ 5 1. Introdução ......................................................................................................................................... 6 2 Paradigmas de Programação ............................................................................................................. 8 3 Definições e Conceitos Básicos ...................................................................................................... 10 3.1 Classes ..................................................................................................................................... 10 3.2 Objetos .................................................................................................................................... 10 3.3 Encapsulamento ...................................................................................................................... 11 3.4 Herança ................................................................................................................................... 11 3.5 Polimorfismo ........................................................................................................................... 12 3.6 Clusters (pacote) ..................................................................................................................... 12 4 Tipos de Defeito em O.O ................................................................................................................ 14 4.1 Encapsulamento ...................................................................................................................... 14 4.2 Herança ................................................................................................................................... 14 4.3 Polimorfismo ........................................................................................................................... 15 5 Fases de teste ................................................................................................................................... 16 6 Teste Baseado em Especificação .................................................................................................... 18 6.1 Critérios de Teste Baseados na Estrutura do Diagrama de Casos de Uso .............................. 19 6.2 Teste Baseado em Programa ................................................................................................... 24 6.2.1 Teste de Mutação ................................................................................................................ 24 6.2.2 Grupos de operadores de mutação OO ............................................................................... 24 6.2.3 Estudo de caso ..................................................................................................................... 25 7 Ferramentas ..................................................................................................................................... 30 7.1 JUnit ........................................................................................................................................ 30 8 Conclusões ...................................................................................................................................... 32 9 Bibliografia ..................................................................................................................................... 33 4 1 Lista de Figuras Figura 1 - Clusters ................................................................................................................................... 13 Figura 2 - Componentes de um caso de uso ............................................................................................ 18 Figura 3 - Critério todas as comunicações [AC03] ................................................................................. 20 Figura 4 - Diagrama de casos de uso genérico [AC03] .......................................................................... 20 Figura 5 - Critério todos os inclusores[AC03] ....................................................................................... 21 Figura 6 - Critério todos os incluídos[AC03] ......................................................................................... 21 Figura 7 - Critério todas as inclusões ...................................................................................................... 21 Figura 8 - Diagrama de casos de uso genérico ........................................................................................ 22 Figura 9 - Critério todos os estendidos ................................................................................................... 22 Figura 10 - Critério todos os extensores ................................................................................................. 23 Figura 11 - Critério todas as extensões ................................................................................................... 23 Figura 12 - Comparação dos Critérios .................................................................................................... 23 Figura 13 - Diagrama de estudo de caso ................................................................................................. 26 Figura 14 - Mutação Inherit .................................................................................................................... 27 Figura 15 - Associate .............................................................................................................................. 27 Figura 16 – Member ................................................................................................................................ 28 Figura 17 – Access .................................................................................................................................. 29 Figura 18 - Exemplo JUnit ...................................................................................................................... 31 5 Lista de Tabelas Tabela 1 - Diferenças entre programação OO e procedimental. [Vicenzi] ............................................... 9 Tabela 2 - Relação entre fases de teste de programas procedimentais e OO. ......................................... 17 6 1. Introdução O teste de software pode ser visto como uma atividade de Verificação, Validação e Teste, e tem como objetivo encontrar o maior número possível de erros com uma quantidade de esforço gerenciável aplicada durante um intervalo de tempo realístico [Pre06]. Também é objetivo dos testes a construção de casos de teste capazes de cobrir diferentes classes de defeitos com o mínimo de tempo e esforço. É válido lembrar que o teste não mostra a ausência de defeitos em um software, apenas pode mostrar que defeitos estão presentes [Pre06]. Mesmo com a evolução constante dos métodos, técnicas e ferramentas de desenvolvimento de software, defeitos podem ser introduzidos, e somente uma atividade específica de teste pode descobrir a ocorrência de determinados defeitos no software. O teste pode ser realizado em diversas etapas de um projeto de softwaree consiste em ser adequado para cada uma dessas etapas [Pre06]. A cada técnica estão associados critérios de teste. Um critério é um predicado a ser satisfeito pelos casos de teste e pode ser utilizado para avaliar um conjunto de casos de teste. O critério fornece uma medida de cobertura dada pelo número de elementos requeridos que foram satisfeitos pelos casos de teste que pode ser utilizada para decidir se o programa foi devidamente testado e encerrar a atividade de teste. Através das diferentes formas de desenvolver um software são aplicadas determinadas técnicas de teste. Segundo Pressman [Pre06], o teste em orientação a objetos utiliza diferentes estratégias e táticas para atingir o objetivo quanto ao teste. Esse trabalho tem por objetivo principal apresentar as diversas técnicas e estratégicas utilizadas para realizar um teste de software em orientação a objetos (OO). Essa monografia segue organizada da seguinte forma: a Seção 2 descreve os conceitos de paradigmas de programação e as diferenças entre programação procedimental e orientada a obetos; a Seção 3 apresenta as principais definições e conceitos básicos da OO; a Seção 4 mostra os prováveis tipos de defeitos que podem ocorrer em função das novas características da OO; a Seção 5 descreve as diversas fases de teste e seus objetivos; a Seção 6 apresenta os principais critérios para a realização de testes baseando-se na especificação de um 7 programa OO; a Seção 7 mostra as ferramentas disponíveis para realização de testes em OO; finalmente, a Seção 8 faz as considerações finais deste trabalho. 8 2 Paradigmas de Programação Paradigma de programação é a forma com que o programador enxerga a solução de um problema, ou seja, a maneira com que o mesmo desenvolve uma aplicação ou um programa. Novos paradigmas de programação são desenvolvidos com o objetivo de suprir as deficiências dos paradigmas já existentes. No paradigma procedimental, a ênfase é dada ao desenvolvimento de procedimentos e a comunicação é realizada por passagem de dados, seu objetivo é estruturar um problema na forma de um conjunto de dados e procedimentos que manipulam esses dados. Esse paradigma possui uma grande desvantagem, pois quando grandes problemas precisam ser solucionados, a dependência entre os procedimentos e os dados torna-se muito grande, fazendo com que pequenas alterações em como os dados estão organizados podem levar a alterações na forma com que os procedimentos acessam esses dados. [VDDM07]. A fim de fornecer um mecanismo que isole os dados da forma como são manipulados surgiu o paradigma de orientação a objetos. A orientação a objetos agrupa os atributos e métodos em uma entidade estática denominada classe. Desse modo, em vez de estruturar o problema em termos de dados e procedimentos/funções, na orientação a objetos o desenvolvedor é incentivado a pensar em termos de classes e objetos que podem ser encarados como uma abstração de mais alto nível [VDDM07]. Pressman [Pre06] descreve que utilizando o paradigma OO o domínio do problema é caracterizado como um conjunto de objetos que possuem propriedades e comportamentos específicos e se comunicam por meio de mensagens. No entanto, Vincenzi et al. [VDDM07] alertam que o uso da orientação a objetos não garante a correção de um programa por si próprio, pois não impede que os desenvolvedores cometem enganos durante o desenvolvimento de um produto de software. Além disso, novos conceitos que surgiram com o paradigma OO apresentam-se como novos desafios no que diz respeito a teste de software, pois novos tipos de defeitos precisam ser considerados. [Pre06] Na tabela 1 podemos verificar as diferenças entre programação OO e procedimental e a evolução entre esses paradigmas. 9 Programação Orientada a Objetos Programação Estruturada Métodos Procedimentos e funções Variáveis de Instâncias Variáveis Mensagens Chamadas a procedimentos e funções Classes Tipos de dados definidos pelo usuário Heranças - Polimorfismo - Tabela 1 - Diferenças entre programação OO e procedimental. [Vicenzi] 10 3 Definições e Conceitos Básicos Neste capítulo são apresentados os conceitos básicos das principais características da orientação a objetos, sempre utilizando a linguagem Java como motivador. 3.1 Classes Uma classe é uma entidade estática que engloba atributos (ou dados) e métodos (ou funções-membro) que representam operações que podem ser realizadas sobre os dados. [VDDM07] No próximo exemplo, construímos uma classe chamada Carro, que mantém os dados relativos de um carro, a qual possui uma declaração de uma variável cor que é da classe Cor, uma variável List denominada pneus da classe Pneu e finalmente uma variável List denominada Roda da classe Roda. public class Carro { Cor cor; List<Pneu> pneus; List<Roda> rodas; } Para uma classe ser compilada, não é necessário a definição de atributos ou métodos. A declaração abaixo também é válida e compilada corretamente, mesmo que sem nenhum método ou atributo. public class Carro { } 3.2 Objetos Um objeto é uma instância de uma classe criada em tempo de execução. Cada objeto tem uma cópia dos dados existentes na classe e encapsula estado e comportamento. [VDDM07] 11 A instrução abaixo instancia um objeto da classe Carro, a qual possui todas as características da mesma. Carro astra = new Carro(); 3.3 Encapsulamento O encapsulamento é uma forte característica da programação orientada a objetos. É a capacidade que um objeto tem de impedir que outros objetos tenham acesso aos seus dados, garante a ocultação de informações na qual a interface e implementação de uma classe são separadas sintaticamente.[MTW] No exemplo abaixo podemos verificar a existência de uma classe pública Carro, a qual possui declarações de variáveis privadas, ou seja, essas variáveis só poderão ser acessadas por métodos contidos dentro da classe, o que garante o encapsulamento. public class Carro { private Cor cor; private List<Pneu> pneus; private List<Roda> rodas; } 3.4 Herança Através da herança novas classes podem ser criadas a partir de outras já existentes. Utilizando a herança, as classes são inseridas em uma hierarquia de especialização, de modo que uma classe mais especializada herda todas as propriedades das classes mais genéricas. A classe mais genérica dá-se o nome de superclasse (classe-pai), e a mais especializada dá-se o nome de subclasse (classe-filha). Através da herança, uma subclasse pode estender ou restringir as características herdadas da superclasse. [MTW] No próximo exemplo apresenta-se uma classe pública Carro que estende uma classe Automóvel. Logo a classe carro é uma subclasse da classe Automóvel (superclasse), e herda todas as características da mesma. public class Carro extends Automovel { } 12 3.5 Polimorfismo O termo polimorfismo representa a qualidade ou estado de um objeto ser capaz de assumir diferentes formas [VDDM07]. No exemplo abaixo inicialmente é instanciado um objeto Carro. Considerando que a classe Carro estende a classe Automóvel e toda classe do Java estende uma classe Object, logo podemos instanciar um objeto da classe Automovel recebendo um objeto do tipo Carro e um objeto do tipo Object recebendo um objeto do tipo Automóvel que nenhum problema ocorrerá. Carro carro = new Carro; Automovel auto = (Automovel) carro; Object obj = (Object) auto; 3.6 Clusters (pacote) Um conjunto de classes que cooperam entre si na implementaçãode determinadas funcionalidades [VDDM07]. As classes que constituem um cluster podem estar fortemente acopladas e trabalhar juntas para fornecer um comportamento unificado, ou ser independentes e fornecer diversos tipos de funções similares. [MTW] Em Java, uma classe Carro que pertence a um pacote br.testeorientacao possui o nome completo br.testeorientacao.Carro. Na figura 1 podemos verificar os pacotes conforme os diretórios de uma aplicação organizados conforme o seu relacionamento. 13 Figura 1 - Clusters 14 4 Tipos de Defeito em O.O Binder [Bin99] descreve que os tipos de defeitos que um desenvolvedor pode cometer são limitados pelas formas similares utilizadas de se expressar o que se tem na mente, bem como o que se utiliza para desenvolver. A programação orientada a objetos pode reduzir a ocorrência de alguns tipos de defeitos encontrados na programação procedimental, mas a partir da aplicação de suas novas características e conceitos, acaba por introduzir outros tipos. Segundo Pressman [Pre06], apesar de se ter o mesmo objetivo fundamental quanto ao teste, o teste em OO utiliza diferentes estratégias e táticas. Novos conceitos que surgiram com o paradigma OO apresentam-se como novos desafios no que diz respeito a teste de software, pois novos tipos de defeitos precisam ser considerados. São apresentados nessa seção, alguns dos defeitos mais prováveis de ocorrer dadas as novas características citadas na seção acima. Esse conteúdo foi extraído de Vincenzi et al. [VDDM07]. 4.1 Encapsulamento Através do encapsulamento, é possível controlar o acesso indesejável de atributos e métodos dentro de uma classe, pois se refere ao tratamento de visibilidade dos mesmos. O encapsulamento não contribui diretamente para a ocorrência de defeitos, mas apresenta-se como um obstáculo para as atividades de teste por não se ter conhecimento do estado de determinados atributos de um objeto em determinados momentos, atributos esses com visibilidade privada. Como solução pode ser aplicada a implementação de todos os métodos get e set a todos os atributos da classe [Har00], ou a utilização de recursos de reflexão computacional [RM98]. 4.2 Herança 15 Através da herança é possível compartilhar atributos e métodos de uma classe a uma nova classe gerada a partir dela. Permite a reusabilidade compartilhando características presentes em classes ancestrais. Contudo, Binder [Bin99] destaca que a herança enfraquece o encapsulamento e pode ser responsável pela criação de um risco de defeito similar ao uso de variáveis globais em programas procedimentais. Grandes hierarquias de herança podem também ser responsáveis por provocar enganos frequentes de desenvolvedores, gerando defeitos causadores de falhas. Portanto, é necessário ter a compreensão dos detalhes de implementação das classes ancestrais. 4.3 Polimorfismo O polimorfismo caracteriza a possibilidade de um mesmo nome ser utilizado para representar instâncias de várias classes. A aplicação do polimorfismo é muito comum em conjuntos hierárquicos formados. Porém o polimorfismo propicia riscos de possíveis defeitos no software como indecibilidade no acoplamento dinâmico, extensibilidade de hierarquias, containers heterogêneas e type casting [VDDM07]. Barbey e Strohmeier [BS94] descrevem alguns riscos de possíveis defeitos no software ocasionados pelo uso do polimorfismo: • Indecidibilidade no Acoplamento Dinâmico • Extensibilidade de Hierarquias • Containers Heterogêneos e Type Casting 16 5 Fases de teste A atividade de teste é dividida em várias fases com diferentes objetivos. Na literatura encontram-se diferentes variações quanto à divisão das fases de teste. Pressman [Pre06] define as seguintes fases: Teste de unidade: Visa identificar os erros de lógica e de implementação, corresponde a verificação da menor unidade do software. A técnica de teste estrutural e o teste de mutação são freqüentemente utilizados nessa fase. Teste de integração: Inicia-se após a fase de teste de unidade. Verifica a integração entre os módulos do software e busca os erros de interface entre os mesmos. A técnica de teste funcional é a mais utilizada durante essa fase. Teste de validação: Verifica se o produto está de acordo com a especificação dos requisitos do software. Idealizado a partir de uma serie de testes funcionais cujos resultados demonstram a conformidade aos requisitos. Teste de sistema: Exercita o software por completo. É composto por diferentes testes específicos os quais verificam se todos os elementos do software estão integrados e executam suas respectivas funções. Duas abordagens diferentes sobre as fases de teste de software OO são apresentadas a seguir. Harrold e Rothermel [HR94] definem o método como a menor unidade a ser testada. O teste de unidade corresponde ao teste intramétodo. O teste de integração é representado por testes intermétodos, Intraclasses e intraclasses. Já para Pressman [Pre06], apesar de considerar que as operações (métodos) de uma classe são a menor unidade testável, devido a essas operações poderem fazer parte de certo número de classes diferentes, a tática aplicada ao teste de unidade precisa modificar- se, não podendo ser a operação a base do teste unitário. O teste de sistema tem o mesmo significado e a mesma forma de aplicação para ambas as abordagens. A tabela 2 apresenta os tipos de teste que podem ser aplicados em cada uma das fases em programas orientados a objetos ou procedimentais, considerando o método ou a classe como menor unidade a ser testada. 17 Menor Unidade: Método Fase Teste Procedimental Teste Orientado a Objetos Unidade Intraprocedimenta l Intramétodo Integração Interprocedimenta l Intermétodo, Intraclasse e Interclasse Sistema Toda Aplicação Toda Aplicação Menor Unidade: Classe Fase Teste Procedimental Teste Orientado a Objetos Unidade Intraprocedimental Intramétodo, intermétodo e Intraclasse Integração Interprocedimental Interclasse Sistema Toda Aplicação Toda Aplicação Tabela 2 - Relação entre fases de teste de programas procedimentais e OO. 18 6 Teste Baseado em Especificação Esta seção apresenta o conjunto de critérios proposto por Chaim[AC03] para realização de testes baseando-se na especificação de um programa orientado a objetos. A especificação de um software é geralmente feita através da notação UML. A UML é uma linguagem visual, que tem como objetivo fornecer uma maneira comum de capturar e expressar relações, comportamentos e idéias de um nível mais alto na forma de notações. A UML visa expressar a modelagem de um software da maneira mais simples e eficiente possível [DP05]. Na linguagem UML os diagramas de caso de uso são utilizados para capturar as funcionalidades e requisitos do sistema. Estes diagramas descrevem a interação entre um usuário e um sistema. Um diagrama de caso de uso apresenta o relacionamento entre um ator e um caso de uso. Os dois principais componentes de um diagrama de caso de uso são os casos de uso e os atores (Figura 2) [DP05]. Um ator é uma representação de um usuário ou outro sistema que irá interagir com o sistema que está sendo modelado. Um caso de uso é uma visão externa do sistema que representa uma ação que o usuário possa executar, a fim de completar uma tarefa [DP05]. De acordo com Fowler [DP05], diagramas de caso de uso devem ser usados na maior parte dos projetos de software, pois são úteis na obtenção de requisitos e planejamento do projeto. Figura 2 - Componentes de umcaso de uso Chaim [AC03] define em seu trabalho uma série de critérios de teste para a geração de testes de cobertura em diagramas de casos de uso. Segundo [livro do jino] estes critérios almejam assegurar que casos de testes garantam a cobertura dos casos de uso utilizados 19 para modelar sistemas orientados a objetos. A idéia básica dos critérios é assegurar que interações entre casos de uso e entre atores sejam exercitadas de forma a exercitar todas as comunicações, inclusões e extensões presentes no diagrama. Desta forma alguns elementos estruturais foram escolhidos por Chaim[AC03] na criação dos critérios: os relacionamentos de comunicação entre atores e casos de uso e relacionamentos de inclusão e extensão entre casos de uso. A definição de critérios é útil pois estabelece um critério de quantificação e parada da atividade de testes. 6.1 Critérios de Teste Baseados na Estrutura do Diagrama de Casos de Uso Esta seção detalha cada critério estabelecido por Chaime detalhado em Carniello[AC03]. O primeiro tipo de critérios a ser definido neste trabalho é o critério baseado em relacionamentos de comunicação. Um relacionamento de comunicação é definido quando um caso de uso é iniciado diretamente por um ator. Desta forma os critérios baseados em relacionamento de comunicação são listados a seguir. 1. Critério todas as comunicações: Um conjunto de dados de teste T satisfaz o critério todas as comunicações se cada relacionamento de comunicação que inicia um caso de uso do diagrama D estiver sido exercitado pelo menos uma vez. Como a linguagem UML não apresenta uma notação especial para identificar qual ator inicia o caso de uso, é apresentada uma tarja especial sobre a relação de comunicação e esta é identificada através da leitura da especificação do caso de uso (Figura 3). 20 Figura 3 - Critério todas as comunicações [AC03] A segunda categoria de critérios são os critérios baseados no relacionamento de inclusão. Estes são aplicados aos casos de uso de um diagrama que mantém relacionamentos de inclusão entre si. Em um relacionamento de inclusão, o caso de uso é incluído e passa a fazer parte de outro caso de uso. Os critérios apresentados por Carniello[AC03] utilizam o diagrama genérico apresentado na Figura 4. Desta forma os critérios baseados em relacionamento de inclusão são listados a seguir. Figura 4 - Diagrama de casos de uso genérico [AC03] 1. Critério todos os inclusores: Um conjunto de dados de teste T satisfaz o critério todos os inclusores se cada caso de uso inclusor do diagrama D tiver exercitado pelo menos um caso de uso incluído (Figura 5). Este critério assegura que cada caso de uso inclusor tenha pelo menos exercitado um caso de uso incluído exercitando desta forma todos os casos de uso inclusores do diagrama. 21 Figura 5 - Critério todos os inclusores[AC03] 2. Critério todos os incluídos: Um conjunto de dados de teste T satisfaz o critério todos os incluídos se cada caso de uso incluído do diagrama D tiver sido exercitado pelo menos uma vez. A aplicação deste critério certifica o exercício de todos os casos de uso incluídos do diagrama (Figura 6). Figura 6 - Critério todos os incluídos[AC03] 3. Critério todas as inclusões: Um conjunto de dados de teste T satisfaz o critério todos as inclusões se cada relacionamento de inclusão entre dois casos de uso de D tiver sido exercitado pelo menos uma vez (Figura 7). Figura 7 - Critério todas as inclusões A terceira categoria de critérios são os critérios baseados no relacionamento de extensão e são aplicados aos casos de uso que mantém relacionamentos de extensão com outros casos de uso. 22 Os critérios apresentados por Carniello[AC03] utilizam o diagrama genérico apresentado na Figura 8. Desta forma os critérios baseados em relacionamento de extensão são listados a seguir. Figura 8 - Diagrama de casos de uso genérico 1. Critério todos os estendidos: Um conjunto de dados de teste T satisfaz o critério todos os estendidos se, para cada caso de uso estendido do diagrama D tiver exercitado pelo menos um caso de uso extensor (Figura 5). Este critério assegura que cada caso de uso extensor tenha pelo menos exercitado um caso de uso estendido exercitando desta forma todos os casos de uso extensores do diagrama. Figura 9 - Critério todos os estendidos 2. Critério todos os extensores: Um conjunto de dados de teste T satisfaz o critério todos os extensores se cada caso de uso extensor do diagrama D tiver sido exercitado pelo menos uma vez. A aplicação deste critério certifica o exercício de todos os casos de uso extensores do diagrama (Figura 10). 23 Figura 10 - Critério todos os extensores 3. Critério todas as extensões: Um conjunto de dados de teste T satisfaz o critério todos as extensões se cada relacionamento de extensão entre dois casos de uso de D tiver sido exercitado pelo menos uma vez (Figura 11). Figura 11 - Critério todas as extensões A Figura 12 apresenta uma comparação dos critérios apresentados. Vale salientar que alguns critérios não apresentados nesta monografia são combinações dos critérios anteriores. Figura 12 - Comparação dos Critérios 24 6.2 Teste Baseado em Programa De acordo com Jino[JIMADE] um problema do teste baseado em especificação é que este está sujeito às inconsistências decorrentes de uma especificação de má qualidade devido a esta ser a base da criação dos casos de teste. Esta má qualidade justifica-se pela forma descritiva e informal da linguagem UML e desta forma os requisitos derivados da especificação também são, de certa forma, descritivos e informais. Desta forma utilizam-se alguns critérios estruturais de fluxo de controle e de dados e critérios baseados na especificação. A próxima seção detalhará o teste de mutação em programas OO. 6.2.1 Teste de Mutação Teste de mutação é uma técnica popular para aferir qualidade de uma suíte de teste. Pequenas modificações sintáticas são introduzidas em um programa de forma a criar versões modificadas de um, conhecidas como mutantes, que servem como simuladores de erro. Tipicamente os mutantes contêm um pequeno defeito, consistente com a prática de desenvolvimento de uma equipe. Mutantes sobreviventes ao teste (isto é, para o qual não há teste na suíte que observe sua diferença de comportamento) indicam necessidade de novos casos de teste na suíte. A aplicação de teste de mutantes a softwares orientado a objetos tem como objetivo investigar resultados de operadores de mutação OO aplicados a uma especificação UML e ao código fonte. O grupo de operadores de mutação apresentados nesta seção e o estudo de caso são baseados no artigo de Anna Derezinska “Object-Oriented Mutation to Asses the Quality of Tests”. [AD] 6.2.2 Grupos de operadores de mutação OO No seu trabalho, Derezinska[AD]define alguns operadores de mutação OO que são listados a seguir: 25 1. Inherit (Inh) – Muda a classe base ou omite a relação de herança; 2. Associate (Ass) – Muda a associação entre classes; 3. Object (Obj) – Acessa um membro em outro objeto da mesma classe ou membro em outra classe da mesma hierarquia de herança; 4. Member (Mem) – Acessa dado ou função diferente do objeto; 5. Access (Acc) – Muda o especificador de acesso relacionados ao dado, às funções, ou às classes em um relacionamento de herança. O estudo de caso a seguir apresentará um estudo de caso aplicando cada um destes operadores. 6.2.3 Estudo de caso O diagrama da Figura13 apresenta um exemplo de diagrama UML para um modelo de carro. Baseado neste modelo serão gerados mutantes para cada operador de mutação proposto no trabalho de Derezinska [AD]. 26 Figura 13 - Diagrama de estudo de caso Como visto, o operador Inherit adiciona, omite ou muda a direção de um relacionamento de herança. Desta forma pode ser criado um mutante baseado no diagrama modificado abaixo; 27 Figura 14 - Mutação Inherit Com o operador Associate é possível modificar a direção de uma associação, modificar o relacionamento de agregação para associação como no diagrama da figura abaixo: Figura 15 - Associate 28 Através do operador Member, podemos chamar a função herdada da classe base, criar funções da mesma classe e acessar dados diferentes. Figura 16 – Member Com o operador de mutação Access podemos modificar uma função de public para protected ou uma herança de public para private por exemplo. 29 Figura 17 – Access De acordo com o artigo de Derezinska, os operadores Inherit, Associate e Access foram aplicados para especificações UML. Já os grupos Object e Member foram aplicados diretamente no código fonte. Contudo alguns mutantes foram invalidados diretamente pelo compilador. Com os mutantes equivalentes foram selecionados casos de teste baseado nos testes tradicionais. Atendendo o critério de seleção por mutantes o artigo obteve uma cobertura de 83% das funções e 85% das linhas de código. 30 7 Ferramentas Como a atividade de testes é propensa a erros e improdutiva, a eficaz aplicação de um critério de testes está condicionada a sua automatização. A utilização de ferramentas de testes propicia uma maior qualidade e produtividade de uma equipe de testes. A próxima seção apresentará uma visão geral do framework para automatização de testes Junit. 7.1 JUnit De acordo com Neto [AVPN], O JUnit é um framework open-source, criado por Eric Gamma e Kent Beck, com suporte à criação de testes automatizados na linguagem de programação Java. O framework foi criado com o objetivo de facilitar a criação de código para a automação de testes unitários. Com ele, pode ser verificado se cada método de uma classe funciona da forma esperada, exibindo possíveis erros ou falhas podendo ser utilizado tanto para a execução de baterias de testes como para extensão. A IBM[IBM] apresenta alguma das vantagens da utilização do JUnit: • Permite a criação rápida de código de teste possibilitando um aumento na qualidade do desenvolvimento e teste; • Amplamente utilizado pelos desenvolvedores da comunidade código-aberto, possuindo um grande número de exemplos; • Uma vez escritos, os testes são executados rapidamente sem que, para isso, seja interrompido o processo de desenvolvimento; • JUnit checa os resultados dos testes e fornece uma resposta imediata; • JUnit é livre e orientado a objetos. A figura apresenta um pequeno exemplo da utilização do JUnit sobre uma classe exemplo valor. 31 Figura 18 - Exemplo JUnit 32 8 Conclusões Foram apresentadas nesse trabalho as diferenças entre os paradigmas de programação procedimental e programação orientada a objetos, assim como os principais conceitos e definições básicas sobre OO. As fases de teste e as questões relativas às estratégias e técnicas de testes orientados a objetos foram descritas. Apresentou-se também a ferramenta de teste JUnit, tendo em vista a importância da automatização da atividade de teste. Como já visto, apesar da programação orientada a objetos trazer alguns benefícios também implica em ocasionar novas dificuldades para atividade de teste, pois suas novas características acabam por introduzir novos erros. Portanto, cada vez mais novos critérios de teste estão sendo desenvolvidos a partir daqueles já existentes para o teste de programas procedimentais. 33 9 Bibliografia [Pre06] R. S. Pressman. Engenharia de Software. McGraw-Hill, 2006. [Har00] M. J. Harrold. Testing: A roadmap. In In The Future of Software Engineering, pages 61_72. ACM Press, 2000. [RM98] A. C. A. Rosa and E. Martins. Using a Re_ective Architeture to Validade Object-Oriented Applications by Fault Injection. pages 76_80. Proc. of the Workshop on Re_ective Programming in C++ and Java, October 1998. [VDDM07] A. M. R. Vincenzi, A. L. S. Domingues, M. E. Delamaro, and J. C. Maldonado. Teste Orientado a Objetos e de Componentes. In M. C. Delamaro, J. C. Maldonado e M. Jino, Introdução ao Teste de Software, pages 119_174. Ed. Campus-Elsevier, Setembro 2007. [RdSSMM05] A. D. Rocha, A. da S. Simão, J. C. Maldonado, and P. C. Masiero. Uma ferramenta baseada em aspectos para o teste funcional de programas Java - ICMC/USP. XIX Simpósio Brasileiro de Engenharia de Software (SBES2005) - Universidade Federal de Uberlândia, 2005. [Bin99] R. V. Binder. Testing Object-Oriented Systems: Models, Patterns, and Tools, volume 1. Addison-Wesley LongMan, Inc., 1999. [HR94] M. J. Harrold and G. Rothermel. Performing data_ow testing on classes. In Proceedings of the SIGSOFT'94 Symposium on the Foundations of Software Engineering, pages 154_163, New Orleans, NO, USA, 1994. ACM Press. [BS94] The Problematics of Testing Object-Oriented Software. Stéphane Barbey, Alfred Strohmeier [Vicenzi] Auri Marcelo Rizzo Vicenzi Orientação a Objeto: Definição, Implementação e Análise de Recursos de Teste e Validação [MTW] G. C. Murphy, P. Townsend e P.S. Wong. Experiences with cluster and class testing. Communications of the ACM, 37(9):39-47, set. 1994. [AC03] A. Carniello, M. Jino, M. L. Chaim – Teste Baseado na Estrutura de caso de Uso [DP05] Dan Pilone and Neil Pitman. UML 2.0 in a nutshell. O’Reilly Media, Inc., 1 edition, 6 2005. 34 [JIMADE] Mário Eduardo Delamaro, José Carlos Maldonado, Mário Jino, Introdução ao Teste de Software [AD] Anna Derezinska “Object-Oriented Mutation to Asses the Quality of Tests” [AVPN] Aristides Vicente de Paula Neto – Criando testes com JUnit (UFPE) [IBM] Elliotte Rusty Harold, An early look at JUnit 4, Polytechnic University
Compartilhar