domingo, 3 de outubro de 2010

Integração Selenium e Testlink

Não deixe de ler o post Integração Selenium e Mantis!

Escopo
Este tutorial vai apresentar como fazer a integração do Selenium com o Testlink. Mas no que consiste essa integração?
Essa integração nada mais é do que o envio do resultado de execução do script de teste para o Testlink. Pode-se explorar muito mais do que isso, porém esse tutorial se limitará a apenas apresentar como reportar o resultado de execução do script.

Criaremos um projeto em Java com o suporte do JUnit para a criação do script de teste com o Selenium. abaixo há uma lista de itens necessários para esse tutorial.

O que é necessário?
PS: apesar de no site estar o dbfacade-testlink como em outro projeto os arquivos necessários estão no link citado acima.

1. Configurando o Testlink
Não existe uma sequencia certa de passos, eles podem ser praticamente em qualquer ordem, porém iniciarei pelo Testlink que costuma ser um ponto crítico se não configurado.
A versão que estou utilizando do Testlink é a 1.9 beta 6, porém você pode utilizar desde a versão 1.8.5

1.1 Habilitar o projeto com a Automação de Teste
Você pode ou criar um novo projeto marcando a opção Enable Test Automation (API keys) ou editando o projeto e selecionando o mesmo item.
A imagem abaixo mostra a criação de uma novo projeto



1.2 Editar o arquivo de configuração do Testlink
Depois de habilitar a automação de teste para o projeto desejado é necessário habilitar o acesso a API XML-RPC do Testlink. É esta API interna que nos possibilitará o acesso aos dados do projeto.
Você precisará alterar duas variáveis no arquivo config.inc.php do Testlink.

Adendo: o ideal é você não alterar diretamente o arquivo config.inc.php, e sim alterar o arquivo custom_config.inc.php que estará como custom_config.inc.php.example. Basta remover o ".example" e colar as variáveis que serão apresentadas abaixo no arquivo e salvá-lo.

As duas variáveis que você deve alterar são:
  • $tlCfg->api->enabled
  • $tlCfg->exec_cfg->enable_test_automation
Copie as duas linhas inteiras, cole no arquivo custom_config.inc.php e altera seus valores para:
  • $tlCfg->api->enabled = TRUE;
  • $tlCfg->exec_cfg->enable_test_automation = ENABLED;
A imagem abaixo mostra como fica o arquivo.



1.3 Gerar uma nova chave de acesso
Depois de habilitar o acesso a API XML-RPC e informar a ativação da automação no arquivo de configuração é necessário gerar a chave de acesso.
Essa chave é criada por usuário e será ela que permitirá ao Testlink identificar quem está tentando acessar os serviços XML-RPC.

Para gerar a chave vá até o menu Personal. No final da página irá existir uma seção API Interface, conforme a figura abaixo:


Clique no botão Generate a new key. Uma chave será gerada.
Procure não clicar mais vezes neste botão, pois ele irá gerar uma nova chave. Qualquer mudança na chave invalida a futura comunicação com os serviços do Testlink.
Por enquanto guarde a chave que iremos utiliza-la mais tarde dentro da API dbfacede-testlink.
A seção API interface ficará parecida com a imagem abaixo:


2. Preparando seu ambiente de Desenvolvimento
A preparação do ambiente vai apresentar somente as bibliotecas necessárias para fazer a integração funcionar. Não é intuito deste item ensinar alguma coisa sobre o Eclipse ou sobre Java.

2.1 Selecionando as bibliotecas necessárias
Para rodar o script de teste com a integração e necessário os seguintes arquivos (bibliotecas e libraries) das seguintes API's / frameworks:

  • dbfacade-testlink: necessário adicionar as seguintes bibliotecas
    • testlink-api-client-2.0.jar
    • todas as libs, exeto a junit, da pasta lib
  • Selenium RC: necessário adicionar as seguintes bibliotecas
    • selenium-server.jar
    • selenium-java-client-driver.jar
  • JUnit: necessário adicionar o JUnit 4 que já vem com o Eclipse (Add Libraries)
Abaixo segue a imagem das bibliotecas que foram adicionadas ao Eclipse.



Para adicionar cada biblioteca você precisa clicar com o botão direito no nome do projeto e selecionar Build Path/Configure Build Path...


Adicone também a biblioteca do JUnit, indo ao mesmo local (Configure Build Path...) e clicando no botão Add Library. Selecione JUnit e, em seguida, JUnit 4.

2.1 Desenvolvendo o código-fonte
A aplicação de exemplo, que está no final do post traz o código-fonte do script de teste e mais dois arquivos de código-fonte, que serão explicados abaixo.

A primeira coisa a fazer é entender o script de teste primeiro. O package, os imports e comentários em javadoc foram excluídos para exemplificar o funcionamento da classe.

1:  public class CasoTesteSelenium extends TestCase implements IConstantes {  
2:       
3:     Selenium selenium;  
4:     SeleniumServer server;  
5:       
6:     String serverHost = "localhost";  
7:     int serverPort = 4444;  
8:     String browserStartCommand = "*firefox";  
9:     String browserURL = "http://www.lojaexemplodelivros.com.br/";  
10:       
11:     public void setUp() throws Exception {  
12:        selenium = new DefaultSelenium(serverHost, serverPort, browserStartCommand, browserURL);  
13:        server = new SeleniumServer();  
14:          
15:        server.start();  
16:        selenium.start();  
17:     }  
18:       
19:     @Test  
20:     public void testPesquisaLivro() throws Exception {  
21:        String resultado = null;  
22:        String nota = null;  
23:          
24:        try {  
25:           selenium.open("/");  
26:           selenium.click("//ul[@id='nav']/li[1]/ul/li[2]/ul/li[1]/a/span");  
27:           selenium.waitForPageToLoad("30000");  
28:             
29:           assertEquals("3 Item(s)", selenium.getText("//div[@id='main']/table[1]/tbody/tr/td[1]/strong"));  
30:           assertEquals("[PRODUTO DE EXEMPLO] - Use a Cabeça! Java", selenium.getText("link=[PRODUTO DE EXEMPLO] - Use a Cabeça! Java"));  
31:           assertEquals("[PRODUTO DE EXEMPLO] - Entendendo e Dominando o Java: para Internet", selenium.getText("link=[PRODUTO DE EXEMPLO] - Entendendo e Dominando o Java: para Internet"));  
32:           assertEquals("[PRODUTO DE EXEMPLO] - Ajax com Java", selenium.getText("link=[PRODUTO DE EXEMPLO] - Ajax com Java"));  
33:             
34:           selenium.click("//img[@alt='[PRODUTO DE EXEMPLO] - Ajax com Java']");  
35:           selenium.waitForPageToLoad("30000");  
36:           assertTrue(selenium.isTextPresent("2x R$ 222,25 sem juros"));  
37:           assertTrue(selenium.isTextPresent("3x R$ 148,17 sem juros"));  
38:           assertTrue(selenium.isTextPresent("4x R$ 111,13 sem juros"));  
39:           assertTrue(selenium.isTextPresent("5x R$ 88,90 sem juros"));  
40:          
41:        resultado = TestLinkAPIResults.TEST_PASSED;  
42:          
43:        } catch (Exception e) {  
44:           resultado = TestLinkAPIResults.TEST_FAILED;  
45:           nota = e.getMessage();  
46:           e.printStackTrace();  
47:        } finally {  
48:           ResultadoExecucao.reportTestCaseResult(PROJETO, PLANO, CASO_TESTE1, BUILD, nota, resultado);  
49:        }  
50:     }  
51:       
52:     public void tearDown() throws Exception {  
53:        selenium.stop();  
54:        server.stop();  
55:     }  
56:  }  
57:    

Basicamente há a criação dos atributos do Selenium e SeleniumServer para a execução, os métodos setup() e tearDown() do JUnit e o caso de teste automatizado.
Note que o bloco do caso de teste (método testPesquisaLivro) está com um try-catch. Isso é necessário para que possamos enviar a informação ao Testlink se o script falhou ou passou.

Na linha 41 há o seguinte código:
resultado = TestLinkAPIResults.TEST_PASSED;

Este atributo (resultado) é uma String que armazena o status de execução. Neste caso ele está no final dos passos do script passando sucesso (TestLinkAPIResults.TEST_PASSED).
É ele que vai dizer para o Teslink que o script passou!

Dentro do bloco de catch (linhas 44 a 46) há os comandos que serão executados quando o script falhar por algum motivo. Note que na linha 44 passamos para a variável de resultado a informação TestLinkAPIResults.TEST_FAILED.
Ele é que vai dizer para o Testlink que o script falhou!

Na linha 45 a mensagem de erro gerado pelo script vai para a variável nota, para que seja adicionado a mensagem de erro no campo Nota do Testlink.

Na linha 48, dentro do bloco de finally há o envio de resultado da execução do teste para o Testlink.
É ele que envia os dados para o Testlink!

Há um método é chamado (reportTestCaseResult) para passar as informações do Selenium para o Testlink.

Classe ResultadoExecucao
Dentro do projeto no pacote com.blogspot.sembugs há a classe ResultadoExecucao, que é a responsável por enviar o resultado do script ao Testlink. Eu gerei essa classe como chamada de uma função da API dbfacade-testlink.

PS: package, imports e comentários em javadoc foram excluídos para exemplificar o funcionamento da classe.

1:  public class ResultadoExecucao implements IConstantes {  
2:    
3:    public static void reportTestCaseResult(String projetoTeste, String planoTeste, String casoTeste, String nomeBuild, String nota, String resultado) throws TestLinkAPIException {  
4:        
5:      // Cria uma instância do TestLinkAPIClient para comunicação com o Testlink  
6:      TestLinkAPIClient testlinkAPIClient = new TestLinkAPIClient(DEVKEY, URL);  
7:      // Submete os resultados para o Testlink  
8:      testlinkAPIClient.reportTestCaseResult(projetoTeste, planoTeste, casoTeste, nomeBuild, nota, resultado);  
9:    
10:    }  
11:  }  

Na linha 6 há a criação de uma instância da classe TestlinkAPIClient, passando a URL do XML-RPC do Testlink (URL) e a chave do usuário (DEVKEY).

Muito atenção!
A URL do XML-RPC é http://servidor/nome_testlink/lib/api/xmlrpc.php, onde:
  • servidor: é o nome do servidor onde está instalado o Testlink. Ex: localhost
  • nome_testlink: é o nome de acesso a aplicação do testlink. Ex: testlink
A DEVKEY foi gerada lá nos primeiros passos deste post dentro do Testlink.
Você deve alterar a DEVKEY para o seu usuário e alterar o servidor e nome_testlink para as suas configurações quando for rodar o exemplo.

A linha 8 envia os dados para o Testlink, com alguns dados como parâmetro, que são:
  • projetoTeste: nome do projeto de teste que estamos usando no Testlink
  • planoTeste: nome do plano de teste que estamos usando no Testlink
  • casoTeste: nome do caso de teste que estamos usando no Testlink
  • nomeBuild: nome da build que estamos usando no Testlink
  • nota: nota que será inserida na execução quando houver falha na execução do script
  • resultado: resultado passado pelo script
Interface iConstantes
Foi criado uma interface com os dados necessários para o envio dos dados para o Testlink, que são os parâmetros que foram descritos acima.

1:  public interface IConstantes {  
2:    
3:     final String DEVKEY = "84947019532f2f23e1d90b6de748cd66";  
4:     final String URL = "http://www.eliasnogueira.info/arquivos_blog/testlink_1_9_beta6/lib/api/xmlrpc.php";  
5:     final String PROJETO = "Integracao Selenium e Testlink";  
6:     final String PLANO = "PT001 - Integracao Selenium e Testlink";  
7:     final String BUILD = "Ciclo 1";  
8:     final String CASO_TESTE1 = "Pesquisar no blog";  
9:       
10:  }  

Note que todos os dados que estão contidos no meu Testlink estão ali. Você vai precisar alterar estes dados para fazer os seus testes.
Todas as informações que precisam ser enviadas para o Testlink através do método reportTestCaseResult da classe ResultadoExecucao estão nesta interface.

3. Criação do(s) Casos de Teste
Por incrível que pareça você não precisa colocar o caso de teste com o tipo "Automatizado" e nem os passos como "Automatizado" para que o script insira o resultado de execução do caso de teste automaticamente, eles servem apenas para informação.
Abaixo segue a imagem deste item dentro do caso de teste citadas.



4. Execução e modificação deste tutorial
Chegamos ao fim do tutorial. Se você deseja executar este tutorial baixe os fontes de exemplo criados no Eclipse e altere a URL de conexão com o Testlink.

Se você alterar os dados da interface IConstantes o exemplo não funcionará, mas você pode usar o tutorial como base para a sua integração.

Por favor mandem sugestões e feedback's se este tutorial tem ajudado ou mesmo se estiver difícil de entender (claro que dentro de seus conhecimentos de programação Java).

4.1 Para entender mais
Você pode fazer a integração com outras linguagens de programação com o Testlink, não especificamente com o Selenium. Na verdade essa é uma implementação em Java para qualquer aplicação desenvolvida em Java, não específica para o Selenium. O que fiz foi inserir dentro do código do Selenium a integração!

Acesse as seguintes páginas para ter mais informações sobre os serviços XML-RPC do Testlink:

4.2 Fontes deste tutorial
Arquivo zipado contendo o projeto desenvolvido no Eclipse:
http://www.eliasnogueira.com/arquivos_blog/selenium/integracao/testlink/testlink-selenium-example.zip

Abraço a todos!

