Apostila do JMeter

Transcrição

Apostila do JMeter
Capítulo
1
Automação de Testes de Desempenho e Estresse
com o JMeter
Ismayle de Sousa Santos, Pedro de Alcântara dos Santos Neto
Resumo
A atividade de teste é uma das atividades relacionadas à garantia da qualidade de software. Existem vários tipos de testes, mas no cenário atual, em que a maioria dos sistemas
está voltada para a Web, os testes de desempenho e estresse têm um destaque especial. É
através deles que podemos verificar, dentre outras coisas, a performance e a capacidade
de recuperação de falhas do sistema. O custo dos testes, entretanto, é geralmente alto,
não sendo raro que esse custo chegue a 40% do esforço total de um projeto. Por isso
a importância do uso de ferramentas de automação de testes. O objetivo deste curso é
apresentar os conceitos relacionados aos testes de desempenho e estresse, bem como a
utilização do JMeter, uma ferramenta de automação apropriada para esse tipo de teste.
1.1. Introdução
O desenvolvimento de sistemas de software envolve uma série de atividades em que a
possibilidade de injeção de erros são enormes. Por conta disso, o teste de software é um
elemento crítico na garantia da qualidade de um produto, atuando como uma revisão final
da especificação, desenho e geração de código. Ao realizarmos testes durante o desenvolvimento de software adicionamos valor ao produto, uma vez que o teste corretamente
executado tende a descobrir falhas, que devem ser corrigidas, aumentando assim a qualidade e confiabilidade de um sistema [7].
Apesar de sua importância, os testes muitas vezes não são executados visto que a
realização dessa atividade é geralmente bastante onerosa em um desenvolvimento. Dependendo do tipo de sistema a ser desenvolvido, ela pode ser responsável por mais de 50%
dos custos [7]. Para se ter uma idéia dos custos envolvidos, de acordo com um relatório
publicado pelo NIST [6], U$59.500.000.000,00 é o valor relativo ao custo de falhas em
softwares desenvolvidos nos Estados Unidos, apenas em 2002. Esse mesmo relatório estima que mais de 37% desse custo (U$22.200.000.000,00) poderia ter sido eliminado se
a infraestrutura para teste fosse melhorada.
O teste de software é a verificação dinâmica do funcionamento de um programa
utilizando um conjunto finito de casos de teste, adequadamente escolhido dentro de um
domínio de execução infinito, contra seu comportamento esperado [3]. Nesse conceito
existem alguns elementos chaves:
• dinâmica: o teste exige a execução do produto, embora algumas de suas atividades
possam ser realizadas antes do produto estar operacional;
• conjunto finito: o teste exaustivo é geralmente impossível, mesmo para produtos
simples;
• escolhido: é necessário selecionar testes com alta probabilidade de encontrar defeitos, preferencialmente com o mínimo de esforço;
• comportamento esperado: para que um teste possa ser executado é necessário saber
o comportamento esperado, para que ele possa ser comparado com o obtido.
Com base no que foi exposto anteriormente é possível notar a importância da
utilização de ferramentas que automatizem a criação e execução dos testes. Neste trabalho
apresentamos uma visão geral sobre os testes de desempenho e estresse, destacando como
automatiza-lo a partir do uso da ferramenta JMeter. Utilizamos a seguinte estrutura neste
trabalho: na próxima seção apresentamos os conceitos de testes de desempenho e estresse;
em seguida, o JMeter e seus principais componentes são descritos; por fim, descrevemos
um exemplo da utilização do JMeter em um sistema, além de concluirmos o trabalho com
algumas observações relacionadas a tal tipo de teste.
1.2. Testes de Desempenho e Estresse
Testes de desempenho consistem em testar um sistema quanto aos seus requisitos de desempenho. Alguns exemplos desses requisitos são[2]:
• Latência, que é o tempo entre uma requisição e a completude e resposta da operação
requisitada;
• Vazão (throughput), o número de operações que o sistema é capaz de completar em
um dado período de tempo;
• Escalabilidade, a quantidade de usuários simultâneos que o sistema pode lidar;
• Uso de recursos de máquina, como memória e processamento.
Para a correta execução desse tipo de teste é necessário que haja um conjunto
bem definido de objetivos para esses requisitos, do contrário, esses testes serão medições
cegas [8]. Apesar de um teste de desempenho completo e ideal depender da existência
de um sistema totalmente integrado e funcional, no contexto sobre o qual o mesmo irá
funcionar, testes de desempenho são freqüentemente aplicados em todos os passos do
processo de teste [7]. Isso está fundamentado na máxima que diz que quanto mais cedo
uma falha é detectada, mais eficiente e barata é a sua solução, principalmente levando em
consideração o fato de que a maioria dos problemas críticos de desempenho advém de
decisões feitas em estágios iniciais do ciclo de desenvolvimento do software [2].
Testes de estresse normalmente são feitos juntamente com testes de desempenho,
não raro havendo confusão entre os mesmos. Enquanto o teste de desempenho tem como
objetivo testar se determinado sistema é capaz de lidar com a carga definida nos requisitos, o teste de estresse consiste em submeter o sistema a situações anormais de uso [5],
como grandes quantidades de carga, comportamento anormal de portas em um servidor,
redução dos recursos computacionais disponíveis, entradas não realistas de dados. Assim,
é possível observar o comportamento do sistema durante essas situações críticas, identificando falhas potencialmente difíceis de serem encontradas em situações normais, mas
não toleráveis, como o vazamento de informações confidenciais de um banco de dados
em mensagens de erro, por exemplo [1].
Testes de desempenho e estresse geralmente são onerosos. Eles demandam instrumentação de software e hardware, além de testadores hábeis e com bom conhecimento nas
ferramentas escolhidas. São testes caros, porém importantes, pois em softwares de médio a grande porte, os principais problemas relatados após a entrega do software estão
relacionados à degradação de desempenho ou a incapacidade do sistema de lidar com a
vazão exigida. Isso acontece porque é comum o software ser largamente testado quanto à
funcionalidade, mas não ter seu desempenho apropriadamente testado [8].
Além disso, com a consolidação dos sistemas Web, questões relativas ao desempenho e comportamento sob estresse ganharam ainda mais visibilidade. Isso porque no
contexto de alta competitividade como é o atual, a performance desses sistemas reflete
diretamente na satisfação ou não do seu público.
1.3. JMeter
O Apache JMeter, cuja tela principal é apresentada na Figura 1.1, é uma aplicação desktop
projetada para a realização de testes de desempenho e estresse em aplicações cliente/servidor,
tais como aplicações Web. Ele pode ser usado para simular cargas de trabalho em um
servidor, rede, aplicações ou mesmo em um objeto, testando sua robustez. O seu desenvolvedor original foi Stefanno Mazzochi, membro da Apache Software Foundation, mas
hoje a ferramenta, que é Open Source, é resultado do trabalho de milhares de pessoas [4].
Por ser uma ferramenta inteiramente escrita em Java, o JMeter é compatível com
qualquer ambiente capaz de suportar a máquina virtual Java versão 1.4 ou superior. O
JMeter também permite a criação de testes para diversos protocolos, como HTTP, JDBC,
FTP, SOAP, dentre outros, podendo inclusive ser utilizada para testar objetos implementados em Java.
Além de poder ser usado para criação e execução de testes de desempenho e estresse, o JMeter também permite a realização de testes funcionais. Isso é possível graças
aos vários tipos de asserções que ele possui e que podem ser usadas para verificar os resultados das requisições enviadas ao objeto de teste. Essas asserções aceitam inclusive
expressões regulares, o que lhes agrega mais poder e flexibilidade.
No JMeter, a organização dos elementos que compõe o teste é feita através de
uma árvore hierárquica, cuja raiz é o Plano de Teste (TestPlan). Na Figura 1.1 é possível
Figura 1.1. Tela principal do Apache JMeter.
observar a árvore mencionada. Alguns elementos da árvore de teste são hierárquicos,
como os Listeners (relatórios) e as Assertions (asserções), pertencendo e referenciando
a outros elementos da ordem hierárquica superior. Outros elementos, como os Samplers
(requisições), são primariamente ordenados e, portanto, a ordem na qual aparecem verticalmente na árvore determina sua ordem de execução. Essa organização também é refletida no arquivo XML gerado pela ferramenta para a persistência dos elementos. Nesse
arquivo, ilustrado na Figura 1.2, cada elemento do script de teste corresponde a um elemento na estrutura XML.
Quanto a execução dos testes com o JMeter, ela pode ser feita de duas formas: em
uma máquina só ou de forma distribuída, na qual o esforço do teste é distribuído dentre
diversas máquinas. A partilha do esforço do teste é uma característica muito importante
e muitas vezes necessária para a correta execução dos testes de desempenho e estresse.
É através dela que os testadores podem conseguir uma maior fidelidade na recriação de
cenários de teste, pois com a distribuição da execução do teste entre várias máquinas
evita-se gargalos tanto de processamento quanto de caminhos na rede do sistema sob
teste.
1.4. Componentes do JMeter
Um Plano de Testes é para o JMeter um conjunto de elementos que descrevem uma série
de passos que serão executados. Assim, um teste bem definido geralmente incorpora
vários componentes do JMeter. Para adicionar, deletar, copiar ou mover um elemento
Figura 1.2. Trecho do arquivo XML gerado pelo JMeter.
(componente) de um script de teste, basta clicar com o botão direito do mouse sobre o
elemento e escolher a opção desejada. Um componente também pode "conter"outro componente. Nesse caso, diz-se que um é o "filho", o que está a uma hierarquia inferior, e
o outro é o "pai", que está em uma hierarquia superior a do filho e com o qual o filho
está ligado. Na Figura 1.1, por exemplo, o primeiro "Duration Assertion"é filho da requisição nomeada de "Login", todos os elementos da mesma hierarquia ou inferior ao dessa
requisição são filhos do Thread Group, que é por sua vez filho do Test Plan.
O JMeter possui vários componentes que podem ser usados na criação dos testes.
Essa sessão, entretanto, abordará apenas aqueles mais usados e diretamente ligados à
criação e execução de testes automatizados para sistemas Web.
1.4.1. Elementos Básicos
Os elementos denominados aqui como "Básicos", são os componenetes do JMeter que devem estar presentes em todos os testes criados/executados com ele. Os elementos referidos são.
• Test Plan: componente que representa o plano de teste;
• WorkBench: é uma espécie de "área de trabalho". Assim, todos os elementos que
forem seu filho não serão executados: eles são utilizados apenas como área de
armazenamento temporário, para a composição do teste;
• Thread Group: contém a configuração do grupo de usuários virtuais, onde cada
usuário corresponde a uma thread que é lançada e controlada pelo JMeter e que
simula a navegação do usuário na aplicação sob teste.
Os dois primeiros elementos citados anteiormente estão presentes no script de
teste desde o momento em que o JMeter é iniciado. Já o Thread Group deve ser adicionado
manualmente. A primeira ação a ser feita após a adição do Thread Group é configurar o
Test Plan, ilustrado na Figura 1.3.
Figura 1.3. Test Plan - plano de teste
Nele é possível definir um nome identificador para o Plano do Teste, adicionar
comentários, criar variáveis globais, que são visíveis por todas as requisições do plano de
teste em questão, além de permitir a definição de parâmetros ou comportamentos comuns
a todos os testes. Além disso, o Test Plan contém duas caixas de seleção (checkbox):
• "Functional Testing", que se selecionada faz com que o JMeter grave os dados retornados do servidor para cada requisição feita. Essa opção interfere significamente
no desempenho da ferramenta e, portanto, não deve estar marcada no caso de um
teste de desempenho ou estresse.
• "Run each Thread Group separately", com o qual pode-se definir se os grupos de
usuários virtuais serão executados simultaneamente ou sequencialmente.
Como supracitado, o Thread Group, ilustrado na Figura 1.4, representa um grupo
de usuários virtuais. Podemos ter vários Threads Groups ligados ao Test Plan, e todos
os outros elementos, com exceção do WorkBench, devem ser adicionados como filho de
algum Thread Group.
Figura 1.4. Thread Group - grupo de usuários virtuais
Na criação de testes com o JMeter, após configurar o Test Plan, o testador deve
configurar o Thread Group, ou seja, deve definir suas propriedades.
• "Number of threads": o número de threads que executarão os testes, ou seja, o
número de usuários virtuais. Cada thread irá executar o plano de teste de forma
independentemente das outras threads que estão executando, por isso threads múltiplas são usadas para simular conexões concorrentes na aplicação sob teste;
• "Ramp-Up Period": define a frequência de lançamento das threads. Se forem
definidas 10 threads e um ramp-up de 100s, então o JMeter levará 100s para iniciar
todas as threads, ou seja, uma thread será iniciada a cada 10s.
• "Loop Count": define quantas vezes o plano de teste será executado. Logo, caso
seja marcado o checkBox "Forever", o teste entrará em execução infinta e o valor
definido no Loop Count será desconsiderado.
• "Scheduler": através do qual pode-se definir um horário para o início e término da
execução dos testes. Ao contrário das citadas anteriormente, a configuração dessa
propriedade é opcional.
1.4.2. Sampler
Samplers são componentes que representam cada requisição que o JMeter fará ao servidor
quando o plano de teste for executado. No caso de um sistema Web, cada operação
ou mudança de página corresponde a uma requisição. O JMeter contém vários tipos
de Samplers, como por exemplo, FTP Request, HTTP Request, JDBC Request, dentre
outros. Cada Sampler contém várias propriedades que podem ser configuradas. Como o
objetivo deste artigo é apresentar a automação de testes de desempenho e estresse para
aplicações web, apresentamos a seguir apenas o HTTP Request (Requisição HTTP).
1.4.2.1. HTTP Request
O HTTP Request permite o envio de requisições HTTP/HTTPS ou arquivos para um
servidor Web. Na Figura1.5 apresentamos um exemplo de um HTTP Request adicionado
a um Plano de Teste.
Figura 1.5. HTTPRequest - Requisição HTTP
Dentre as propriedades desse elemento podemos destacar:
• "Name": o nome da requisição;
• "Server": URL ou endereço ip do servidor Web;
• "Port": a porta a ser usada. Por default ela já está configurada como 80.
• "Protocol": define se a requisição é HTTP, HTTPS or FILE (para enviar arquivo ao
servidor);
• "Method": define o método de submissão dos dados. Os principais métodos são o
GET, no qual os dados são enviados na própria URL, e POST, onde os dados são
enviados "ocultamente"na requisição, ou seja, não são visíveis na URL;
• "Path": o path da página testada;
• "Send Parameters With the Request": no qual adicionamos todos os parâmetros e
os seus respectivos valores para serem enviados junto com a requisição;
1.4.3. Logic Controllers
Os Logic Controllers são usados para alterar a execução do plano do teste. Com eles
é possível, por exemplo, selecionar qual requisição será enviada dentre um conjunto de
requisições, repetir a execução de requisições e executar requisições somente sob certas
condições. Serão apresentados aqui os principais controladores lógicos: "Simple Controller", "Loop Controller", "Once only Controller", "Interleave Controller" e "If Controller".
1.4.3.1. Simple Controller
Os Simple Controllers são elementos que não causam nenhuma alteração na execução
dos testes, sendo utilizado somente para organizar a árvore do plano de teste. Com ele o
usuário pode agrupar Samplers e outros elementos de forma a deixar o teste mais organizado e inteligível. Uma ilustração dessa situação pode ser visualizada na Figura 1.6, onde
três Simpler Controller são usados para agrupar as requisições de forma a permitir a fácil
identificação de quais delas são executadas em cada um dos dois casos de uso, Login ou
Usuario, do sistem sob teste.
1.4.3.2. Loop Controller
O Loop Controller (Figura 1.7) é o componente no qual é possivel determinar quantas
vezes um certo grupo de requisições deve ser executado. Esse elemento atua independentemente da propriedade "Loop Count"do Thread Group. Assim, se o plano de teste
foi configurado para ser executado três vezes e existe uma "requisição A"que está como
filho de um Loop Controller configurado para ser executado 2 vezes, então a requisição
em questão será executada 3 ∗ 2 = 6 vezes.
Figura 1.6. SimpleController - Controlador Simples
Figura 1.7. LoopController - Controlador de Loop
1.4.3.3. Once Only Controller
O Once Only Controller, ilustrado na Figura 1.8, permite que as requisições controladas
por ele, assim como seus filhos, sejam executados uma única vez por cada thread. Dessa
forma, a requisição que está sobre o efeito desse elemento só será executada na primeira
iteração do teste. Testes que requerem um único login para estabelecer a sessão podem
ser criados utilizando uma requisição que faça o login como filho de um Once Only Controller. Assim, o login só é executado apenas uma vez por cada thread.
Figura 1.8. OnceOnlyController - Controlador de execução única
1.4.3.4. Interleave Controller
O Interleave Controller é usado para alternar entre seus filhos a cada iteração, com base na
ordem em que eles estão dispostos. No exemplo ilustrado na Figura 1.9, apresentamos um
teste que foi configurado para iterar duas vezes, tendo a seguinte sequência de execução:
Requisição A, Requisição B, Requisição A, Requisição C.
Figura 1.9. InterleaveController - Controlador de Alternância
O JMeter também possui o Random Controller, que é similar ao Interleave Controller. A única diferença entre eles é o fato desse não alternar entre as requisições com
base na ordem em que foram colocadas. O Random Controller simplesmente escolhe
aleatoriamente um dos seus filhos a cada iteração.
1.4.3.5. If Controller
Com o If Controller é possível colocar uma condição que será avaliada para definir se o
seu filho vai ser executado ou não. No exemplo ilustrado na Figura 1.10, a "requisição
A"só será executada se a variável "var"tiver valor menor que 10. É importante observar
também como é feita a referência a variáveis no JMeter: devemos utilizar o nome da
variável (var) entre chaves e precedida de cifrão ($).
Figura 1.10. ifController - Controlador IF
1.4.4. Listeners
Para visualizar os resultados dos testes é necessário adicionar um Listener ao plano de
teste. Os Listeners capturam os dados das informações durante a execução dos testes e
criam relatórios e gráficos com os resultados obtidos. Além de exibir os resultados, os listeners também possibilitam a geração de um arquivo, que pode ser inclusive uma planilha
eletrônica, contendo tais resultados. Existem vários tipos de Listeners, mas apenas três
serão abordados a seguir : "View Results Tree", "Assertion Results" e "Graph Results".
1.4.4.1. View Results Tree
O View Results Tree é um listener que mostra uma árvore com as respostas de todos os
samplers, permitindo assim que o testador veja o resultado de cada sampler que foi executado. Através dele, o usuário também toma conhecimento do tempo gasto para obtenção
da resposta, além de outras informações associadas à requisição, como por exemplo, a
URL acessada e os parâmetros enviados. Esse elemento também permite visualizar o
resultado de várias formas diferentes, como por exemplo, no formato texto, HTML ou
XML. A Figura 1.11 ilustra a utilização desse listener. A partir da figura podemos observar que esse Listener é ideal para visualizar o que exatamente o usuário final deveria de
acordo com cada requisição.
1.4.4.2. Assertion Results
O Assertion Results permite uma visualização do resultado das asserções que falharam.
Além de indicar qual requisição teve falha na asserção, ele indica qual asserção falhou
(Response ou Duration), e o porquê da falha. No exemplo ilustrado na Figura 1.12, por
exemplo, ele mostra que o Response Assertion da "requisição A"falhou, pois ele procurou
pela palavra "teste"e não a encontrou na página resultante da execução dessa requisição.
1.4.4.3. Graph Results
O Graph Results, ilustrado na Figura 1.13, gera um gráfico que plota os tempos de todas
as requisições, o desvio padrão, a média e a taxa de requisições realizadas por segundo. O
Figura 1.11. View Results Tree - Visualizador dos Resultados em árvores
Figura 1.12. Assertion Results - Visualizador dos Resultados das Asserções
testador tem a possibilidade de optar por quais desses dados ele quer visualizar no gráfico
e esse Listener, assim como os outros, permite a indicação de um arquivo para exportar a
visualização gerada.
1.4.5. Configurations Elements
Os Configurations Elements são elementos que podem adicionar ou modificar dados das
requisições. Os principais Configurations Elements utilizados em testes para aplicações
Web são o "HTTP Cookie Manager", usado para manter a sessão, e o "HTTP Request
Figura 1.13. Graph Results - Visualizador dos Resultados em um Gráfico
Defaults", para definir o servidor que será usado por todas as HTTP Requests da sua
hierarquia ou inferior.
1.4.5.1. HTTP Cookie Manager
Esse elemento, ilustrado na Figura 1.14 , pode ser usado de duas formas: sem preencher
nenhum valor ou configurando o Cookie manualmente. No primeiro caso, esse componente guarda e envia os cookies como um browser e atua como se houvesse um Cookie
Manager para cada thread. Isso quer dizer que após o JMeter receber a resposta de uma
requisição, se ela contiver um cookie, esse será armazenado e enviado para as próximas
requisições para o mesmo site. Já no segundo, quando o testador adiciona manualmente
um cookie, o Cookie Manager servirá para compartilhar o mesmo cookie entre todas as
threads.
Figura 1.14. HTTP Cookie Manager - Gerenciador do Cookie de requisições HTTP
1.4.5.2. HTTP Request Defaults
Esse elemento permite a definição de propriedades para serem utilizados por todos os
HTTP Request da sua mesma hierarquia ou e, uma hierarquia inferior. Se um teste contiver, por exemplo, 30 requisições para um mesmo site, então elas provavelmente acessarão o mesmo servidor. Assim, ao invés de definirmos em cada HTTP Request o servidor, colocamos o endereço do servidor apenas no HTTP Request Defaults, ilustrado na
Figura 1.15, restanto às HTTP Requests definir apenas os path e os parâmetros das páginas testadas.
Figura 1.15. HTTP Request Defaults - Padrão das Requisições HTTP
1.4.6. Assertions
Os Assertions permitem a validação das respostas recebidas do servidor que está sendo
testado. Com as assertions, o testador obtém a certeza de que a aplicação está retornando
o resultado esperado. Isso porque ela faz com que o JMeter procure determinado texto
dentro do conteúdo retornado de uma requisição. Se o texto não for encontrado a asserção
falhará. Em testes para servidores Web, duas assertions são muito utilizadas: "Response
Assertion"e "Duration Assertion".
1.4.6.1. Response Assertion
O Response Assertion faz com que o JMeter procure por um determinado texto, definido
pelo testador, na requisição obtida como resposta. A procura por esse texto é feito
utilizando-se o sistema de expressão regular presente na ferramenta. Caso o texto não
seja encontrado, a asserção falhará e aparecerá no Assertion Results em vermelho, aparecendo destacado no View Results Tree, caso esses elementes estejam adicionados a um
plano de teste. Na Figura 1.16 , por exemplo, temos uma Response Assertion que possui
um único objetivo, que é encontrar a palavra "teste"na reposta da requisição a qual ele
está associado.
Figura 1.16. Response Assertion - Asserção na Resposta
1.4.6.2. Duration Assertion
O Duration Assertion, ilustrado na Figura 1.17, é usado para definir o tempo máximo que
o sistema tem para responder a uma requisição. Caso a obtenção da resposta demore mais
que o tempo definido, a asserção falhará. Essa assertion é muito utilizada, pois a partir
dela podemos verificar o atendimento a um dos principais requisitos de desempenho: o
tempo de resposta das requisições.
Figura 1.17. Duration Assertion - Asserção do Tempo de Resposta
1.4.7. Timers
Por default, o JMeter envia as requisições das threads sem pausar um tempo entre elas.
Isso significa que as requisições serão disparadas rapidamente, uma seguida da outra.
Como os usuários sempre analisam os resultados obtidos antes de executar a próxima
ação, Timers devem ser usados para simular paradas entre as requisições, tornando-as
mais realistas. Existem vários tipos de timers, mas para simplificar, apresentamos aqui
apenas o mais simples deles, o "Constant Timer", ilustrado na Figura 1.18. Esse timer
define o tempo em milisegundos que cada thread deve aguardar entre as requisições.
Figura 1.18. Constante Timer - Tempo constante entre as requisições
1.4.8. Pre-Processors
Um Pre-Processor é um elemento que executa certas ações antes da requisição ser enviada. Eles são utilizados para modificar características ou atualizar valores de variáveis das
requisições antes que estas sejam executadas. Dentre os Pre-Processors disponíveis temos
o Counter, ilustrado na Figura 1.19, que representa um contador que pode ser referenciado em qualquer lugar do Plano de Testes. Ele pode ser usado, por exemplo, para colocar
um valor único em um certo campo em cada iteração. Para isso, basta colocar como valor
desse campo uma string qualquer seguido da referência à variável que contém o valor do
contador, o "Reference Name"do contador. Suponhamos, por exemplo, que temos como
parâmetro de uma requisição, um campo com nome "login", cujo valor deve ser único
toda vez que essa requisição for executada. Uma possível solução seria acrescentar um
contador, definir suas propriedades (valor inicial, vamor máximo, incremento, nome da
variável) e colocar "login${cont}", onde "cont"é o nome da variável do contador, como
valor do campo "login".
Figura 1.19. Counter - Contador
1.4.9. Post-Processors
Um Post-Processor é um elemento que executa uma ação depois que uma requisição é
executada. Geralmente eles são utilizados para processar os dados recebidos da requisição
e os seus resultados são utilizados para modificar as requisições seguintes. Dentre os
Post-Processors, destacamos o Regular Expression Extractor, ilustrado na Figura 1.20,
que permite ao testador extrair valores da resposta proveniente do servidor a partir de
expressões regulares.
Figura 1.20. Regular Expression Extractor - Extrator de Expressões Regulares
1.5. Criando testes de desempenho e estresse automatizados
Esta sessão tem por objetivo apresentar um pequeno exemplo de utilização da ferramenta
para a automação de testes de desempenho e estresse de um sistema Web. O objeto de
teste referido é uma parte de um gerador (sistema) de páginas Web para usuários leigos.
A função desse gerador é tornar simples a criação de páginas, seguindo um formato préestabelecido. Os usuários do sistema podem criar menus laterais, notícias, destaques,
usuários para administrar as páginas e links para outras páginas e arquivos. Esse sistema
possui no total 8 casos de uso, mas iremos abordar aqui apenas o caso de uso Usuários,
que corresponde as operações de inclusão, alteração, busca e remoção de um usuário
desse sistema.
Para iniciar a criação desse teste, primeira coisa a ser feita é a inserção do Thread
Group e configuração do nosso Test Plan. Com base nos requisitos definidos para esse
sistema, configuramos o teste para 100 usuários simultâneos a serem disparados em 50
segundos. Também colocamos o teste para repetir por três vezes, para assim confirmarmos os padrões de comportamento do sistema, como por exemplo, a identificação de que
certa operação sempre demora mais que o esperado. Para mantermos o teste organizado
adicionamos quatro Simpler Controllers, cada um nomeado com a operação cujas requisições filhos irão realizar. O resultado pode ser visualizado na Figura 1.21.
Figura 1.21. Plano de Teste do caso de uso Usuário
Em seguida, adicionamos os listeners, o View Resulsts in Tree e o Graph Results.
E como os testes seriam todos para um mesmo servidor, acrescentamos também o HTTP
Request Defaults, configurando-o com o endereço do servidor que será testado e o HTTP
Cookie Manager, pois para acessar o sistema é preciso logar e é necessário manter a
sessão do usuário logado para permanecer no sistema. O estado do Test Plan com essas
cofigurações é ilustrado na Figura 1.22 .
Por fim, basta colocar as requisições que realizam as operações, bem como as
asserções para verificar o atendimento aos requisitos de desempenho. Primeiro criamos
a requisição "Login", cuja função é fazer o usuário virtual logar na página. Como já
tinhamos configurado o HTTP Request Default, só precisamos agora definir o path e os
parâmetros da página testada, que no caso da requisição "Login"são os campos login e
senha.
Existem caraterísticas importantes que devem ser observadas nesse ponto. Em
primeiro lugar, o path supracitado não é qualquer path do sistema. O path em questão é o
path que tratará os dados provenientes da requisição. Logo, para a configuração correta,
muitas vezes é necessário olhar o código-fonte da página ou algum documento que tenha
Figura 1.22. Plano de Teste do caso de uso Usuários com as configurações gerais
toda a configuração dela, a fim de descobrir qual página receberá aqueles dados. Na
página de login do usuário, por exemplo, verificamos que a página que trata os dados é
a própria página que os recebe. Assim, o path dessa requisição é o mesmo path onde o
usuário insere os dados. Isso pode ser facilmente visualizado através do código-fonte da
página onde o usuário insere o login e a senha, ilustrado na Figura 1.23. Nele observamos
que a ação do formulário que recebe o login e a senha está em branco, oncluindo então
que ela própria recebe e trata o login e a senha.
Outro detalhe que merece ser mencionado está relacionado aos re-direcionamentos
de alguns sistemas Web. No sistema utilizado neste trabalho, por exemplo, quando o
usuário efetua a operação de login, o sistema redireciona para a mesma página, se o login
falhar, ou para a página principal caso o login seja bem sucedido. O problema é que se a
opção Follow Redirects não estiver marcada, o JMeter não "seguirá"esse redirecionamento
e, portanto, continuará na mesma página para o qual os dados foram enviados. Assim, devemos desmarcar a opção Redirect Automatically, que não segue os re-direcionamentos
que vem como resposta de uma requisição, e marcar a opção Follow Redirects.
Além disso, devemos colocar como método de submissão aquele utilizado pela
página (GET,POST,...) e adicionar os parametros necessários. No nosso exemplo, a partir
do código-fonte, ilustrado na Figura 1.23, identificamos que o método utilizado é o POST
e observamos que os campos necessários não eram somente "login"e "senha". Para o
correto funcionamento da requisição é necessário colocar também o campo "enviado".
Isso porque os campos hidden são usados pela página para identificar a submissão de
Figura 1.23. Código-fonte da página de login do usuário do sistema
dados, logo são campos necessários para a execução da operação requisitada. Nesse caso
devemos preencher os valores respectivos dos campos login e senha, colocando também o
valor do campo "enviado"como sendo o valor definido na sua propriedade value, ou seja,
o valor "ok". Como resultado de todas essas configurações, o login foi bem sucedido,
como é visto na Figura 1.24.
Figura 1.24. Execução da requisição "Login"do estudo de caso
Como basta um login para cada usuário virtual, colocamos a requisição de login
como filho do controlador Once Only Controller. Continuando a automação do teste, in-
serirmos uma Response Assertion, para nos certificarmos que a página alvo foi alcançada
e um Duration Assertion, para medirmos o tempo gasto para responder a essa requisição.
Por último, devemos criar as outras requisições seguindo os mesmos passos: descobrindo
o path, colocando os campos, o método, adicionando um duration e um response assertion.
Feitas todas as requisições, notamos que algumas asserções da requisição de Inserção de Usuário falhavam. Observamos então que isso acontecia porque na inserção
de Usuário o campo "login", que nesse caso era o nome de login do usuário, deveria ser
único para cada usuário. Adicionamos então um Count, e modificamos o valor do campo
login para usuario${cont}, em que "cont"é o nome da variável que contém o valor do
contador. Isso significa que durante a execução desses testes estamos inserindo usuários
com os logins usuario1, usuario2, usuario3, etc, ou seja, criaremos um login único para
cada usuário. Feito isso, temos agora um teste automatizado de desempenho e estresse
para o caso de uso Usuário, teste esse visualizado na Figura 1.25.
Figura 1.25. Teste automatizado de desempenho e estresse para o caso de uso
Usuário do sistema testado
Além da construção dos testes, a análise dos seus resultados é importante para
se identificar as áreas críticas do sistema. Os resultados da execução do nosso exemplo,
em forma de gráfico, podem ser visualizados na Figura 1.26. Com esses dados, aliados
aos resultados exibidos no View Results Tree, adicionado ao plano de teste, podem ser
utilizados pelo testador para avaliar sobre o atendimento da aplicação aos requisitos de
desempenho existentes.
Figura 1.26. Gráfico resultante da execução dos testes
1.6. Conclusão
A atividade de Teste é fundamental para a garantia da qualidade dos produtos desenvolvidos. Dentre os diversos testes, destacamos os testes de desempenho e estresse, que estão
crescendo em importância, uma vez que os sistemas para Web cada vez ganham mais espaço em relação aos sistemas desktop. Esses testes ainda são pouco utilizados no cenário
atual e como os custos associados a sua execução são altos, a utilização de ferramentas que automatizem a criação e execução dos mesmos é essencial. Além disso, fazer
medições de tempo de resposta e simular muitos usuários acessando ao mesmo tempo
uma aplicação é inviável e muitas vezes até impossível de se fazer sem uma ferramenta
que automatize o processo.
Neste trabalho apresentamos a automação de testes de desempenho e estresse para
sistemas Web através de uma ferramenta de automação desses testes. Para isso, descrevemos os principais componentes do JMeter, uma ferramenta de automação desses testes, e
apresentamos um estudo de caso de forma a esclarecer os procedimentos necessários para
se automatizar os testes de desempenho e estresse com a ferramenta em questão. E com o
que foi apresentado aqui, podemos concluir que no mercado competitivo como é o atual,
investir em testes de software e em ferramentas que automatizem a sua realização pode
ser a chave de sucesso para muitas empresas.
Referências
[1] R. Binder. Testing Object-Oriented Systems: Models, Patterns, and Tools. AddisonWesley, 2000.
[2] G. Denaro, A. Polini, and W. Emmerich. Early performance testing of distributed
software applications. In WOSP ’04: Proceedings of the 4th international workshop on Software and performance, pages 94–103, New York, NY, USA, 2004. ACM
Press.
[3] IEEE. Guide to the Software Engineering Body of Knowledge. IEEE Computer
Society, 2004.
[4] A. JMETER.
Aplicação desktop projetada para testes de carga e medidas de performance.
Technical report, Apache Software Foundation,
http://jakarta.apache.org/jmeter/. último acesso em 17/11/2008.
[5] G. Myers. The Art of Software Testing. John Wiley & Sons, 1979.
[6] NIST. Planning Report 02-3, National Institute of Standards and Technology,
http://www.nist.gov/director/prog-ofc/report02-3.pdf, 2002.
[7] R. Pressman. Engenharia de Software. McGraw-Hill, 6th edition, 2006.
[8] E. J. Weyuker and F. I. Vokolos. Experience with performance testing of software
systems: Issues, an approach, and case study. IEEE Transactions on Software Engineering, 26(12):1147–1156, 2000.

Documentos relacionados

Manual de Utilização da Ferramenta JMeter

Manual de Utilização da Ferramenta JMeter executados. Os principais componentes adicionados ao “TestPlan” são: • Listeners - elementos que capturam os resultados gerados pelo plano de testes e apresenta-os em um determinado formato, com vi...

Leia mais