Instituto de Ciˆencias Matem´aticas e de Computa¸c˜ao ISSN - 0103-2585 INTRODUC¸A˜O AO TESTE DE SOFTWARE COM FERRAMENTAS PARA JAVA (Vers˜ao 2016-01) Auri Marcelo Rizzo Vincenzi Pedro Henrique Dias Valle Jacson Rodrigues Barbosa Cristiane Aparecida Lana M´arcio Eduardo Delamaro Jos´e Carlos Maldonado No 65 ´ NOTAS DIDATICAS DO ICMC Sa˜o Carlos OUTUBRO/2016 Introdu¸ca˜o ao Teste de Software com Ferramentas para Java∗ (Vers˜ao 2016-01) Auri Marcelo Rizzo Vincenzi1, Jacson Rodrigues Barbosa2 Pedro Henrique Dias Valle2, M´arcio Eduardo Delamaro2 Cristiane Aparecida Lana2, Jos´e Carlos Maldonado2 1Universidade Federal de Sa˜o Carlos – DC/UFSCar [email protected] 2Universidade de S˜ao Paulo — ICMC/USP [email protected], [email protected] [email protected], [email protected] [email protected] Resumo As exigˆencias por software com maior qualidade tˆem motivado a definic¸˜ao de m´etodos e t´ecnicas para o desenvolvimento de softwares que atinjam os padr˜oes de qualidade impostos. Com isso, o interesse pela atividade de teste de software aumentou nos u´ltimos anos. V´arios pesquisadores investigam os diferentes crit´erios de teste, buscando obter uma estrat´egia de teste com baixo custo de aplicac¸˜ao, mas ao mesmo tempo, com grande capacidade em revelar a presen¸ca de defeitos. O objetivo desta nota did´atica ´e apresentar os aspectos te´oricos e pr´aticos relaciona- dos `a atividade de teste de software. Uma s´ıntese das t´ecnicas de teste funcional, estrutural e baseada em erros, bem como de crit´erios de teste pertencentes a cada uma delas, ser˜ao apresentados. Fatores utilizados na compara¸c˜ao e avalia¸c˜ao de crit´erios de teste de software (custo, efic´acia e dificuldade de satisfac¸˜ao) tamb´em ser˜ao abordados, tanto do ponto de vista te´orico como emp´ırico. A importˆancia da automatiza¸c˜aodaatividadedetesteser´adestacada,caracterizando-seosesfor¸cosda comunidade cient´ıfica nessa dire¸c˜ao. Dar-se-´a ˆenfase ao crit´erio de teste An´alise de Mutantes apresentando uma revis˜ao hist´orica do seu surgimento e desenvolvimento. Aspectos te´oricos e pr´aticos de sua utilizac¸˜ao ser˜ao abordados e as estrat´egias que procuram minimizar o custo de aplica¸c˜ao desse crit´erio ser˜ao discutidas. A ati- vidade de teste e os problemas pertinentes `a ela ser˜ao ilustrados utilizando-se as ferramentas JaBUTi e JaCoCo para crit´erios estruturais e MuJava e PIT Mutation Testing para teste de muta¸c˜ao. Identificam-se ainda outras iniciativas e esfor¸cos da comunidade para a automatiza¸c˜ao desses crit´erios de teste. ∗Partes deste trabalho foram extra´ıdas de [1] e [2]. 1 1 Introdu¸c˜ao A Engenharia de Software evoluiu significativamente nas u´ltimas d´ecadas procurando estabelecer t´ecnicas, crit´erios, m´etodos e ferramentas para a produ¸ca˜o de software, em consequˆencia da crescente utiliza¸ca˜o de sistemas baseados em computa¸ca˜o em pratica- mente todas as a´reas da atividade humana, o que provoca uma crescente demanda por qualidade e produtividade, tanto do ponto de vista do processo de produ¸ca˜o como do ponto de vista dos produtos gerados. A Engenharia de Software pode ser definida como uma disciplina que aplica os princ´ıpios de engenharia com o objetivo de produzir software de alta qualidade a baixo custo [3]. Por meio de um conjunto de etapas que envolvem o desenvolvimentoeaplica¸ca˜odem´etodos, t´ecnicaseferramentas, aEngenhariadeSoftware oferece meios para que tais objetivos possam ser alcan¸cados. O processo de desenvolvimento de software envolve uma s´erie de atividades nas quais, apesar das t´ecnicas, m´etodos e ferramentas empregados, erros no produto ainda podem ocorrer. Atividades agregadas sob o nome de Garantia de Qualidade de Software sa˜o introduzidas ao longo de todo o processo de desenvolvimento, entre elas atividades de VV&T – Verifica¸ca˜o, Valida¸c˜ao e Teste, com o objetivo de minimizar a ocorrˆencia de erros e riscos associados. Dentre as t´ecnicas de verifica¸c˜ao e valida¸ca˜o, a atividade de teste ´e uma das mais utilizadas, constituindo-se em um dos elementos para fornecer evidˆencias da confiabilidade do software em complemento a outras atividades, como por exemplo o uso de reviso˜es e de t´ecnicas formais e rigorosas de especifica¸ca˜o e de verifica¸ca˜o [4]. A atividade de teste consiste de uma an´alise dinˆamica do produto e ´e uma atividade relevante para a identifica¸ca˜o e elimina¸ca˜o de erros que persistem. Do ponto de vista de qualidade do processo, o teste sistem´atico ´e uma atividade fundamental para a ascens˜ao ao N´ıvel 3 do Modelo CMM do Software Engineering Institute — SEI [5]. Ainda, o conjunto de informa¸c˜ao oriundo da atividade de teste ´e significativo para as atividades de depura¸ca˜o, manuten¸c˜ao e estimativa de confiabilidade de software [3,6–9]. Salienta-se que aatividadedetestetemsidoapontadacomoumadasmaisonerosasnodesenvolvimentode software [3,10,11]. Apesar deste fato, Myers et al. observam que aparentemente conhece- se muito menos sobre teste de software do que sobre outros aspectos e/ou atividades do desenvolvimento de software [10]. O teste de produtos de software envolve basicamente quatro etapas: planejamento de testes, projeto de casos de teste, execuc¸˜ao e avaliac¸˜ao dos resultados dos testes [3,4,10,11]. Essasatividadesdevemserdesenvolvidasaolongodopro´prioprocessodedesenvolvimento de software, e em geral, concretizam-se em trˆes fases de teste: de unidade, de integra¸ca˜o e de sistema. O teste de unidade concentra esforc¸os na menor unidade do projeto de software, ou seja, procura identificar erros de l´ogica e de implementa¸ca˜o em cada m´odulo do software, separadamente. O teste de integra¸ca˜o ´e uma atividade sistem´atica aplicada durante a integrac¸˜ao da estrutura do programa visando a descobrir erros associados `as interfacesentreosm´odulos; oobjetivo´e,apartirdosm´odulostestadosnon´ıveldeunidade, construir a estrutura de programa que foi determinada pelo projeto. O teste de sistema, realizado ap´os a integra¸ca˜o do sistema, visa a identificar erros de fun¸co˜es e caracter´ısticas de desempenho que na˜o estejam de acordo com a especifica¸c˜ao [3]. Um ponto crucial na atividade de teste, independentemente da fase, ´e o projeto e/ou a avalia¸ca˜o da qualidade de um determinado conjunto de casos de teste T utilizado para o teste de um produto P, dado que, em geral, ´e impratic´avel utilizar todo o dom´ınio de dados de entrada para avaliar os aspectos funcionais e operacionais de um produto 2 em teste. O objetivo ´e utilizarem-se casos de teste que tenham alta probabilidade de encontrar a maioria dos defeitos com um m´ınimo de tempo e esfor¸co, por questo˜es de produtividade. Segundo Myers [10], o principal objetivo do teste de software ´e revelar a presen¸ca de erros no produto. Portanto, o teste bem sucedido ´e aquele que consegue determinar casos de teste para os quais o programa em teste falhe. Tem-se observado que a pr´opria atividade de projeto de casos de teste ´e bastante efetiva em evidenciar a presen¸ca de defeitos de software. Em geral, os crit´erios de teste de software s˜ao estabelecidos, basicamente, a partir de trˆes t´ecnicas: a funcional, a estrutural e a baseada em erros. Na t´ecnica funcional, os crit´erios e requisitos de teste sa˜o estabelecidos a partir da func¸˜ao de especifica¸ca˜o do software; na t´ecnica estrutural, os crit´erios e requisitos sa˜o derivados essencialmente a partir das caracter´ısticas de uma particular implementa¸ca˜o em teste; e, na t´ecnica baseada em erros, os crit´erios e requisitos de teste s˜ao oriundos do conhecimento sobre erros t´ıpicos cometidos no processo de desenvolvimento de software. Observa-se tamb´em o estabelecimento de crit´erios de gerac¸˜ao de sequ¨ˆencias de teste baseados em M´aquinas de Estados Finito [12,13]. Esses u´ltimos tˆem sido aplicados no contexto de valida¸ca˜o e teste de sistemas reativos e de sistemas orientados a objetos [14–22]. Segundo Howden [23], o teste pode ser classificado de duas maneiras: teste baseado em especifica¸c˜ao (specification-based testing) e teste baseado em programa (program- based testing). Estre trabalho tem foco no teste baseado em programas e na utiliza¸ca˜o dos crit´erios de teste das t´ecnicas funcional, estrutural e baseada em defeitos. Os crit´erios da t´ecnica funcional ou caixa-preta tˆem como objetivo determinar se o programa satisfaz aos requisitos funcionais e n˜ao-funcionais que foram especificados. O problema ´e que, em geral, a especifica¸ca˜o existente ´e informal e, desse modo, a deter- mina¸ca˜o da cobertura total da especifica¸ca˜o que foi obtida por um dado conjunto de casos de teste tamb´em ´e informal [24]. Entretanto, os crit´erios funcionais podem ser utili- zados em qualquer contexto (procedimental ou orientado a objetos) e em qualquer fase de teste sem a necessidade de modifica¸ca˜o. Exemplos desses crit´erios sa˜o: particionamento em classe de equivalˆencia [3], an´alise do valor limite [3], grafo de causa-efeito [3] e teste baseado em estado [16,19]. Ao contr´ario, os crit´erios da t´ecnica estrutural ou caixa-branca requer a inspe¸c˜ao do co´digo fonte e a sele¸c˜ao de casos de teste que exercitem partes do c´odigo e na˜o de sua especifica¸ca˜o [24]. ´ E importante ressaltar que as t´ecnicas de teste devem ser vistas como complementares e a questa˜o esta´ em como utiliza´-las de forma que as vantagens de cada uma sejam melhor exploradas em uma estrat´egia de teste que leve a uma atividade de teste de boa qualidade, ou seja, eficaz e de baixo custo. As t´ecnicas e crit´erios de teste fornecem ao desenvolve- dor uma abordagem sistema´tica e teoricamente fundamentada, al´em de constitu´ırem um mecanismo que pode auxiliar a avaliar a qualidade e a adequa¸ca˜o da atividade de teste. Crit´erios de teste podem ser utilizados tanto para auxiliar na gera¸c˜ao de conjunto de casos de teste como para auxiliar na avalia¸ca˜o da adequa¸ca˜o desses conjuntos. Dada a diversidade de crit´erios estabelecidos [3,4,10,11,25–35] e reconhecido o cara´ter complementar das t´ecnicas e crit´erios de teste [35–44], um ponto crucial que se coloca nessa perspectiva ´e a escolha e/ou a determina¸ca˜o de uma estrat´egia de teste, que em u´ltima an´alise passa pela escolha de crit´erios de teste, de forma que as vantagens de cada um desses crit´erios sejam combinadas objetivando uma atividade de teste de maior qualidade. Estudos teo´ricos e emp´ıricos de crit´erios de teste s˜ao de extrema relevˆancia 3 para a formac¸˜ao desse conhecimento, fornecendo subs´ıdios para o estabelecimento de estrat´egias de baixo custo e alta efica´cia. Identificam-se diversos esfor¸cos da comunidade cient´ıfica nessa dire¸c˜ao [35,41–43,45–51]. Fundamental se faz o desenvolvimento de ferramentas de teste para o suporte `a ati- vidade de teste propriamente dita, uma vez que essa atividade ´e muito propensa a erros, al´em de improdutiva, se aplicada manualmente, bem como para dar apoio a estudos emp´ıricos que visem a avaliar e a comparar os diversos crit´erios de teste. Assim, a dis- ponibilidade de ferramentas de teste propicia maior qualidade e produtividade para as atividades de teste. Observam-se na literatura esfor¸cos da comunidade cient´ıfica nessa dire¸ca˜o [11,35,43,52–67]. Pode-se observar que os crit´erios baseados em ana´lise de fluxo de dados [27,29–33] e o crit´erio Ana´lise de Mutantes (Mutation Analysis) [25,34,68] tˆem sido fortemente investigados por diversos pesquisadores em diferentes aspectos [7,37,38,41,42,44,46, 50,57,59,69–79]. Resultados desses estudos fornecem evidˆencias de que esses crit´erios, hoje investigados fundamentalmente no meio acadˆemico, a`s vezes em cooperac¸˜ao com a indu´stria, podem, em m´edio prazo, constituir o estado da pr´atica em ambientes de produ¸ca˜odesoftware. Umaforteevidˆencianessadirec¸˜ao´eoesforc¸oalocadopelaTelcordia Technologies (USA) no desenvolvimento da xSuds [80], um ambiente que apoia a aplicac¸˜ao de crit´erios baseados em ana´lise de fluxo de controle e de dados em programas C e C++. De uma maneira geral, pode-se classificar as contribui¸c˜oes para a a´rea de Teste de Software em: Estudos Teo´ricos, Estudos Emp´ıricos e Desenvolvimento de Ferramentas. Este texto aborda esses trˆes aspectos, dando-se ˆenfase a estudos teo´ricos e emp´ıricos de crit´erios baseados em ana´lise de fluxo de dados e do crit´erio Ana´lise de Mutantes para o testedeprogramasemn´ıveldeunidade,assimcomoasferramentasqueapoiamaaplica¸ca˜o desses crit´erios. Com esse objetivo em mente, o texto est´a organizado da seguinte forma: na Se¸ca˜o 2 s˜ao introduzidos a terminologia e os conceitos b´asicos pertinentes `a atividade de teste. Na Sec¸˜ao 3 s˜ao apresentados os crit´erios de teste mais difundidos das t´ecnicas funcional, estrutural e baseada em erros e ilustrados os principais aspectos operacionais das ferramentas JaBUTi, JaCoCo, MuJava e PIT Mutation Testing ou apenas PIT. Na Se¸ca˜o 4 sa˜o apresentadas as concluso˜es e perspectivas de trabalhos futuros. 2 Terminologia e Conceitos B´asicos A IEEE tem realizado v´arios esforc¸os de padroniza¸c˜ao, entre eles para padronizar a terminologia utilizada no contexto de Engenharia de Software. O padr˜ao IEEE nu´mero 610.12-1990 [81] diferencia os termos: defeito (fault) – passo, processo ou defini¸ca˜o de da- dos incorreto, como por exemplo, uma instru¸ca˜o ou comando incorreto; engano (mistake) – a¸ca˜o humana que produz um resultado incorreto, com por exemplo, uma a¸ca˜o incorreta tomadapeloprogramador; erro(error)–diferen¸caentreovalorobtidoeovaloresperado, ou seja, qualquer estado intermedi´ario incorreto ou resultado inesperado na execu¸ca˜o do programa constitui um erro; e falha (failure) – produ¸c˜ao de uma sa´ıda incorreta com rela¸ca˜o `a especifica¸ca˜o. Neste texto, os termos engano, defeito e erro sera˜o referencia- dos como erro (causa) e o termo falha (consequ¨ˆencia) a um comportamento incorreto do programa. De uma forma geral, os erros s˜ao classificados em: erros computacionais – o erro provoca uma computa¸ca˜o incorreta mas o caminho executado (sequ¨ˆencias de comandos) ´e igual ao caminho esperado; e erros de dom´ınio – o caminho efetivamente executado ´e diferente do caminho esperado, ou seja, um caminho errado ´e selecionado. 4 A atividade de teste ´e permeada por uma s´erie de limita¸co˜es [23,31,82–84]. Em geral, os seguintes problemas sa˜o indecid´ıveis: dados dois programas, se eles sa˜o equivalentes; dados duas sequ¨ˆencias de comandos (caminhos) de um programa, ou de programas di- ferentes, se eles computam a mesma fun¸ca˜o; e dado um caminho se ele ´e executa´vel ou na˜o, ou seja, se existe um conjunto de dados de entrada que levam a` execu¸c˜ao desse cami- nho. Outra limita¸ca˜o fundamental´e a corre¸c˜ao coincidente – o programa pode apresentar, coincidentemente, um resultado correto para um item particular de um dado d ∈ D, ou seja, um particular item de dado ser executado, satisfazer a um requisito de teste e n˜ao revelar a presen¸ca de um erro. Diz-se que um programa P com dom´ınio de entrada D ´e correto com respeito a uma especifica¸ca˜o S se S(d) = P∗(d) para qualquer item de dado d pertencente a D, ou seja, se o comportamento do programa esta´ de acordo com o comportamento esperado para todos os dados de entrada. Dados dois programas P e P , se P∗(d) = P∗(d), para 1 2 1 2 qualquerd ∈ D, diz-sequeP eP sa˜oequivalentes. Notestedesoftware, pressupo˜e-sea 1 2 existˆencia de um ora´culo – o testador ou algum outro mecanismo – que possa determinar, para qualquer item de dado d ∈ D, se S(d) = P∗(d), dentro de limites de tempo e esfor¸cos razoa´veis. Um ora´culo decide simplesmente se os valores de sa´ıda sa˜o corretos. Sabe-se que o teste exaustivo ´e impratica´vel, ou seja, testar para todos os elementos poss´ıveis do dom´ınio de entrada ´e, em geral, caro e demanda muito mais tempo do que o dispon´ıvel. Ainda, deve-se salientar que na˜o existe um procedimento de teste de prop´osito geral que possa ser usado para provar a corretitude de um programa. Apesar de na˜o ser poss´ıvel, atrav´es de testes, provar que um programa est´a correto, os testes, se conduzidos sistema´tica e criteriosamente, contribuem para aumentar a confianc¸a de que o software desempenha as fun¸co˜es especificadas e evidenciar algumas caracter´ısticas m´ınimas do ponto de vista da qualidade do produto. Assim, duas questo˜es s˜ao chaves na atividade de teste: “Como os dados de teste devem ser selecionados?” e “Como decidir se um programa P foi suficientemente testado?”. Crit´erios para selecionar e avaliar conjuntos de casos de teste s˜ao fundamentais para o sucesso da atividade de teste. Tais crit´erios devem fornecer indica¸ca˜o de quais casos de testedevemserutilizadosdeformaaaumentaraschancesderevelarerrosou,quandoerros na˜o forem revelados, estabelecer um n´ıvel elevado de confian¸ca na correc¸˜ao do programa. Um caso de teste consiste de um par ordenado (d,S(d)), no qual d ∈ D e S(d) ´e a respectiva sa´ıda esperada. Dados um programa P e um conjunto de casos de teste T, definem-se: • Crit´erio de Adequa¸c˜ao de Casos de Teste: predicado para avaliar T no teste de P; • M´etodo de Sele¸c˜ao de Casos de Teste: procedimento para escolher casos de teste para o teste de P. Existe uma forte correspondˆencia entre m´etodos de sele¸c˜ao e crit´erios de adequac¸˜ao de casos de teste pois, dado um crit´erio de adequa¸ca˜o C, existe um m´etodo de sele¸c˜ao MC que estabelece: selecione T tal que T seja adequado a C. De forma an´aloga, dado um m´etodo de sele¸ca˜o M, existe um crit´erio de adequa¸ca˜o CM que estabelece: T ´e adequado se foi selecionado de acordo com M. Desse modo, costuma-se utilizar o termo “crit´erio de adequa¸ca˜o de casos de teste” (ou simplesmente crit´erio de teste) tamb´em para designar m´etodo de selec¸˜ao [4,55]. Dados P, T e um crit´erio C, diz-se que o conjunto de 5 casos de teste T ´e C-adequado para o teste de P se T preencher os requisitos de teste estabelecidos pelo crit´erio C. Outra questa˜o relevante nesse contexto ´e dado um conjunto T C -adequado, qualseriaumcrit´eriodetesteC quecontribuiriaparaaprimorarT? Essa 1 2 questa˜o tem sido investigada tanto em estudos teo´ricos quanto em estudos emp´ıricos. Em geral, pode-se dizer que as propriedades m´ınimas que devem ser preenchidas por um crit´erio de teste C sa˜o: 1. garantir, do ponto de vista de fluxo de controle, a cobertura de todos os desvios condicionais; 2. requerer, do ponto de vista de fluxo de dados, ao menos um uso de todo resultado computacional; e 3. requerer um conjunto de casos de teste finito. As vantagens e desvantagens de crit´erios de teste de software podem ser avaliadas atrav´es de estudos teo´ricos e emp´ıricos. Do ponto de vista de estudos teo´ricos, esses estudos tˆem sido apoiados principalmente por uma rela¸c˜ao de inclusa˜o e pelo estudo da complexidade dos crit´erios [31,83,85]. A rela¸ca˜o de inclusa˜o estabelece uma ordem parcial entre os crit´erios, caracterizando uma hierarquia entre eles. Diz-se que um crit´erio C inclui um crit´erio C se para qualquer programa P e qualquer conjunto de casos de 1 2 testeT C -adequado, T fortamb´emC -adequadoeexistirumprogramaP eumconjunto 1 1 1 2 T C -adequado que n˜ao seja C -adequado. A complexidade ´e definida como o nu´mero 2 2 1 ma´ximo de casos de teste requeridos por um crit´erio, no pior caso. No caso dos crit´erios baseadosemfluxodedados,essestˆemcomplexidadeexponencial,oquemotivaacondu¸c˜ao de estudos emp´ıricos para determinar o custo de aplica¸ca˜o desses crit´erios do ponto de vista pr´atico. Mais recentemente, alguns autores tˆem abordado do ponto de vista teo´rico a questa˜o de efica´cia de crit´erios de teste, e tˆem definido outras rela¸co˜es, que captem a capacidade de revelar erros dos crit´erios de teste [37,38,86,87]. Do ponto de vista de estudos emp´ıricos, trˆes aspectos costumam ser avaliados: custo, efica´cia e strength (ou dificuldade de satisfa¸ca˜o) [40,41,46,73,78,88]. O fator custo reflete o esfor¸co necess´ario para que o crit´erio seja utilizado; em geral ´e medido pelo nu´mero de casos de teste necessa´rios para satisfazer o crit´erio. A efica´cia refere-se a` capacidade que um crit´erio possui de detectar a presen¸ca de erros. O fator strength refere-se a` probabilidade de satisfazer-se um crit´erio tendo sido satisfeito um outro crit´erio [41]. Umaatividademuitocitadanacondu¸ca˜oeavalia¸c˜aodaatividadedeteste´eaan´alisede cobertura, que consiste basicamente em determinar o percentual de elementos requeridos por um dado crit´erio de teste que foram exercitados pelo conjunto de casos de teste utilizado. A partir dessa informac¸˜ao o conjunto de casos de teste pode ser aprimorado, acrescentando-se novos casos de teste para exercitar os elementos ainda na˜o cobertos. Nessa perspectiva, ´e fundamental o conhecimento sobre as limita¸co˜es teo´ricas inerentes `a atividade de teste, pois os elementos requeridos podem ser na˜o execut´aveis, e em geral, determinar a n˜ao executabilidade de um dado requisito de teste envolve a participa¸ca˜o do testador. 3 T´ecnicas e Crit´erios de Teste Conforme mencionado anteriormente, para se conduzir e avaliar a qualidade da ativi- dade de teste tˆem-se as t´ecnicas de teste funcional, estrutural e baseada em erros. Tais 6 t´ecnicas diferenciam-se pela origem da informa¸ca˜o utilizada na avalia¸c˜ao e constru¸ca˜o dos conjuntos de casos de teste [4]. Neste texto apresentam-se com mais detalhes as duas u´ltimas t´ecnicas, mais especificamente os crit´erios Potenciais-Usos [4], o crit´erio Ana´lise de Mutantes [34], e as ferramentas de suporte JaBUTi [89], JaCoCo [90], MuJava [91], e PIT [92]. Atrav´es desses crit´erios, ilustram-se os principais aspectos pertinentes `a ati- vidade de teste de cobertura de software. Para propiciar uma vis˜ao mais abrangente, apresentam-se primeiramente uma vis˜ao geral da t´ecnica funcional e os crit´erios mais co- nhecidos dessa t´ecnica. O programa identifier (Figura 1) sera´ utilizado para facilitar a ilustra¸ca˜o dos conceitos desenvolvidos neste texto. 3.1 T´ecnica Funcional O teste funcional tamb´em´e conhecido como teste caixa preta [93] pelo fato de tratar o software como uma caixa cujo conteu´do ´e desconhecido e da qual s´o ´e poss´ıvel visualizar o lado externo, ou seja, os dados de entrada fornecidos e as respostas produzidas como sa´ıda. Nat´ecnicadetestefuncionals˜aoverificadasasfun¸c˜oesdosistemasemsepreocupar com os detalhes de implementa¸ca˜o. O teste funcional envolve dois passos principais: identificar as fun¸c˜oes que o software deverealizarecriarcasosdetestecapazesdechecarseessasfun¸co˜esesta˜osendorealizadas pelo software [94]. As func¸˜oes que o software deve possuir s˜ao identificadas a partir de sua especifica¸ca˜o. Assim, uma especifica¸ca˜o bem elaborada e de acordo com os requisitos do usu´ario ´e essencial para esse tipo de teste. Alguns exemplos de crit´erios de teste funcional s˜ao [94]: • Particionamento em Classes de Equivalˆencia: a partir das condi¸co˜es de en- trada de dados identificadas na especifica¸ca˜o, divide-se o dom´ınio de entrada de um programa em classes de equivalˆencia v´alidas e inv´alidas. Em seguida seleciona-se o menor nu´mero poss´ıvel de casos de teste, baseando-se na hipo´tese que um elemento de uma dada classe seria representativo da classe toda, sendo que para cada uma das classes inva´lidas deve ser gerado um caso de teste distinto. O uso de particiona- mento permite examinar os requisitos mais sistematicamente e restringir o nu´mero de casos de teste existentes. Alguns autores tamb´em consideram o dom´ınio de sa´ıda do programa para estabelecer as classes de equivalˆencia. • An´alise do Valor Limite: ´e um complemento ao crit´erio Particionamento em Classes de Equivalˆencia, sendo que os limites associados a`s condi¸co˜es de entrada s˜ao exercitados de forma mais rigorosa; ao inv´es de selecionar-se qualquer elemento de uma classe, os casos de teste sa˜o escolhidos nas fronteiras das classes, pois nesses pontos se concentra um grande nu´mero de erros. O espa¸co de sa´ıda do programa tamb´em ´e particionado e sa˜o exigidos casos de teste que produzam resultados nos limites dessas classes de sa´ıda. • Grafo de Causa-Efeito: os crit´erios anteriores n˜ao exploram combina¸co˜es das condi¸co˜es de entrada. Este crit´erio estabelece requisitos de teste baseados nas poss´ıveis combina¸co˜es das condi¸co˜es de entrada. Primeiramente, s˜ao levantadas as poss´ıveis condi¸co˜es de entrada (causas) e as poss´ıveis a¸co˜es (efeitos) do programa. A seguir ´e constru´ıdo um grafo relacionando as causas e efeitos levantados. Esse grafo ´e convertido em uma tabela de decisa˜o a partir da qual s˜ao derivados os casos de teste. 7 /**************************************************************************************** Identifier.java ESPECIFICACAO: O programa deve determinar se um identificador eh ou nao valido em ’Silly Pascal’ (uma estranha variante do Pascal). Um identificador valido deve comecar com uma letra e conter apenas letras ou digitos. Alem disso, deve ter no minimo 1 caractere e no maximo 6 caracteres de comprimento ****************************************************************************************/ public class Identifier { public boolean validateIdentifier(String s) { /* 1 */ char achar; /* 1 */ boolean valid_id = false; /* 1 */ achar = s.charAt(0); /* 1 */ valid_id = valid_s(achar); /* 1 */ if (s.length() > 1) { /* 2 */ achar = s.charAt(1); /* 2 */ int i = 1; /* 3 */ while (i < s.length() - 1) { /* 4 */ achar = s.charAt(i); /* 4 */ if (!valid_f(achar)){ /* 5 */ valid_id = false;} /* 6 */ i++; /* 6 */ } /* 6 */ } /* 7 */ if (valid_id && (s.length() >= 1) & &(s.length() < 6)) /* 8 */ return true; /* 9 */ else /* 9 */ return false; /* 10 */ } public boolean valid_s(char ch) { /* 1 */ if (((ch >= ’A’) && (ch <= ’Z’)) || ((ch >= ’a’) && (ch <= ’z’))) /* 2 */ return true; /* 3 */ else /* 4 */ return false; /* 5 */ } public boolean valid_f(char ch) { /* 1 */ if (((ch >= ’A’) && (ch <= ’Z’)) || ((ch >= ’a’) && (ch <= ’z’)) || ((ch >= ’0’) && (ch <= ’9’))) /* 2 */ return true; /* 3 */ else /* 4 */ return false; /* 5 */ } /* 10 */} Figura 1: Programa exemplo: identifier (cont´em ao menos um erro). 8 Um dos problemas relacionado aos crit´erios funcionais ´e que muitas vezes a especi- fica¸ca˜o do programa ´e feita de modo descritivo e na˜o formal. Dessa maneira, os requisitos de teste derivados de tais especifica¸co˜es s˜ao tamb´em, de certa forma, imprecisos e infor- mais. Como consequˆencia, tem-se dificuldade em automatizar a aplica¸c˜ao de tais crit´erios, que ficam, em geral, restritos `a aplica¸c˜ao manual. Por outro lado, para a aplicac¸˜ao desses crit´erios ´e essencial apenas que se identifiquem as entradas, a fun¸ca˜o a ser computada e a sa´ıda do programa, o que os tornam aplica´veis praticamente em todas fases de teste (unidade, integra¸ca˜o e sistema) [35]. Offutt e Irvine [95], por exemplo, propo˜em a utilizac¸˜ao do M´etodo de Parti¸ca˜o- Categoria (Category-Partition Method) no teste de programas OO. Segundo os autores, existe muita preocupa¸c˜ao no desenvolvimento de novas t´ecnicas e crit´erios para o teste de programas OO sem que se tenha investigado a efic´acia das t´ecnicas e crit´erios tradicionais nessecontexto. OffutteIrvinecomentamquediversosautoresachamqueutilizarsomente t´ecnicas de teste tradicionais´einsuficiente para testar programas OO mas, segundo Offutt e Irvine, somente um autor da´ alguma evidˆencia desse fato e suas evidˆencias ainda na˜o sa˜o conclusivas. Nesse contexto eles propo˜em o uso de um crit´erio de teste baseado em especifica¸ca˜o (que, teoricamente ´e aplic´avel tanto para programas procedimentais quanto OO, indistintamente) no teste de programas OO. Outro crit´erio baseado em especifica¸ca˜o ´e o Particionamento em Classes de Equi- valˆencia. A t´ıtulo de ilustra¸ca˜o, considerando o programa identifier e o crit´erio Parti- cionamento em Classes de Equivalˆencia, sa˜o identificadas na Tabela 1 as condic¸˜oes de entrada e classes de equivalˆencia v´alidas e inv´alidas. A partir dessas classes o seguinte conjunto de casos de teste poderia ser elaborado: T = {(a1, Va´lido), (2B3, Inva´lido), 0 (Z-12, Inva´lido), (A1b2C3d, Inva´lido)}. De posse do conjunto T , seria natural indagar se 0 esse conjunto exercita todos os comandos ou todos os desvios de fluxo de controle de uma dada implementa¸ca˜o. Usualmente, lanc¸a-se ma˜o de crit´erios estruturais de teste, apre- sentados a seguir, como crit´erios de adequa¸c˜ao ou crit´erios de cobertura para se analisar questo˜es como essas, propiciando a quantifica¸c˜ao e a qualifica¸c˜ao da atividade de teste de acordo com o crit´erio escolhido. Quanto mais rigoroso o crit´erio utilizado e se erros n˜ao forem revelados, maior a confian¸ca no produto em desenvolvimento. Tabela 1: Classes de Equivalˆencia para o programa identifier. Restri¸c˜oes de Entrada Classes V´alidas Classes Inv´alidas Tamanho (t) do identificador 1≤t≤6 t>6 (1) (2) Primeiro caracter (c) ´e uma letra Sim N˜ao (3) (4) Cont´em somente caracteres v´alidos Sim N˜ao (5) (6) Steve et al. [96] definiram o crit´erio de Teste Funcional Sistem´atico (Systematic Func- tional Testing) o qual, basicamente, combina os crit´erios Particionamento em Classes de Equivalˆencia e Ana´lise do Valor Limite, para a gera¸ca˜o de casos de teste baseados em especifica¸ca˜o. No estudo de caso conduzido, o conjunto de casos de teste desenvolvido utilizando o Teste Funcional Sistema´tico foi capaz de distinguir 100% dos mutantes de unidades gerados n˜ao equivalentes do programa Cal (utilita´rio do UNIX) ao passo que os outros 11 conjuntos de teste gerados gerados a partir dos crit´erios Particionamento em 9
Description: