• Nenhum resultado encontrado

Transformac~ao de Tipo em Componentes Web

Para a compilac~ao da operac~ao de transformac~ao de tipo de WSat n~ao podemos utilizar, por exemplo, a operac~ao de cast de Java, pois a sua sem^antica e diferente. A operac~ao

de transformac~ao de tipo necessita criar um novo objeto de tipo mais espec co, diferen- temente da operac~ao decastde Java, que trabalha com o mesmo objeto mas permitindo o acesso aos atributos e metodos denidos no tipo mais espec co. O objeto criado pela operac~ao de transformac~ao de tipo representa, de forma mais detalhada, o mesmo componente Web representado pelo objeto original. Alem das diferencas mencionadas, a operac~ao decasttesta se o objeto e do tipo utilizado no cast, enquanto a implementac~ao da operac~ao de transformac~ao de tipo testa se o objeto representa um componente Web que satisfaz as caracter sticas determinadas pelo tipo utilizado na operac~ao.

Para entender a implementac~ao adotada para a transformac~ao de tipo, e necessario o entendimento de como os objetos Java que representam componentes Web s~ao criados e carregados com as propriedades de seus respectivos componentes Web. As informac~oes sobre componentes Web s~ao representadas por objetos da API HttpUnit 18]. Para agrupar tais objetos foi criada a classe WebComponentContext. Esta classe representa um contexto que armazena, entre outras coisas, o codigo fonte da pagina Web onde o componente Web representado esta inserido. A classeWebComponentContextpossui um construtor que recebe como par^ametro um objeto do tipo WebResponseque permite o acesso as informac~oes sobre a pagina Web representada.

Denimos na classe WebComponentum construtor que recebe como par^ametro uma inst^ancia da classe WebComponentContext. Objetos que representam componentes Web s~ao criados com o uso deste construtor. A seguir vemos o construtor da classeWebPage.

public WebPage(WebComponentContext context) { super(context)

}

Este construtor invoca o construtor de seu supertipo, no caso o construtor deWebCompo- nent, cujo codigo e visto a seguir.

public WebComponent(WebComponentContext context) { this.context = context

load() }

Como podemos ver, este construtor armazena a refer^encia para o contexto do compo- nente e, em seguida, invoca o metodo load. Este metodo e responsavel por carregar as propriedades do componente Web representado, alem de testar se estas proprieades satisfazem as restric~oes denidas pelo tipo WSat associado. O codigo do metodoload pode ser visto a seguir:

private void load() {

initExpectedPropertiesValues() loadAndCheckPropertiesValues() loadWebComponentProperties() }

Como podemos ver, o metodo loade composto pela invocac~ao sequencial dos metodos initExpectedPropertiesValues, loadAndCheckPropertiesValues e loadWebCompo- nentProperties. O metodo initExpectedPropertiesValues, como visto anterior- mente,e responsavel por carregar os atributos do objeto com os valores determinados pe- las propriedades do tipo WSat associado. O metodoloadAndCheckPropertiesValues,

por sua vez, e responsavel por carregar os atributos do objeto com os valores encontrados no componente Web representado, vericando se estes valores encontrados satisfazem os seus valores esperados. Ja o metodo loadWebComponentPropertiescarrega e testa as propriedades denidas pelo testador.

O metodo loadAndCheckPropertiesValues e declarado como abstrato na classe WebComponent, sendo implementadopelos subtipos especias predenidos emWSat. Para facilitar o desenvolvimento destes codigos de teste, foi denido o metodocheckAttribu- teValuena classe WebComponentcomo visto a seguir.

01: protected void checkAttributeValue(String attributeName,

02: Object defaultValue, Object realValue) { 03: try {

04: Field attrib = this.getClass().getField(attributeName) 05: Object value = attrib.get(this)

06: boolean valueEqualsDefaultValue = false 07: if (defaultValue == null) {

08: valueEqualsDefaultValue = (value == null)

09: } else { 10: valueEqualsDefaultValue = 11 defaultValue.equals(value) 12: } 13: if (valueEqualsDefaultValue) { 14: attrib.set(this, realValue) 15: } else { 16: if (!value.equals(realValue)) {

17: throw new DataTestValidationException(...)

18: }

19: }

20: } catch (Exception e) {

21: throw new TestExecutionException(e)

22: }

23: }

Este metodo utiliza as classes de Java contidas no pacote java:lang:reflect19] para

manipular atributos de objetos. Atraves do nome do atributo, indicado pelo par^ametro attributeName, podemos acessar o valor deste atributo (linhas4e5) e compara-lo a seu valordefault, indicado pelo par^ametrodefaultValue. Caso o valor do atributo seja igual ao valor default, simplesmente atribuimos o valor encontrado (par^ametrorealValue) a este atributo (linha 14). Caso contrario, fazemos a comparac~ao do valor esperado com o valor encontrado (linha16). Se estes valores n~ao forem iguais, o teste n~ao e satisfeito e a excec~ao DataTestValidationExceptione levantada (linha 18). Os detalhes sobre tratamento de excec~oes durante a execuc~ao dos testes s~ao vistos mais adiante.

Com a denic~ao do metodocheckAttributeValue, podemos implementar o metodo loadAndCheckPropertiesValuesde WebPageda forma vista a seguir:

protected void loadAndCheckPropertiesValues() {

WebResponse response = getContext().getWebPageInformation() int codeFound = response.getResponseCode()

checkAttributeValue("code", new Integer(-1), new Integer(codeFound)) }

