segunda-feira, 15 de setembro de 2014

Automação de Testes Funcionais com Selenium



Selenium é uma ferramenta para testar aplicações web pelo browser de forma automatizada. Selenium se refere ao Acceptance Testing (ou functional testing) que involve rodar testes num sistema finalizado. Os testes rodam diretamente num browser, exatamente como o usuário faria.

Por que testar?
Temos que testar o nosso código, mas em uma aplicação web fica dificil de testar a camada de apresentação, o resultado final. Como testar os custom tags (por exemplo erro.tag ou select.tag)? Como testar a compatibilidade entre browser diferentes de forma automatizada? Em geral, como testar que a página renderizada tem o resultado desejado?
Para isso serve Selenium, que se preocupa basicamente com duas tarefas
  • testes de funcionalidades da aplicação web
  • testes de compatibilidade entre browser e plataformas diferentes

Componentes do Selenium:
Dois componentes são importante para gerar e rodar testes com Selenium:
É um servidor escrito em java. Ele recebe chamadas http e executa os testes. As chamadas vem dos testes unitários (com junit, por exemplo). Este blog tem foco nesse componente.
É uma extensão do firefox. Com ela podemos criar testes. Ela funciona com um recorder e grava as ações do usuário. As ações podem ser transformadas em código em várias linguagens entre elas java.

Integração com JUnit
Vamos criar um teste de funcionalidade com Selenium e JUnit. Precisamos:
- uma aplicação web
- o selenium server
- o selenium test client com junit
Objetivo é testar um combo box numa página jsp. Vamos deixar o selenium abrir um browser, chamar a página e testar a combo box.

A página do aplicação web
Aqui tem uma página ( index.jsp) simples para testar a opção selecionada num combo box:
<html>
<head>
<title>Selenium e JUnit HowTo</title>
</head>
<body>
Size:
<select name=¿size¿>
<option id="x-large">X-Large</option>
<option id="large">Large</option>
<option id="medium selected>Medium</option>
<option id="small">Small</option>
<option id="tiny">Tiny</option>
</select>
</body>
</html>
Vamos supor que esta página é acessível pela url: http://localhost:8080/test/index.jsp

O Selenium Server
O servidor Selenium tem obviamente estar rodando antes de executar os testes de funcionalidade. Para iniciar o server precisamos o selenium-server.jar que está dentro do Selenium-RC download .
Executamos na linha de comando:
$java -jar selenium-server.jar
Existe um modo interativo do server para passar testes diretamente na linha de comando. Basta adicionar a opção -interactiv.
$java -jar selenium-server.jar -interactiv

O selenium client
Com a aplicação web e o servidor selenium rodando podemos escrever o teste com junit. Os métodos setUp e tearDown da classe de teste vão abrir e fechar a conexão com o servidor selenium. A classe DefaultSelenium é utilizado para a conexão. Aqui o selenium-java-client-driver.jar que vem com o Selenium RC é necessário:

new DefaultSelenium("localhost"4444, "*firefox /usr/lib/firefox/firefox-bin", "http://localhost:8080")
A porta 4444 é a padrão do Selenium, o terceiro parâmetro é o perfil do browser junto com o caminho executável (tem que ser binario mesmo), por último a url do servidor web. Existem perfis disponíveis para os browser mais usados do mercado.
Aqui temos o começo código do nosso teste unitário:
private static DefaultSelenium selenium;

@BeforeClass
public static void setup() {
String url = "http://localhost:8080";
selenium = new DefaultSelenium("localhost"4444, "*firefox /usr/lib/firefox/firefox-bin", url);
selenium.start();
}


@AfterClass
public static void tearDown() {
selenium.stop();
}
Falta agora o método de teste que abre a página index.jsp e verifica a opção selecionada no combobox:
@Test
public void testSelectedIdOfSizeComboBox() {
selenium.open("/test/index.jsp");
assertEquals(¿medium¿, selenium.getSelectedId("size"));
}
Ao rodar o teste o Selenium abrirá o firefox e chamará a página. Existem muitos métodos para que o Selenium preencha campos, submeta formulários, navegue entre as páginas e muito mais. Você pode utilizar o Selenium IDE e realizar as operações que deseja testar, e o Selenium IDE vai gerar um código com tudo o que você fez durante aquela sessão no browser, depois basta você adicionar as assertions desejadas, gastando pouco esforço para codificar a simulação de cliques e preenchimento de formulários.

Problemas com Firefox 2.0
Usando Firefox 2.0.1 eu tive problemas na versão atual do Selenium. Lendo o forum li que isso já foi resolvido no snapshot do selenium (que não está disponível atualmente) e será resolvido na próxima versão.

Versões usadas
  • selenium-remote-control-0.9.1-SNAPSHOT
  • selenium client 0.9.0
  • junit 4.1

