FERRAMENTA PARA EXECUÇÃO DE TESTES AUTOMATIZADOS … · expressava as dificuldades do...
Transcript of FERRAMENTA PARA EXECUÇÃO DE TESTES AUTOMATIZADOS … · expressava as dificuldades do...
FERRAMENTA PARA EXECUÇÃO DE TESTES
AUTOMATIZADOS EM CLUSTER
Carlos Alberto Barth
Vandir Fernando Rezende
UDESC – Universidade do Estado de Santa Catarina [email protected]; [email protected]
Resumo
Este artigo apresenta uma alternativa para equipes de desenvolvimento de software, que visam
garantir a qualidade do software de forma eficaz e economica através dos testes automatizados,
porém se deparam com longos tempos de execução dos testes. A proposta deste trabalho foi
reduzir o tempo de execução através de clusters, obtendo o resultado da execução em 22% do
tempo inicial.
Palavras-chave: Testes Automatizados. Integração Contínua. Cluster.
Abstract
This paper presents an alternative for software development team, seeking to ensure the quality
of the software effectively and economic through automated tests, but are faced with long test
runtimes. The purpose of this work is to reduce this runtime using cluster, getting the result of
running on 22% of the initial time.
Keywords: Automated Tests. Continuous Integration. Cluster.
1. Introdução
A engenharia de software tem como base a busca de ferramentas e métodos para garatir a
qualidade dos sistemas desenvolvidos. Criada na década de 70, durante a crise do software,
expressava as dificuldades do desenvolvimento de software frente ao rápido crescimento da
demanda por software, da complexidade dos problemas a serem resolvidos e da inexistência de
técnicas estabelecidas para o desenvolvimento de sistemas que funcionassem adequadamente ou
pudessem ser validados (TELES, 2005).
Códigos fonte dificeis de manter, softwares com baixa qualidade e sem atender os requisitos
são fatores que reduzem a confibilidade dos softwares entregues. Para amenizar estes problemas,
e baseadas na engenharia de software, empresas começaram a investir em técnicas de qualidade,
inicialmente manuais e com o passar dos tempos foram surgindo ferramentas para automatizar
parte deste processo.
Assim como os testes manuais, os testes automatizados tem como objetivo melhorar a
qualidade de sistemas através da verficação e validação, mas a automação de testes expande a
área de estudo de testes de software e muda os paradigmas de implementação, manutenção e
execução de testes. Segundo Schuwaber e Beedle (2001), dentre os métodos ágeis que satisfazem o manifesto,
existem os que focam em aspectos mais gerenciais, como o Lean e o Scrum, e outros que
também dão ênfase a práticas de desenvolvimento de software, tal como a programação extrema
(XP). Todas prezam pelo controle de qualidade disseminado por toda a equipe e durante todo o
desenvolvimento.
O controle da qualidade no desenvolvimento com métodos ágeis normalmente é associado à
automação de testes, já que essa prática surgiu da mesma comunidade. Automação de testes é
uma das práticas bases do XP (BECK, 2000). As baterias de testes podem ser executadas sem
esforço a todo momento, o que possibilita a verificação contínua da qualidade do sistema durante
e após a implementação.
De acordo com Aniche (2012), essa simples inversão no ciclo traz diversos benefícios para o
projeto. Baterias de testes tendem a serem maiores, cobrindo mais casos, e garantindo uma maior
qualidade externa. Além disso, escrever testes de unidade forçará o desenvolvedor a escrever um
código de maior qualidade, pois para escrever bons testes de unidade, o desenvolvedor será
obrigado a fazer bom uso de orientação a objetos. Assim as suítes de testes validam o
comportamento do software, e podem ser usadas para verificar se a implementação funciona
conforme o esperado. E ainda, quando um erro é corrigido, o conjunto de testes pode ser usado
para verificar se a modificação no código fonte teve efeito colateral em outras partes do
software.
No entanto, conforme o software cresce, sua bateria de testes tende a ser maior e seu tempo de
execução pode se tornar um problema, especialmente em equipes que fazem uso das
metodologias ágeis, que pregam um ciclo curto de desenvolvimento. Além disso, devido à
crescente complexidade dos sistemas, já não é suficiente testar o software apenas no ambiente de
desenvolvimento, é preciso testar em uma variedade de ambientes (DUARTE, 2005).
Grandes projetos de software normalmente envolvem várias equipes de desenvolvimento.
Nestas situações, um conjunto de testes pode ser usado por uma equipe de desenvolvimento para
verificar se um módulo de software fornecido por outra equipe tem um comportamento desejado,
escondendo os detalhes de implementação (JEFFRIES, ANDERSON, HENDRICKSON, 2001).
Dessa forma, grandes projetos de software geralmente têm grandes conjuntos de testes, que
levam muitas horas para executar, até mesmo dias, em sua completude.
A fim de ser eficaz, o processo de teste de software que deve ser executado de uma maneira
rápida e automática. Ele deve ser automático, pois o mesmo conjunto de testes deve ser
executado várias vezes ao longo do ciclo de vida do software, incluindo a cada vez que uma
nova funcionalidade foi adicionada e cada vez que um defeito do software é corrigo. Além disso,
uma suite de testes que executa rapidamente, pode ser executada com mais freqüência durante o
processo de desenvolvimento, e assim a captura de problemas ocorresse mais cedo.
Assim, neste trabalho se desenvolveu uma ferramenta para executar testes automatizados em
um cluster computacional, visando acelerar o processo de teste de software.
2. Cluster
Segundo Sales (2008), atualmente existem vários tipos de aplicações que necessitam de um
poder computacional muito maior do que um único computador, que possui somente um
processador, pode proporcionar. Assim, o tempo de espera por respostas para esses tipos de
aplicações nesses tipos de computadores pode durar de dias a anos. Alguns tipos de aplicações
que demandam um alto poder de processamento são: mapeamento do genoma humano,
exploração de petróleo, previsão do tempo, renderização de efeitos especiais em filmes, e outras.
Com o objetivo de preencher a falta de computadores que dão resultados mais rápidos quando
são exigidos por aplicações que demandam por um alto poder computacional, foram surgindo os
supercomputadores, como estações de trabalho dedicadas com múltiplos processadores, sendo
capazes de distribuir a carga gerada pelas aplicações entre seus vários elementos de
processamento. Mas, a obtenção de supercomputadores, nem sempre chega a ser a alternativa
mais conveniente, devido a vários fatores, como por exemplo: o custo muito elevado; possuem
softwares proprietários e caros; um custo elevado para manutenção; a grande dependência dos
fornecedores; grande dificuldade de atualização (SALES, 2008).
Assim surgiu a computação baseada em clusters, que aparece então como um alternativa
relativamente simples e de baixo custo para suprir esta demanda, que até então somente
supercomputadores seriam capazes de resolver. Uma definição simples para a computação em
cluster seria: o agrupamento de dois ou mais computadores trabalhando em paralelo para
solucionar determinado problema (figura 1).
Figura 1 - Estrutura do Cluster (JUI, PERRIERO, 2004).
Uma outra definição de cluster pode ser resumida como sendo um conjunto de computadores
autônomos e que interligados comportam-se como um único sistema do ponto de vista do
usuário. Ou seja, todos os aspectos relativos à distribuição de tarefas, comunicação,
sincronização e organização física do sistema devem ser abstraídos do usuário (PITANGA,
2003).
3. Características dos Clusters
A computação baseada em cluster ainda supera os supercomputadores em diversos aspectos,
onde podem-se destacar (DANTAS, 2005):
a) Alto desempenho: resolução de problemas de grande complexidade em curto espaço
de tempo;
b) Escalabilidade: possibilidade de adicionar aplicações, periféricos, nós e até mesmo
mais interconexões de rede sem interromper a disponibilidade dos serviços do cluster;
c) Baixo custo: custos reduzidos com processamento de alto desempenho utilizando
hadware de fácil disponibilidade, como computadores pessoais; utilização de
hardware aberto, software livre e independência de fabricantes;
d) Confiabilidade: o cluster tem que ser dotado da capacidade de detecção de falhas
internas, e com isso, tomar a decisão cabível para solucionar o problema, para que o
mesmo não venha a prejudicar os serviços que são oferecidos;
e) Gerenciamento e manutenção: mecanismos que permitem gerenciar de forma simples
a complexidade de configurações e manutenção. Umas das grandes dificuldades de
um cluster são a sua manutenção e principalmente a sua configuração, pois na maioria
das vezes são tarefas morosas e que tem grande propensão a erros;
f) Transparência: O cluster, que é construído por vários nós independentes e fracamente
acoplados, deve parecer como se fosse apenas um computador para o cliente, ou seja,
possuir a capacidade de se apresentar como um sistema único.
Clusters de computadores podem ser subdivididos em várias categorias, onde cada uma delas
tem sua própria característica, sendo utilizada para uma finalidade específica, são elas:
3.1. Alta Disponibilidade
Um cluster de alta disponibilidade tem por finalidade principal prover os serviços de um servidor
o maior tempo possível. A sua forma de funcionamento consiste em fazer a substituição de um
nó do cluster, no momento que este vier a falhar, por outro, de modo transparente ao usuário.
Isso é possível através da criação de réplicas dos serviços e servidores, onde os computadores
agem como um único sistema. Cada um monitorando o outro através de software e, no caso de
ocorrer uma falha, um deles assume os serviços daquele que ficou indisponível (DANTAS,
2005).
3.2. Balaceamento de Carga
Esta solução tem como objeto manter o equilibrio de carga entre diversos servidores,
distribuindo as requisições feitas aos elementos que o compõe, mantendo de forma equilibrada o
tráfego gerado a determinados serviços, garantindo assim a disponibilidade do serviço em
momentos de elevados acessos. A necessidade deste tipo de cluster se justifica pelo fato da
grande quantidade de tráfego nos servidores que prestam serviço em uma rede, pois atualmente,
um dos maiores problemas enfrentados na Internet são os execessivos acessos quando sse possui
apenas um servidor (PITANGA, 2003).
A atividade principal é fazer o redirecionamento das requisições de entrada por meio de um
elemento que fará o balanceamento entre os servidores e os usuários. Com isso, nesse tipo de
estrutura têm-se múltiplos servidores, mas que parecem existir apenas um para o cliente.
3.3. Alto Desempenho
Sua utilização destina-se atender tarefas que exigem um grande poder computacional, esse tipo
de cluster, trabalha de modo a fazer a distribuição da carga de processamento entre os elementos
que compõe o cluster, gerando uma redução do tempo que é gasto com seu processamento
paralelo e distribuído. Sua utilização é bastante comum para resolução de problemas tipicamente
paralelos, ou seja, aplicações desenvolvidas para processarem cálculos de forma paralela. É
muito útil em áreas que tem como características a geração de um grande volume de dados,
como simulações finanaceiras, renderização de efeitos especiais em filmes, meteorologia, e em
várias outras que tem por necessidade um alto poder de processamento (PITANGA, 2003).
4. Testes Automatizados
Como foi descrito no decorrer das seções anteriores, testes automatizados estão fortemente
relacionados com as principais práticas de métodos ágeis. Para algumas delas, a escrita de testes
automatizados é um pré-requisito, enquanto, para outras, a automação dos testes traz muitas
vantagens. Dessa forma, a introdução de testes automatizados no processo de desenvolvimento
remete a iniciativa de melhoria da qualidade dos softwares. A automatização de testes possui o
objetivo de apoiar o processo, reduzindo ou eliminando gargalos no tempo de execução,
entretanto esse processo vai além da escolha de uma ferramenta (CHIAVEGATTO, SILVA,
VIERIA, MALVEZZI, 2013). Segundo Maldonado (2007), a técnica de automação é voltada
principalmente para melhoria da qualidade, baseia-se fortemente na teoria de teste de software,
para aplicar as recomendações dos testes manuais na automação dos testes.
Chiavegatto, Silva, Vieira e Malvezzi (2013) citam que a automatização de testes é uma
prática ágil e eficaz para melhorar a qualidade dos software, porém inicialmente a adoção da
técnica é mais custosa, pois, demanda um esforço maior de tempo e de mão de obra qualificada.
É necessário conhecimento, organização e experiência para evitar que a aplicação dessa técnica
não seja utilizada de forma incorreta, e para que não haja redução no custo-benefício dessa
prática no desenvolvimento de software. Ainda assim, os testes automatizados tendem a ter uma
maior produtividade, onde é necessário um esforço inicial que é compensando na execução a
longo prazo. O teste manual não pode ser eliminado, deve sim, ser reduzido ao máximo possível
e focado naquilo que é muito caro automatizar.
5. JUnit
O JUnit é um framework open source para utilização de testes unitários em Java, sendo possível
criar classes de testes que podem ter um ou mais métodos para execução. Os testes podem ser
executados sequencialmente ou de forma modularizada, dessa forma, os sistemas podem ser
testados em partes ou de uma única vez (TAHCHIEV, LEME, MASSOL, GREGORY, 2003).
Conforme Hunt e Thomas (2003), em 1998, Kent Beck e Erich Gamma desenvolveram o
projeto JUnit para a linguagem Java, inspirado no SUnit. Desde então a prática de testes
automatizados vem sendo disseminada dentre as equipes de desenvolvimento de software
adeptas a automatização.
A estrutura base do JUnit se da através de pequenas validações, verificação de valores na
menor unidade do sistema (Unit test), que agrupadas pela classe de negócio a ser testadas
formam uma classe de teste (Test Case). As suítes de testes (TestSuite) são classes do JUnit para
organizar a melhor forma que se deseja executar os testes, por exemplo, os testes podem estar
agrupados por módulos do sistemas, ou ainda, organizados em funcionais e não funcionais. A
concepção dos testes unitários é validar o sistema em pequenos pedaços e a junção de todos os
pequenos pedaços dados através dos suites de testes e consequentemente dos casos de testes que
formam o resultado final da cobertura do software que os testes abrangem (TAHCHIEV, LEME,
MASSOL, GREGORY, 2003).
Figura 2 - Estrutura do JUnit (TAHCHIEV, LEME, MASSOL, GREGORY, 2003).
a) Unit test - Um teste de unidade examina o comportamento de uma unidade distinta de
trabalho. Dentro de um aplicativo Java, a unidade distinta de trabalho é muitas vezes (
mas nem sempre) um único método. Por outro lado, testes de integração e testes de
aceitação examinam como vários componentes interagem. A unidade de trabalho é uma
tarefa que não é diretamente dependente da conclusão de qualquer outra tarefa, ou seja,
uma unidade de testes jamais deve depender de outra, e como trata-se da menor unidade
de teste, estima-se que o seu tempo de execução não deve exceder 10 segundos;
b) TestCase (caso de teste) - A classe que estende o JUnit TestCaseClass. Ele contém um ou
mais testes representados por testXXXmethods. Um caso de teste é utilizado para agrupar os testes que exercitam comportamentos comuns ou validações de uma mesma classe;
c) TestSuite (conjunto de testes) - Um grupo de testes. Um conjunto de testes é uma maneira
conveniente para agrupar os testes que estão relacionados, tais como grupo de objetos
que pertencem ao mesmo módulo do sistema. Por exemplo, se você não definir um
conjunto de testes para um TestCase, JUnit fornece automaticamente um conjunto de
testes que inclui todos os testes encontrados no TestCase;
d) TestRunner (executor de teste) - Um executor de suítes de teste. JUnit fornece várias
classes de teste que você pode usar para executar os testes. Não há TestRunnerInterface,
apenas um BaseTestRunner que todos os executores de teste estendem.
De forma geral seu funcionamento se dá através da verificação dos métodos de uma classe,
constatando se os mesmos funcionam da maneira esperada, exibindo de forma visual o resultado
da execução positiva ou negativa dos testes (Passed or Fail).
Figura 3 - Barra de progresso JUnit no Eclipse (BERNARDO, KON, 2008).
O projeto JUnit é bem simples, assim como os códigos dos testes devem ser. Com esta noção
básica da ferramenta já é possível criar seus próprios testes automatizados para seus projetos. No
entanto, é recomendado um estudo um pouco mais profundo para que seus testes tenham mais
qualidade. Duas características fundamentais para garantir a qualidade dos testes
são:simplicidade e legibilidade (BERNARDO, KON, 2008).
Bernardo e Kon (2008) ainda citam que o código do teste, assim como o código do sistema,
pode conter erros; por isso, é imprescindível que o código do teste seja o mais simples possível.
Evite testes longos, código repleto de condições (ifs), testes responsáveis por muitas verificações
e também nomes obscuros. É também importante que a legibilidade dos testes seja boa para
facilitar a sua manutenção e para se obter pistas explícitas de qual funcionalidade está quebrada
quando um teste falhar. Além disso, testes claros e legíveis podem ser utilizados como
documentação do sistema ou como base para gerar a documentação através dos relatórios dos
resultados.
6. Apache Ant
Apache Ant é uma ferramenta de desenvolvimento, um pequeno programa concebido para ajudar
as equipes de software a desenvolver programas maiores, automatizando todas as tarefas de
compilação de código, execução de testes e publicação dos resultados para redistribuição
(LOUGHRAN, HATCHER, 2007).
Ant é escrito em Java e é projetado para ser multi-plataforma, fácil de usar, extensível e
escalável. Pode ser utilizado em um pequeno projeto pessoal, ou ele pode ser utilizado em um
projeto de software de grande porte. Destina-se a automatizar todo o seu processo de
desenvolvimento.
A ferramenta tem uma sintaxe similar ao XML, o que é bom para os desenvolvedores já
familiarizados. Em projetos de software que sofrem constantes mudanças, uma compilação
automatizada pode fornecer uma base de estabilidade. Mesmo que os requisitos mudem e os
desenvolvedores se esforçam para acompanhar, ter um processo de construção que precisa de
pouca manutenção e que execute os testes constantemente fornece uma segurança maior aos
desenvolvedores.
7. Ferramenta
A concepção inicial da ferramenta segue o mesmo principio dos testes unitários, que é o dividir
para conquistar, ou seja, a ideia é pegar a suite de testes e dividir sua execução dos casos de
testes em um cluster computacional. Este cluster é formado por um nó central e um ou mais nó
executores, onde o nó central é responsável pela distribuição dos casos de testes para os nós
executores e recepção dos resultados fornecido pelos mesmos.
O nó central pode ainda ser configurável como nó executor, neste caso além dele distribuir as
tarefas para os demais nós, ele também executa parte dos casos de teste.
Os nós executores são máquinas conectadas na rede de trabalho, não necessáriamente
máquinas físicas, podendo ser máquinas virtuais, com configurações distintas. Essa
heterogenidade nas configurações dos nós executores contribuiem nas validações dos testes, pois
os mesmos devem executar sem falhas nos ambientes distintos, não importando o sistema
operacional ou limitações de hardware. A função destes nós é receber a classe de teste delegada
pelo nó central, executá-la em seu ambiente através do Ant, e repassar o resultado dos testes para
o nó central.
O nó central, além de distruibuir os casos de testes e poder trabalhar como nó executor, é
responsável por receber os resultados das execuções pelos nós através do Ant, e uní-los,
formando assim o relatório final no formato XML, pronto para ser importado pelo plugin do
JUnit no Eclipse, e assim realizar a sua devida análise de execução (figura 4).
Figura 4 – Fluxo de execução da Ferramenta (Elaborado pelo autor, 2013).
7.1. Transmissão de Dados
Em uma arquitetura baseada em Cluster, o principal gargalo é comunição entre os nós, devido
a grande latência de informações trocadas. Hoje o principal meio de comunicação é através da
rede, sendo composta por meios fisicos e mecanismos de controle para transporte, além de uma
política de sincronização de dados (BACELLAR, 2010).
A mérito de implementação, neste projeto foi utilizado a API java.net.Socket, que fornece
recursos para envio e recebimento de dados, com detecção de erros, controle de
congestionamento e orientado à conexão, através do protocolo TCP, onde os nós pertencentes ao
Cluster se comunicam em uma determinada porta configurada, no caso porta 7339 para evitar
conflitos.
7.2. Escalabilidade
A escalabilidade dos sistemas distribuídos esta relacionado à capacidade de inclusão de novos
nós executores, a fim de aumentar o poder de processamento quando necessário. Para divisão de
tarefas entre os nós executores, utilizou-se o agrupamento implicito fornecido pelo JUnit, os
TestCases, além de garantir a integridade dos testes através dos métodos de setup e tearDown.
Assim, ao iniciar a execução é definido a suite principal e os seus casos de testes são
agrupados em uma fila sincronizada, para serem consumidos pelos nós executores. A
escalabilidade deste projeto ocorre de forma horizontal, ou seja, a medida que se necessita de
mais processamento é incluso mais nós executores, onde o nó central conhece os nós
disponiveis, porém não tem o controle da capacidade de processamento de cada um, forcendo
uma classe de teste por vez.
7.3. Sincronização
Um pré-requisito para a execução distrinuída de testes é garantir que todos os nós executores
possuem a mesma versão do código fonte para validação dos testes, caso contrário a execução se
torna inconsistente, pois pode acusar falhas no código que já fora corrigida em uma versão mais
recente.
Esta condição foi um dos grandes desafios ao implementar esta ferramenta, tendo em vista
que inicialmente era efetuado o checkout dos fontes pelo gerenciador de versionamento toda vez
antes de executar os teste, o que honerava completamente o processo.
Então, optou-se por trabalhar com diretório de rede compartilhado, aproveitando que o
Cluster estava em uma rede local. Assim o workspace do nó central foi compartilhado entre os
demais nós, e uma vez que o nó executor obtêm conexão com o nó central, é realizado a
sincronização dos fontes, baixando apenas as diferenças entre as versões.
7.4. Execução
A alternativa escolhida neste projeto para invocar o JUnit, e por sua vez adicionando-lhe o
recurso de execução distribuida, foi através da biblioteca Apache Ant, pois pelos seus scripts não
seria necessário alterar a implementação dos testes, garantindo assim a transparência ao usuário
final.
Os scripts Ant são baseados em tarefas pré-definidas, similares a macros, sejam estas tarefas
para compilar o código fonte, executar os casos de testes ou manipular arquivos XML,
auxiliando assim a automatização do processo.
Desta maneira, uma vez que o nó executor se conectou ao nó central e sincronizou os fontes,
já esta apto à receber os casos de testes e executá-lo via Ant, gerando o resultado em um arquivo
XML, salvo em um diretório compartilhado na rede.
Enquanto houver casos de testes na fila de execução, o nó central distribui as execuções entre
os demais nó, ao término, o nó central acessa o diretório compartilhado na rede e obtêm todos os
arquivos XML, referentes aos resultados de cada execução, e executa a rotina de junção destes
arquivos, formando assim o relatório final da execução, totalizando a quantidade de testes com
sucesso, falhas e erros.
7.5. Sumário
Assim podemos destacar as principais características desta ferramenta que estende a implentação
do projeto JUnit:
a) Transparência e Distribuição Automática: uma vez definido a suite a ser executada, a
distribuição dos testes e junção dos resultados ocorre de uma forma transparente para
o usuário final;
b) Integridade: antes do nó executor iniciar a execução dos testes no seu ambiente, o
mesmo verifica se todos os fontes estão na mesma versão fornecida pelo nó central,
evitando assim, erros por falta de sincronização e atualização de fontes;
c) Diversificação: por ter sua implementação em Java, a ferramenta torna-se
multiplataforma, podendo validar os testes em diferentes sistemas operacionais;
d) Atomicidade: para não violar o principio que um teste jamais deve alterar o contexto
de sua execução, a granularidade de divisão dos testes foi definida no nível de casos
de testes, inicialmente a ferramenta foi implentada a nível de unidades de teste, porém
não era possível garantir a execução dos métodos acessores, tais como: beforeClass()
e before(), que são executados antes dos testes, normalmente para estabelecer valores
e pré-configurações aos testes e o after() e afterClass() utilizados para restaurar o
contexto pós-execução dos testes, garantindo assim a independência dos testes, não
importando a sua ordem de execução;
e) Resultados: por fim, para quem já esta habituado com o uso do plugin do JUnit no
Eclipse, o uso da ferramenta e análise dos resultados ocorre de forma natural, pois o
mesmo fornece o relatório final da execução no mesmo formato do plugin.
8. Resultados
O propósito deste trabalho foi destacar a importância dos testes automatizados no cotidiano
das equipes de desenvolvimento de software, e além disto, fornecer uma alternativa para reduzir
o tempo de execução das suites de testes.
Para validar a eficiência da ferramenta desenvolvida, foram submetidos uma massa de 25.000
testes unitários, considerando o pior cenário de execução, onde cada unidade de teste leva 10
segundos para executar, concluímos em uma conta rápida que os testes levavam
aproximadamente 68 horas para executar em sua completude.
Os primeiros experimentos foram executados em uma máquina física como nó central e uma
máquina virtual como nó executor, e foi observado mais um benefício da ferramenta, enquanto
os testes executavam na máquina virtual, a máquina física estava disponível para o
desenvolvedor executar demais tarefas sem influenciar nos testes.
Em outras palavras, os testes automatizados executavam em plano de fundo, pela máquina
virtual, e o ambiente principal não era alocado para os mesmos, pois outra premissa referente à
execução de testes é não interferir no ambiente de execução, podendo afetar os resultados das
validações. Assim o problema da máquina ficar alocada totalmente para os testes e o
desenvolvedor ter que aguardar o término da execução foi sanado.
Executando os testes em plano de fundo, o desenvolvedor tem um feedback mais rápido dos
impactos das suas implementações, sem a necessidade de commit e aguardar a integração
contínua, e aumento da sua produtividade, pois enquanto aguarda a execução dos testes pode
executar outras atividades em paralelo.
Executar os testes em plano de fundo não eram suficientes para resolver o problema principal,
pois apesar de executarem em outra máquina, ainda era apenas um nó executor e o seu tempo
continuava extenso. Logo foi configurado o nó central como executor também e mais uma
máquina física que estava ociosa, onde os resultados de performance puderam ser observados.
Nesta configuração os testes levaram 36% do tempo inicial observado, aproximadamente 25
horas. O resultado já era satisfatório, mas ainda assim o tempo de execução excedia 1 dia, o que
para a equipe de desenvolvimento era um prazo muito extenso para feedback de alterações,
devido à grande quantidade de commits.
Então foram criadas mais 2 máquinas virtuais, uma em cada máquina física, aproveitando os
hardwares disponiveis, porém cada máquina virtual contava com no máximo 1gb de memória, o
que para os testes não é problema algum, devido suas unidades de validações serem enxutas.
Assim o cluster estava formado, com o total de 5 máquinas, 3 virtuais e 2 físicas, que resultaram
no tempo total de 15 horas, ou 22% do tempo inicial de execução. A figura 5 apresenta a
evolução dos tempos de execução.
Figura 5 - Horas x Nós Executores ( Elaborado pelo autor, 2013).
Podemos constatar que quanto maior a quantidade de nós executores, a relação de eficácia
horas x nó diminui, isto ocorre devido ao maior número de sincronizações de fontes e resultados
de execução. Neste cenário, o ambiente ágil estava reestabelecido, pois a integração contínua era
iniciada no final da tarde e na manhã seguinte todo o time de desenvolvimento já tinham
conhecimento do estado do projeto.
9. Trabaho Correlato
Duarte (2005) propôs uma outra alternativa para resolver o cenário de um ambiente com uma
grande massa de testes automatizados em um curto intervalo de tempo. Sua proposta buscou
também alternativas baseadas em sistemas distribuídos, porém diferentemente deste trabalho que
utilizou um Cluster local para a distribuição das execuções, Duarte utilizou a estratégia de Grids,
segue o quadro comparativo com as diferenças entre as estratégias:
Característica Grid Cluster
Atomicidade = =
Performance 12x (40cpu) 4x (5cpu)
Segurança Rede Global Rede Local
Balanceamento de Carga = =
Heterogenidade Diversos SO’s e Hardwares
distintos
Infraestrutura Local
Massa de Testes 450 730
Transparência = =
Simplicidade Dependência de projetos
terceiros
Config. Local
Execução Somente quando ocioso Dedicado
Quadro 1 - Grid x Cluster (Elaborado pelo autor, 2013).
Comparando as estratégias, percebemos que ambas atendem várias características de forma
similar, tais como: transparência; atomicidade e balanceamento de carga, isso ocorre devido ao
fato que tanto Grids, quando Cluster são implementações distintas de sistemas distribuidos.
Apesar das características em comum, há grandes diferenças entre elas, a começar pela sua
execução, a implementação dos Grids foi pensada em utilizar o tempo ocioso das máquinas
conectadas, já o Cluster a sua execução é focada na resolução do problema, assim podemos
analisar outra característica, a performance do Cluster foi 4 vezes mais rápida que o tempo
inicial trabalhando com 5 cpu’s, enquando a proporção do Grid foi 12/40, a diferença esta
relacionada diretamente na estratégia de execução.
Falando ainda em execução, podemos notar que heterogenidade do Grid é muito maior que a
do Cluster, pois no primeiro executamos em uma rede Global, e o segundo dependemos da
infraestrutura disponivel localmente. Em contrapartida, em termos de simplicidade de
configuração o Cluster leva vantagem, pois bastar configurar um arquivo .bat para invocar a
classe java que o testes já podem se executados, enquanto com o Grid é necessário configurações
terceiras de acordo com qual Grid se deseja executar.
Quanto a segurança, para executar os testes automatizados é necessário o envio dos códigos
fontes do software a ser testado, de acordo com a política de segurança da empresa vale analisar
os riscos se expõe os fontes à uma rede global, através dos Grids, ou se restringe a execução
apenas na rede local, utilizando o Cluster.
Por fim, independente de qual estratégia se opte em adotar, ambas buscaram alternativas para
redução dos longos perídos de execução de testes, cabe a equipe de desenvolvimento decidir qual
estratégia é mais oportuna para a sua realidade.
10. Considerações Finais
Neste trabalho foi possível demonstrar o poder computacional fornecido por um Cluster, com
configurações modestas de hardware, se destacou por paralelizar a execução dos testes,
acelerando todo o processo de testes e desenvolvimento de software.
Além disto, foi fortemente embasado no crescimento do desenvolvimento ágil, e com ele a
extrema importância dos testes automatizados e das práticas de desenvolvimento de software
relacionadas, ágeis ou tradicionais.
Quanto aos resultados, foram considerados bons, pois ajudou a diminuir o tempo total de
execução dos testes, porém sabe-se que o tamanho da bateria de testes tende a crescer, o que nos
resta aumentar a quantidade de nós executores ou então dar margem para a seguinte reflexão: “é
necessário executar a bateria de testes por completo sempre?”
A continuação deste trabalho pode ser dada através do estudo das práticas ágeis, em especial
os testes automatizados, atrelados com a engenharia de requisitos e sua matriz de rastreabilidade,
pois uma vez que sabemos os possíveis impactos de nossas implementações, rodamos os testes
específicos para constatar tais efeitos colaterais.
Por fim, baseado na vivência do autor em projetos que fazem uso da prática de testes
automatizados, o mesmo constatou uma baixa incidência de erros comparado à projetos que a
qualidade é realizada apenas manualmente, porém não foi encontrado nenhum estudo que prove
este fato, deixando assim esta sugestão de trabalho futuro.
Referências
ANICHE, Mauricio. Test-Driven Development: Teste e Design no Mundo Real. Casa do
Código, 2012. 160 p.
BACELLAR, Hilário Viana. Cluster: Computação de Alto Desempenho. Artigo publicado,
Instituto de Computação, Universidade Estadual de Campinas. 2010. 6 p.
BECK, Kent. Extreme Programming explained: embrace change. 1. ed. Reading, MA:
Addison-Wesley, 2000. 190 p.
BERNARDO, Paulo, KON, Fabio. A importância dos testes automatizados. Artigo publicado
Engenharia de Software Magazine, 1(3), p54-57. 2008.
CHIAVEGATTO, Rafael, SILVA, Lidiane, VIERIA Andréia, MALVEZZI William.
Desenvolvimento Orientado a Comportamento com Testes Automatizados utilizando
JBehave e Selenium. Artigo publicado, Anais do Encontro Regional de Computção e Sistemas
de Informação, Faculdade FUCAPI – Manaus, AM. 2013. 10 p.
CRISPIN, Lisa, HOUSE, Tip. Testing Extreme Programming. Addison-Wesley, 2002. 237 p.
DANTAS, Mario. Computação Distribuída de Alto Desempenho: Redes, Clusters e Grids
Computacionais. Rio de Janeiro: Axcel Books, 2005. 262 p.
DUARTE, Alexandre. Using the Computational Grid to Speed up Software Testing. Papper.
DSC-Universidade Federal Campina Grande: Campina Grande, PB. 2005. 6 p.
HUNT, Andrew, THOMAS, David. Pragmatic Unit Testing in Java with JUnit: The Pragmatic
Programmers. 2. ed. Addison-Wesley Professional, 2003. 352 p.
JEFFRIES, Ron, ANDERSON, Ann, HENDRICKSON, Chet. Extreme Programming
Installed. Addison-Wesley Professional, 2001. 265 p.
JUI, Stephen, PERRIERO, Robert. Clustering & Computing. Disponivel em: <
http://pages.csam.montclair.edu/~perrieror/projects/CMPT495-clustering.and.security/>. 2004.
Acessado em: 02 Mar 2014.
LOUGHRAN, Steve, HATCHER, Erick. Ant in Action. 2. ed. Manning Publications:
Greenwich, 2007. 600 p.
MALDONADO, José Carlos, DELAMARO, Marcio Eduardo, e JINO, Mario. Introdução ao
Teste de Software. Editora: Elsevier, Campus, 2007. 408 p.
MOLINARI, Leonardo. Inovação e Automação de Testes de Software. 1. ed. Erica: São Paulo,
2010. 144 p.
PITANGA, Marcos. Computação em Cluster: O Estado Arte da Computação. Rio de Janeiro:
Brasport, 2003. 292 p.
SALES, Péricles. Avaliação de Desempenho de Ferramentas de Renderização de Imagens
em Clusters openMosix e Arquiteturas Multicore. Trabalho de Conclusão de Curso.
Universidade de Pernambuco – UPE: Recipe, PE. 2008. 62 p.
SCHWABER, Ken, BEEDLE, Mike. Agile Software Development with SCRUM. Prentice
Hall, 2001. 158 p.
TAHCHIEV, Petar, LEME, Felipe, MASSOL, Vincent, GREGORY, Gary. JUnit in Action. 2.
ed. Manning Publications: Greenwich, 2003. 384 p.
TELES, Vinicius. Um Estudo de Caso da Adoção das Práticas e Valores do Extreme
Programming. Dissertação Informática. IM-NCE/UFRJ: Rio de Janeiro, 2005. 181 p.