16 comentários:

  1. Muito boa a dica Elias, ta aí um material mais do que útil.

    Abraço

    ResponderExcluir
  2. Boa Tarde Elias,
    Excelente dica.
    Fiz as configurações, porém ao executar, ao chamar o método reportTestCaseResult o console me da o seguinte erro:

    14:03:56.298 INFO - Got result: OK,true on session 82b0e57ac3fe4fc4928163f8b8790569
    [Fatal Error] :53:70: Invalid byte 2 of 3-byte UTF-8 sequence.
    [Fatal Error] :53:70: Invalid byte 2 of 3-byte UTF-8 sequence.
    [Fatal Error] :53:70: Invalid byte 2 of 3-byte UTF-8 sequence.
    [Fatal Error] :53:70: Invalid byte 2 of 3-byte UTF-8 sequence.
    14:05:58.383 INFO - Command request: testComplete[, ] on session 82b0e57ac3fe4fc4928163f8b8790569

    Poderia me ajudar?

    ResponderExcluir
  3. Olá Rafael!
    Esse é um problema de encoding do edito ou IDE que tu ta usando. Dá uma revisada no encoding dele.
    Dá uma olhada também se, ao salvar uma classe, ele alterou a acentuação do texto nela.

    Abraços!

    ResponderExcluir
  4. Show de bola o post Elias. Parabéns!

    ResponderExcluir
  5. Muito massa cara, to tentando integrar TestComplete com TestLink e ta dando mto certo (por enquanto) qdo tiver pronto deixo um post a respeito tbm... vlw

    ResponderExcluir
  6. Muito bom, obrigado por compartilhar :)

    ResponderExcluir
  7. Ficou muito bom o material! Conseguir rodar aqui tranquilo e até ja adaptei essa integração na minha arquitetura automatizada (que usa TestNG, mas tive que fazer uma "gambira" hehe).

    valeu!

    ResponderExcluir
  8. Parabens pelo post, consegui adaptar para o uso com o Testcomplete.

    Muito obrigado

    ResponderExcluir
  9. Hi,

    Excuse me, but i wonder if you could write un other tutoriel in english

    I don't understand your language and I really need to know how did you do to link between Selenium and TestLink

    Thanks in advance,

    Salma,
    badrodoja@gmail.com

    ResponderExcluir
  10. Parabéns pelo tutorial, consegui aplicar essa integração utilizando a ferramenta TestComplete com o Testlink.

    Abraços

    ResponderExcluir
  11. Estou a ter o seguinte erro fica parado no 16:13:15.267 INFO - Launching Firefox...abre o firefox mas não faz nada e não me entra no metodo testPesquisaLivro()

    ResponderExcluir
  12. "Erro"
    Qual e o teu sistema operacional?
    Se o Firefox não está abrindo é porque, provavelmente, o teu Windows é o 7 e o Firefox não está no PATH do Windows.

    Abraço!

    ResponderExcluir
  13. Estou com o erro abaixo, alguem pode auxiliar.
    Exception in thread "main" testlink.api.java.client.TestLinkAPIException: The call to the xml-rpc client failed.
    at testlink.api.java.client.TestLinkAPIClient.executeXmlRpcMethod(TestLinkAPIClient.java:1266)
    at testlink.api.java.client.TestLinkAPIClient.execXmlRpcMethodWithCache(TestLinkAPIClient.java:1195)
    at testlink.api.java.client.TestLinkAPIClient.getProjects(TestLinkAPIClient.java:726)
    at testlink.api.java.client.TestLinkAPIHelper.getProjectInfo(TestLinkAPIHelper.java:64)
    at testlink.api.java.client.TestLinkAPIHelper.getProjectID(TestLinkAPIHelper.java:48)
    at testlink.api.java.client.TestLinkAPIClient.reportTestCaseResult(TestLinkAPIClient.java:184)
    at ResultadoExecucao.reportTestCaseResult(ResultadoExecucao.java:12)
    at Automation.main(Automation.java:34)
    Caused by: org.apache.xmlrpc.client.XmlRpcClientException: Failed to parse servers response: Expected methodResponse element, got html
    at org.apache.xmlrpc.client.XmlRpcStreamTransport.readResponse(XmlRpcStreamTransport.java:177)
    at org.apache.xmlrpc.client.XmlRpcStreamTransport.sendRequest(XmlRpcStreamTransport.java:145)
    at org.apache.xmlrpc.client.XmlRpcHttpTransport.sendRequest(XmlRpcHttpTransport.java:94)
    at org.apache.xmlrpc.client.XmlRpcSunHttpTransport.sendRequest(XmlRpcSunHttpTransport.java:44)
    at org.apache.xmlrpc.client.XmlRpcClientWorker.execute(XmlRpcClientWorker.java:53)
    at org.apache.xmlrpc.client.XmlRpcClient.execute(XmlRpcClient.java:166)
    at org.apache.xmlrpc.client.XmlRpcClient.execute(XmlRpcClient.java:157)
    at org.apache.xmlrpc.client.XmlRpcClient.execute(XmlRpcClient.java:146)
    at testlink.api.java.client.TestLinkAPIClient.executeXmlRpcMethod(TestLinkAPIClient.java:1232)
    ... 7 more
    Caused by: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 7; Expected methodResponse element, got html
    at org.apache.xmlrpc.parser.XmlRpcResponseParser.startElement(XmlRpcResponseParser.java:98)
    at org.apache.xerces.parsers.AbstractSAXParser.startElement(Unknown Source)
    at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanStartElement(Unknown Source)
    at org.apache.xerces.impl.XMLNSDocumentScannerImpl$NSContentDispatcher.scanRootElementHook(Unknown Source)
    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
    at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
    at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
    at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
    at org.apache.xmlrpc.client.XmlRpcStreamTransport.readResponse(XmlRpcStreamTransport.java:175)
    ... 15 more

    ResponderExcluir
  14. Bom Dia Elias, Excelente dica.

    Eu quero saber se existe alguma forma automática de anexar evidências aos casos de teste executados no Testlink.

    Poderia me ajudar?

    ResponderExcluir
  15. Boa Tarde,
    Estou com um seguinte problema ao executar o teste:

    testlink.api.java.client.TestLinkAPIException:
    The xml-rpc call to TestLink API method tl.reportTCResult failed.
    Result[0] = {message=(reportTCResult) - Parameter platformname OR platformid is required, but has not been provided, code=200}

    at testlink.api.java.client.TestLinkAPIClient.execXmlRpcMethodWithCache(TestLinkAPIClient.java:1209)
    at testlink.api.java.client.TestLinkAPIClient.reportTestCaseResult(TestLinkAPIClient.java:282)

    ResponderExcluir
  16. Oi Walber,
    Qual versão da API do Testlink tu estás utilizando?

    Abraço!

    ResponderExcluir