terça-feira, 18 de setembro de 2007

Preparando o Terreno para o Selenium

A importância da realização dos testes em um sistema não é motivo de discussão, mas sem o apoio de ferramenta para automatizar esses testes, essa atividade pode tornar-se um verdadeiro calvário. Ainda mais se houver a necessidade que essa execução ocorra várias vezes ao longo do cilo de vida da aplicação.

Se pensarmos de forma simplista temos duas abordagens para testes:
1 - Dada uma entrada, existe uma saída esperada
2 - Dada uma entrada, observar como será o comportamento do sistema

Nos prendamos a primeira abordagem.

O princípio básico dos testes unitários com o junit se dá através de afirmações (assertions), ou seja, você programa várias afirmações para suas classes através de seus métodos: "dado duas entradas 1 e 1, é esperado que a soma seja 2" e assim por diante.

O Selenium usa esse mesmo princípio realizando testes em função dos resultados respondidos pelo sistema, com o seguinte tempero: Os testes dizem respeito ao sistema como um todo - tipicamente são testes funcionais. Um simples navegar de telas pode reprentar a realização de um cálculo complexo. E é justamente neste ponto que precisamos ter atenção.

Vamos a um exemplo simples: Uma calculadora de Horas extras para profissionais CLT. Dado um volume de horas trabalhadas e seu salário, a calculadora responde quanto você deve receber. Para este simples exemplo temos alguns cenários possíveis:

a) As horas trabalhadas foram durante a semana;
b) As horas trabalhadas foram num feriado;
c) As horas trabalhadas foram de um dia até o outro.

Esse tipo de cálculo prevê uma série de adicionais que devem incidir sobre o cálculo de suas horas, de modo que para este exemplo simples os dados existentes para o sistema acabam ganhando uma importância grande.

Num sistema de maior complexidade o conhecimento prévio desses dados ganha um nível a mais. Dessa forma é muito importante que tenhamos conhecimento prévio dessa massa de dados para os casos de testes que serão executados principalmente porque, dado o automatismo, a possibilidade de repetição é fundamental para um boa produtividade na criação de códigos com qualidade.

Seguindo o princípio K.I.S.S. (Keep It Stupidly Simple), podemos criar facilmente uma classe que carregue o banco de dados a partir de um arquivo .SQL onde cada linha tem um comando SQL:



public class CarregaMassaDados {
   public static void cargaDados(String arquivoSql) {
      String stm = "";
      BufferedReader in = null;
      Connection connection = null;
      Statement stmt = null;
      if ((arquivoSql == null) ("".equals(arquivoSql))) {
         throw new RuntimeException("O Parâmetro arquivoSql deve ser informado");
      }
      try {
         Class.forName("org.postgresql.jdbc3.Jdbc3ConnectionPool");
         connection =
            DriverManager.getConnection(
            "jdbc:postgresql://127.0.0.1:5432/BDAplicacao",
            "LOGIN",
            "SENHA");
         in = new BufferedReader(new FileReader(arquivoSql));
         stmt = connection.createStatement();
         String sql;
         while ((sql = in.readLine()) != null) {
            stmt.executeUpdate(sql);
         }
      } catch (ClassNotFoundException e) {
         throw new RuntimeException("Database driver não encontrado.");
      } catch (SQLException e) {
         throw new RuntimeException("Database não conectado.");
      } catch (IOException e) {
         throw new RuntimeException("Impossivel ler o arquivo.");
      } finally {
         try {
            if (in != null) in.close();
            if (stmt != null) stmt.close();
            if (connection != null) connection.close();
         } catch (IOException e) {
            throw new RuntimeException("Impossivel ler o arquivo.");
         } catch (SQLException e) {
            throw new RuntimeException("Database não conectado.");
         }
      }
   }
}

A chamada a carga de dados pode ser colocada no início dos seus testes, permitindo que a sua massa de dados seja conhecida garantido assim a repetividade de seus testes.

Abraços.

segunda-feira, 10 de setembro de 2007

SOA, Java e Paixão

No ano passado estivemos no Sun Tech Days 2006 em São Paulo. Lá tivemos a oportunidade de conhecer em algumas das palestras uma figura muito peculiar que, inclusive pode ser vista em uma bela performance em http://www.youtube.com/watch?v=BXHE4SktsbM .