A implementac~ao do metodocheckAttributeValuefacilita o desenvolvimento dos me- todos loadAndCheckPropertiesValues de outras classes, permitindo tambem uma maior facilidade para a inserc~ao de novas propriedades em tipos WSat.

A carga das propriedades de tipos WSat denidas pelo testador e realizada pelo metodoloadWebComponentPropertiesda classeWebComponent. Este metodo e invoca- do pelo metodoloadvisto anteriormente e tambem utiliza o pacotejava:lang:reflect

de Java, como mostrado a seguir.

01: private void loadWebComponentProperties() {

02: Class] paramTypes = {WebComponentContext.class} 03: Object] args = {getContext()}

04: try {

05: Field] attribs = this.getClass().getFields() 06: WebComponent comp, realComp

07: Constructor constr 08: Class componentClass

09: for (int i = 0 i < attribs.length i++) { 10: componentClass = attribsi].getType() 11: if ((WebComponent.class).isAssignableFrom(

12: componentClass)) {

13: constr = componentClass.getConstructor(

14: paramTypes)

15: realComp = (WebComponent) constr.newInstance(

16: args)

17: attribsi].set(this, realComp)

18: }

19: }

20: } catch (Exception e) {

21: throw new TestExecutionException(e)

22: }

23: }

Este metodo obtem a lista de atributos publicos denidos na classe que representa o tipo WSat ou em suas superclasses (linha 5) e a percorre (linha 9) vericando, para cada atributo da lista, se o seu tipo e subtipo de WebComponent(linhas 10e 11). Em caso armativo, uma inst^ancia do tipo do atributo e criada a partir do contexto do componente Web (linhas 13 e 15). Ao ser criada, esta inst^ancia verica a exist^encia do componente Web que ela representa dentro do contexto recebido. Por m, o objeto criado e atribu do ao atributo analisado (linha 15).

Com a denic~ao dos metodos apresentados, a compilac~ao da operac~ao de transfor- mac~ao de tipo pode ser realizada pela criac~ao do novo objeto a partir do contexto do

objeto ja existente. A seguir podemos ver o uso do operador de transformac~ao de tipo para testar se a pagina Web retornada pela URL armazenada na variavel urlAcesso satisfaz as caracter sticas da pagina inicial do sistema de busca, denidas pelo tipo PagInicial.

WebPage webPage = getWebPage(urlAcesso) PagInicial pag = PagInicial] webPage

A implementac~ao para a compilac~ao desta transformac~ao gera o seguinte codigo Java. WebPage webPage = getWebPage.execute(urlAcesso)

PagInicial pag = new PagInicial(webPage.getContext())

A instanciac~ao da classePagInicialatraves do contexto utilizado pela variavelwebPage testa se a pagina Web deste contexto satisfaz as restric~oes impostas pelo tipo PagIni- cial, levantando uma excec~ao caso as restric~oes n~ao sejam satisfeitas. Alem da gerac~ao deste codigo, o compilador deveria realizar analises sem^anticas como, por exemplo, a vericac~ao de que a transformac~ao de tipo so pode ser realizada de um tipo para um de seus subtipos. Por serem bem conhecidas, estas analises n~ao foram implementadas.

Teste do Conte udo Din^amico de Componentes Web

Alem da transformac~ao de tipos, podemos utilizar comandos comoasserte failpara testar componentes Web. A seguir podemos ver o uso do comando fail.

fail("Num. de resposta n~ao encontrado.")

O comandofailmostrado e compilado para o levantamento da excec~aoTestFailedEx- ception, como visto no codigo Java a seguir.

throw new TestFailedException("Num. de resposta n~ao encontrado.") A excec~ao TestFailedException recebe em seu construtor a mensagem de falha do teste.

O comando asserte compilado similarmente ao comando fail, vericando entre- tanto o valor de seus par^ametros para depois levantar a excec~ao, caso os mesmos sejam diferentes. A seguir, mostramos o uso deste comando para vericar o codigo de retorno de uma pagina Web acessada a partir do sistema de busca:

assert("Link de Resposta Quebrado.", paginaEncontrada.code, 200) Este comando WSat e compilado para o seguinte codigo Java:

if (paginaEncontrada.code != 200) { throw new TestFailedException(

"O numero de resposta n~ao foi encontrado.") }

Como podemos notar, a excec~ao TestFailedExceptione levantada apenas quando os par^ametros recebidos pelo comando s~ao diferentes. Caso os valores comparados n~ao sejam de tipos primitivos, o metodoequalse o operador de negac~ao ! s~ao utilizados no lugar do operador ! =.

O teste de conteudo din^amico de componentes Web tambeme vericado por servicos como findTextByValuee findAllWebLinkByURL. Estes servicos de componentes Web poderiam ser representados em Java por metodos de mesma assinatura. Entretanto, eles n~ao fazem parte desta implementac~ao do ambiente de execuc~ao de WSat devido ao curto espaco de tempo dispon vel e por n~ao serem necessarios para validar as princi- pais ideias de WSat, como por exemplo, a representac~ao e manipulac~ao de componentes Web atraves da denic~ao de tipos. Durante a realizac~ao de experimentos, o teste dos conteudos din^amicos foram realizados de forma estatica, criando-se um tipo para cada possibilidade de resposta testada. Na pratica, este procedimento e inviavel devido ao grande numero de tipos necessarios para cobrir cada possibilidade de resposta de sis- temas reais. A implementac~ao destes comandos pode ser feita com o aux lio da API HttpUnit, sem apresentar maiores problemas.