Para gera¸c˜ao de dados de teste para programas orientados a objetos ´e necess´ario representar objetos, m´etodos e seus valores em uma codifica¸c˜ao poss´ıvel de ser executa por seus algoritmos. Essa se¸c˜ao apresenta dois modelos de representa¸c˜ao de dados de teste encontrados na literatura.
de software orientado a objetos. Sua representa¸c˜ao especifica uma estrutura cromossˆomica que agrupa sequˆencias de comandos, cria¸c˜ao de objetos, mudan¸cas de estados e chamada de m´etodos. Essa estrutura cromossˆomica constitui uma entrada de dados para um al- goritmo de teste, a qual consideramos como indiv´ıduo de teste. Na representa¸c˜ao de Tonella um cromossomo (indiv´ıduo) ´e dividido em duas partes, separadas pelo caractere “@” (arroba). A primeira parte cont´em uma sequˆencia de a¸c˜oes (i.e., construtores e m´etodos), separadas pelo caractere “:” (dois pontos). Cada a¸c˜ao pode conter um novo objeto, atribu´ıdo a uma vari´avel do cromossomo, indicada como “$id”.
A segunda parte cont´em os valores de entrada dos m´etodos para serem usados nas suas chamadas. Valores de entrada de m´etodos ou construtores podem ser de tipos primitivos (i.e., int, double, boolean), separados pelo caractere “,” (v´ırgula).
Figura 3.9– Aplica¸c˜ao da representa¸c˜ao de Tonella. Fonte: Criado com base em To- nella (2004)
A Figura 3.9 apresenta o modo como a representa¸c˜ao de Tonella ´e aplicada. Do lado esquerdo pode-se observar um bloco de c´odigo e do lado direito sua representa¸c˜ao utilizando a representa¸c˜ao de Tonella. Pode-se notar que os valores inteiros utilizados como parˆametros para os m´etodos s˜ao posicionados do lado direito do s´ımbolo de “@” (arroba), enquanto que as chamadas a m´etodos s˜ao posicionadas do lado esquerdo. Vale ressaltar a sintaxe utilizada para representar a constru¸c˜ao de instˆancias de objetos e as chamadas a m´etodos. No caso, a instru¸c˜ao “A a = new A();” foi escrita na representa¸c˜ao de Tonella (2004) com a sintaxe “$a=A()”, assim como a sintaxe da chamada de m´etodo “b.f(2);” foi representada com a sintaxe “$b.f(int)”. Nota-se que a representa¸c˜ao de Tonella mant´em a apresenta¸c˜ao do indiv´ıduo de forma intuitiva, o que facilita a sua leitura e compreens˜ao. Todo o conjunto de instru¸c˜oes foi adequado a uma nova representa¸c˜ao que ordena todos os comandos em uma ´unica linha.
A gera¸c˜ao de valores para os parˆametros de tipo primitivo ´e aleat´oria, mas segue algumas regras, como:
Valores inteiros e de ponto flutuante – valores inteiros e de ponto flutuante s˜ao se- lecionados no intervalo de 0 a 100.
Booleanos – valores booleanos true (verdadeiro) e false (falso) s˜ao escolhidos aleatoria- mente, assumindo probabilidade igual (0,5).
Strings e caracteres – valores escolhidos uniformemente dentre os caracteres alfanu- m´ericos (i.e., [a-z A-Z 0-9]).
Segundo Silva e Someren (2010) um dos principais fatores que levam `a escolha da representa¸c˜ao de Tonella ´e o risco de utilizar uma estrutura na qual deve-se tomar cuidado com a compatibilidade dos parˆametros quando testados os m´etodos, a fim de que n˜ao haja corrompimento dos cromossomos. A estrutura de Tonella resolve este problema por meio de uma representa¸c˜ao bem estruturada de composi¸c˜ao dos cromossomos. Silva e Someren (2010) ainda afirmam que outra vantagem de sua utiliza¸c˜ao ´e a possibilidade de desacoplar o cromossomo do sistema, tornando f´acil a aplica¸c˜ao e constru¸c˜ao de diferentes operadores de muta¸c˜ao e crossover.
A representa¸c˜ao de Tonella n˜ao ´e a ´unica utilizada. Segundo Tracey et al. (2002), os algoritmos gen´eticos tradicionalmente utilizam codifica¸c˜ao bin´aria para suas solu¸c˜oes. Isso decorre do desenvolvimento hist´orico dos algoritmos gen´eticos, no qual se faz uma analogia entre os bits e os cromossomos na evolu¸c˜ao natural. No entanto, para gera¸c˜ao de dados de teste, trˆes problemas podem ser encontrados: perda de informa¸c˜ao, corrup¸c˜ao bin´aria e disparidade espacial da solu¸c˜ao original. A disparidade espacial ´e causada por solu¸c˜oes muito pr´oximas no espa¸co de solu¸c˜ao, mas que s˜ao muito distantes no espa¸co de solu¸c˜ao codificado. Por exemplo, a representa¸c˜ao bin´aria do n´umero 31 ´e “1 1 1 1 1”, enquanto que o n´umero 32 (o n´umero posterior a 31) a representa¸c˜ao ´e “1 0 0 0 0 0”. Isto ´e, dois n´umeros t˜ao pr´oximos na solu¸c˜ao original, mas que s˜ao muito diferentes em suas codifica¸c˜oes. Opera¸c˜oes de muta¸c˜ao e crossover tˆem dificuldade de executar movimentos entre estas duas solu¸c˜oes.
Para resolver esta quest˜ao, os autores prop˜oem o uso da codifica¸c˜ao de Gray (TRACEY et al., 2002, p. 9) como forma de solu¸c˜ao para o problema da disparidade espacial. A codi- fica¸c˜ao de Gray auxilia com os tipos num´ericos, mas n˜ao ajuda com tipos n˜ao-num´ericos, al´em de n˜ao resolver o problema da perda de informa¸c˜ao e da corrup¸c˜ao bin´aria.
A perda de informa¸c˜ao ocorre durante o crossover, quando a representa¸c˜ao bin´aria de um valor ´e acidentalmente partida em duas partes gerando um terceiro valor, diferente dos valores dos indiv´ıduos que originaram a evolu¸c˜ao. Conforme a Figura 3.10, podemos
identificar dois indiv´ıduos P1 e P2, cujos atributos X possuem valores diferentes (35 e
12, respectivamente), mas que ap´os uma divis˜ao errada do indiv´ıduo para execu¸c˜ao do crossover, geram um novo indiv´ıduo com um valor para X diferente dos demais (TRACEY et al., 2002).
Outro problema enfrentado ´e a corrup¸c˜ao bin´aria que ocorre durante a muta¸c˜ao de um cromossomo, devido `a c´opia indevida de alguns bits de uma representa¸c˜ao para outra, modificando o valor de um n´umero que n˜ao deveria ser alterado. Na Figura 3.11 pode-se observar que a muta¸c˜ao copia indevidamente os primeiros bits da representa¸c˜ao de um atributo que n˜ao deveria ser mutado, acarretando na muta¸c˜ao de mais de um atributo ao mesmo tempo (TRACEY et al., 2002).
Figura 3.10 – Codifica¸c˜ao bin´aria - perda de informa¸c˜ao. Fonte: Tracey et al., 2002.
3.2.1
Opera¸c˜oes com indiv´ıduos de teste
Em sua abordagem, Tonella (2004), prop˜oe um conjunto de operadores de muta¸c˜ao e
crossover, com o objetivo de evoluir os indiv´ıduos da popula¸c˜ao para obter uma popula¸c˜ao
mais adaptada. Os operadores de Tonella funcionam da seguinte maneira:
Muta¸c˜ao de valores de entrada: o valor de um parˆametro primitivo ´e substitu´ıdo por outro valor, de mesmo tipo, aleatoriamente gerado.
$a=A() : $b=B() : $b.f(int) : $a.m(int, $b) @ 2, 5 $a=A() : $b=B() : $b.f(int) : $a.m(int, $b) @ 6, 5
Figura 3.12 – Representa¸c˜ao de Tonella: muta¸c˜ao de valores de entrada
A Figura 3.12 mostra o parˆametro passado para o m´etodo “f(int)” da classe “B” alterado de 2 para 6.
Mudan¸ca de construtor: um dos construtores do indiv´ıduo ´e aleatoriamente tro- cado. Esse operador pode acarretar a inclus˜ao de novos parˆametros ou objetos na estru- tura do indiv´ıduo, dependendo dos parˆametros esperados pelo novo construtor.
$a=A() : $b=B() : $b.f(int) : $a.m(int, $b) @ 2, 5
$a=A() : $c=C() : $b=B($c, int) : $b.f(int) : $a.m(int, $b) @ 3, 2, 5 Figura 3.13 – Representa¸c˜ao de Tonella: mudan¸ca de construtor
No exemplo da Figura 3.13, o construtor da classe “B” ´e substitu´ıdo por outro cons- trutor, que recebe dois parˆametros, onde um deles ´e outro objeto, do tipo “C”, e o segundo parˆametro ´e de um tipo primitivo.
Inclus˜ao de chamada a m´etodo: novas chamadas a m´etodos s˜ao inclu´ıdas ale- atoriamente na estrutura do indiv´ıduo. Essa opera¸c˜ao pode exigir a inclus˜ao de novos parˆametros (i.e., objetos, vari´aveis de tipos primitivos).
$a=A() : $b=B() : $b.f(int) : $a.m(int, $b) @ 2, 5
$a=A() : $b=B() : $b.g(int) : $b.f(int) : $a.m(int, $b) @ 3, 2, 5 Figura 3.14 – Representa¸c˜ao de Tonella: inclus˜ao de chamada a m´etodo
Como se pode observar, no exemplo da Figura 3.14, foi inclu´ıda uma chamada ao m´etodo “g(int)”, que acarretou a inclus˜ao de um parˆametro de tipo primitivo com valor 3.
Remo¸c˜ao de chamada a m´etodo: na estrutura do indiv´ıduo, ap´os a aplica¸c˜ao deste operador, um dos m´etodos intermedi´arios ´e removido, junto com seus respectivos parˆametros.
$a=A() : $b=B() : $b.f(int) : $a.m(int, $b) @ 2, 5 $a=A() : $b=B() : $a.m(int, $b) @ 5
Figura 3.15 – Representa¸c˜ao de Tonella: remo¸c˜ao de chamada a m´etodo
O exemplo da Figura 3.15 mostra a aplica¸c˜ao deste operador removendo a chamada do m´etodo intermedi´ario “f(int)” da classe “B”.
Crossover: Depois de selecionar dois indiv´ıduos aleatoriamente, trocam-se partes dos cromossomos entre si, com o objetivo de gerar dois novos cromossomos na popula¸c˜ao.
$a=A() : $b=B() : $b.f(int) : $a.m(int, $b) @ 2, 5
$a=A() : $b=B() : $b.n(int) : $b.g(int,int) : $a.m(int, $b) @ 8, 4, 7, 6 $a=A() : $b=B() : $b.g(int,int) : $a.m(int, $b) @ 4, 7, 5
$a=A() : $b=B() : $b.n(int) : $b.f(int) : $a.m(int, $b) @ 8, 2, 6
Figura 3.16 – Representa¸c˜ao de Tonella: crossover
Nota-se na Figura 3.16 que no exemplo apresentado o m´etodo intermedi´ario “f(int)” da classe “B” do primeiro cromossomo, ´e substitu´ıdo pelo m´etodo intermedi´ario “g(int, int)” da classe “B” do segundo cromossomo, junto com seus respectivos parˆametros. Da mesma forma que o segundo indiv´ıduo troca o m´etodo “g(int, int)” da classe “B” pelo m´etodo intermedi´ario “f(int)” da classe “B” do primeiro cromossomo, junto com seus respectivos parˆametros.