O dançarino em questão é Sang Shin, evangelista da Sun que apresentou uma bela palestra sobre SOA com objetividade e didática suficientes para romper qualquer barreira que o idioma pudesse causar. Nessa palestra (estou procurando o link, mas fiquem com este por enquanto) ficou muito claro o propósito de SOA e que ele não é Webservice :-) Ainda falaremos um pouco sobre SOA, mas no momento gostaria de ressaltar a paixão desse profissional.

Preocupado em compartilhar conhecimento, ele mantém um site - o www.javapassion.com - através do qual é possível se inscrever em alguns dos vários cursos que ele ministra. O custo? De graça e eles são em inglês.

Abraços.

sábado, 8 de setembro de 2007

Testes Funcionais na Web - Selenium

Quem está procurando uma ferramenta para testes funcionais (de tela) que:

  • não seja preciso "decorar" mais uma linguagem ou 1001 novos comandos;
  • siga um padrão, xunit por exemplo;
  • seja possível integrar os scripts a um repositório de gerência de configuração para integração contínua;
  • possa ser criado por equipe de testes, não necessariamente por programadores;
  • não seja preciso escrever uma linha de código;
  • não tenha custo de aquisição "grátis";
  • execução totalmente automática.

Esté querendo muito?! Não, existe uma ótima ferramenta chamada Selenium (http://www.openqa.org/selenium/), que é grátis e open-source.

A idéia deste post é mostrar alguns benefícios e na prática esta suite. Digo suite, pois há diversos projetos em paralelo (não é fácil de entender) que podem ser utilizados em conjunto para um melhor resultado.

A seguir vamos criar um passo a passo de utilização, que está misturado com um processo que pode ser adaptado de acordo com as suas necessidades. Lembre-se que a ferramenta pode ser utilizada em qualquer processo desde CMMi até processos Ágeis.

Vamos a nossa receita de bolo...

Passo 1 - Criando um plano de testes (trabalho árduo)

Neste passo é onde os analistas do negócio ou sistemas descrevem as entradas de testes necessárias e os resultados esperados para que o atendimento a um requisito seja corretamente satisfeito.

Passo 2 - Automatizando o plano de testes

A partir do plano de testes criado é necessária a automatização de cada entrada de teste. No Selenium esta automatização é realizada através de uma IDE extremamente simples e robusta.

A ferramenta integra um plugin ao Mozila Firefox. Isto não quer dizer que os testes são executados apenas sob o Firefox, a IDE é apenas um adicional que afeta a produtividade na implementação dos testes.

Você pode baixar o Mozilla Firefox em http://www.mozilla.com/en-US/firefox/, recomendo o uso da versão 2.0 pois foi a versão que utilizei para avaliação da ferramenta. E para baixar o XPI (plugin para o firefox) do Selenium acesse a url http://www.openqa.org/selenium-ide/.

O objetivo do Selenium IDE é provê interface amigável para gravação dos testes através de toda ação do usuário à aplicação web. Estas ações são gravadas como um roteiro, baseado em HTML, que pode ser exportado em inúmeras linguagens (próximo passo).

Abaixo a tela principal do Selenium IDE para gravação dos testes, simples e poderosa. Digo poderosa porque é possível alterar ordem das ações, consultar todas as funções disponíveis (asserts, verify, alerts) e ainda incluir ações não gravadas.

Passo 3 - Exportando testes automatizados

Os testes automatizados através do auxílio da IDE no Mozilla Firefox são gravados no formato tabular - HTML (usado no método de testes FIT, talvez um próximo post).

Este formato não é ideal, visto que é necessário o auxílio da IDE ou utilização de um outro projeto chamado Selenium TestRunner.

Desta forma, o ideal é que tenhamos o teste escrito em linguagens flexíveis e extensíveis como: Java, C#, PHP ... O Selenium IDE oferece exportação dos testes nestas várias linguagens e estruturado de acordo com o respectivo xUnit (jUnit, nUnit...). E acreditem, oferece suporte a extensibilidade, ou seja, podemos colaborar com novas linguagens. :-)

Uma observação importante é que o script em HTML também deve ser salvo para futuras manutenções nos testes sem a necessidade de re-gravação, o Selenium IDE só lê neste formato e exporta "n" outros.

Passo 4 - Adaptando os testes

Não vamos nos enganar, o script gravado pelo Selenium IDE não é perfeito. Desta forma, é necessário que refinemos geralmente nos seguintes pontos:

  • As vezes é necessário incluir entre ações "tempo de espera", pois depende da velocidade que o navegador executou a ação naquele momento. O ideal é que sempre entre requests tenhamos um wait para garantir.
  • Sempre que exportamos na linguagem que desejamos o Selenium IDE usa hard-coded para informação de servidor, abrir página inicial, usuário e senha de acesso e etc. Recomendo que seja criada uma classe base para tratar situações que valem para todos os testes da aplicação.

Assim, recomendo que do conteúdo exportado pelo Selenium IDE sejam copiados os test cases (métodos de testes) ajustados e depois é só colar na sua IDE preferida.

Crie uma classe de teste que pode ser em qualquer linguagem. Em qualquer?! Sim, até mesmo se for diferente da sua aplicação. Lembre-se o Selenium testa somente aplicações web.

Cole o teste e adapte-o de acordo com as nossas dicas.

É claro que o Selenium estende os frameworks xUnit das linguagens específicas, ou seja, ele estende o jUnit, nUnit e etc. Então, é necessário que façamos a inclusão das dependências. Este já é um outro projeto no site do Selenium, chamado de Remote Control. Baixe-o a partir da url: http://www.openqa.org/selenium-rc/download.action. Neste projeto temos as extensões para cada linguagem (.NET, Java...) e o server (já já explico).

Passo 5 - Executando a classe de testes

Bom, aqui nós chegamos a etapa final: execução dos testes. Diferente de inúmeras ferramentas de testes de aplicações web onde são enviados requests e recebidos responses do servidor (parse para lá, parse para cá) o Selenium trabalha usando o próprio browser. Isso mesmo, terceiriza o serviço mais difícil: eventos em páginas web, navegação, renderização e tudo mais. Esta é uma grande vantagem em relação a outras ferramentas como o jWebUnit.

Aí surgem algumas perguntas:

Eu só posso testar em um browser? Não, você escolhe o browser em que deseja executar os testes, ou seja, podemos executar os mesmos testes no Internet Explorer e Firefox, testando assim a compatibilidade cross-browser.

Fico dependente do browser, ou seja, meu teste é mais lento e não posso executar testes em paralelo? Verdade, o teste fica lento, preciso de ambiente gráfico para execução e só é possível executar um teste por vez (por enquanto!).

Então, a cada entrada de teste o browser é aberto e ações externas são realizadas sobre ele. O responsável por realizar estas ações é o Selenium Server, aplicação console, que inicia um serviço que recebe as requisições e as envia ao browser. Também é responsável por capturar eventos e traduzí-los em teste de sucesso ou falha. O Selenium Server vem junto com o pacote do Remote Control. Este server é implementado em Java e precisa da máquina virtual para rodar. Exemplo de linha de comando para executá-lo:

java -jar selenium-server.jar -interactive

Após iniciar o servidor, basta executar os testes da sua IDE de preferência.

Problemas conhecidos

  • Utilize a opção multiwindow para iniciar o servidor do Selenium. Esta opção resolve problema quando a aplicação possui frames. A utilização de frames causa instabilidade no Selenium que utiliza um frame para execução dos seus comandos.
  • A ferramenta apresentou problemas para executar em um ambiente com proxy no meio. Se você tiver executando teste em aplicação web, na internet, e tenha um proxy no caminho poderá ter problemas. No site do Selenium informa que é compatível, testei mas não funcionou. Quem souber, pode comentar!

Conclusão

Este foi um breve post sobre esta ferramenta maravilhosa para testes funcionais na Web. Após várias pesquisas esta ferramenta foi a que mais se aproximou de critérios como teste de qualidade, facilidade, produtividade e estabilidade.

Bom galera, é isso aí. O post ficou um pouco longo mas objetivo. Prentendo incluir mais algumas informações práticas. Talvez um próximo post faço um exemplo de ponta a ponta de alguns testes em uma aplicação web por aí. Sugestões são aceitas.

Abraços e até a próxima!

quarta-feira, 5 de setembro de 2007

O início

Neste blog conversaremos sobre problemas rotineiros ligados a desenvolvimento de software, passando por dicas de linguagens, programação, frameworks, orientação a objetos... Essas conversas serão protagonizadas por Fernando Bichara, Wesley Gonçalves e, claro, quem mais quiser...

Sejam benvindos!