Dica (Selenium IDE)
Podem-se encontrar em sites que usam AJAX, Portlets e DHTML alguns controles que possuem variação dinâmica em seu identificador. Veja, por exemplo, o ID desse controle gerado pela especificação de portlets Pluto:
id="Pluto_8A828179268FE1FD01268FE6FB8302AE__SELECTED_client_code"
Ao utilizar o Selenium IDE para gerar o script de teste automatizado, obtemos o seguinte comando em Selenese HTML:
type Pluto_8A828179268FE1FD01268FE6FB8302AE__SELECTED_client_code
O grande problema é que esse número muda de forma constante e aleatória. Como podemos tornar nosso teste no Selenium mais estável? Usando o comando contains dentro do XPath !
O comando modificado fica assim:
type //select[contains(@id,"Pluto_") and contains(@id, '_SELECTED_client_code')]
Fazendo essa pequena alteração obtemos scripts que conseguem trabalhar com identificadores dinâmicos que mudam aleatoriamente, algo comum em aplicações AJAX ou de portais . Uma dica fundamental para melhor uso do Selenium IDE.

MySQL Performance


Muitas vezes, um administrador do servidor de banco de dados DBA tem pouco controle sobre os aplicativos que usam o MySQL e é difícil encontrar gargalos. Este blog não tem como objetivo resolver todos os problemas, e sim apresentar um pouco das minhas próprias experiências com o mecanismos de armazenamento de bando de dados MySQL (pelo menos para MyISAM e InnoDB mais populares).
Tenha em mente que eu não sou um especialista neste campo. Quando tenho problemas com MySQL, eu luto com todas as forças para solucionar o problema sem vitimas. Cada aplicação tem as suas próprias peculiaridades e você precisa encontrá-las via log de consultas lentas.
Antes de fazer qualquer coisa, tenha em mente que a instalação padrão do MySQL geralmente funciona bem. Infelizmente performances máximas não pode ser alcançadas sem os ajustes para aumentar o desempenho e estabilidade.
Antes que você possa fazer qualquer coisa, você precisa habilitar o log de consultas lentas.
Execute:
# touch /var/log/slow-query.log 

para criar o arquivo slow-query.log
log-slow-queries = /var/log/slow-query.log long_query_time = 4 log-queries-not-using-indexes
(para o MySQL 5.0.x)
/etc/my.cnf (dentro [mysqld] ) e reinicie o mysql. Espere pelo menos 24-48 horas antes de prosseguir para a próxima etapa.
High performance tuning scripts
Mysqltuner
MySQLTuner é um script escrito em Perl que tem como objetivo ajudá-lo com as configuração do MySQL fazendo recomendações para aumentar a performance e estabilidade.
# wget mysqltuner.pl
# chmod +x mysqltuner.pl
# ./mysqltuner.pl
Leia as recomendações em Output e tente segui-las.
Tuning-primer
Tuning-primer é outro roteiro que leva informações de SHOW STATUS LIKE e SHOW VARIABLES LIKE para produzir recomendações legíveis para as variáveis de ajuste do servidor.
# wget http://www.day32.com/MySQL/tuning-primer.sh
# ./tuning-primer.sh
Além disso, ler a saída e tentar ver o que você pode fazer para resolver os problemas. Tenha em mente que você precisa reiniciar o mysql depois de adicionar algo ao arquivo / etc / my.cnf. No caso de algo der errado, verifique o log mysql (/var/log/mysqld.log).
MyTOP
Mytop é uma ferramenta baseada em console (não-gui) para monitorar as linhas e o desempenho geral de um MySQL
Para instalar o MyTop:
# wget http://jeremy.zawodny.com/mysql/mytop/mytop-1.6.tar.gz
# tar -xvzf mytop-1.6.tar.gz
# cd mytop-1.6
# perl Makefile.PL
# make
# make install
No caso de algumas bibliotecas Perl estarem faltando, você deve instalá-los via CPAN.
Por exemplo, ReadKey é necessário e você pode obtê-lo via cpan.
# cpan (pressione Enter várias vezes até chegar shell cpan)
#cpan> install Term::ReadKey
#cpan> quit
Exemplo: # mytop -d DATABASE -u USERNAME -p PASSWORD (troque os valores de DATABASE, USERNAME e PASSWORD)

MySQLReport
MysqlReport faz um relatório amigável de importantes valores do estado do MySQL. O MysqlReport transforma um simples comando como ¿SHOW STATUS¿ em uma maneira fácil de ler o relatório fornecendo uma compreensão profunda de como o MySQL está sendo executado. MysqlReport é uma alternativa melhor (e praticamente a única alternativa) para interpretar manualmente SHOW STATUS.
# wget http://hackmysql.com/mysqlreport
# chmod +x mysqlreport
# ./mysqlreport --user root --password