FERRAMENTA PARA EXECUÇÃO DE TESTES AUTOMATIZADOS … · expressava as dificuldades do...

13
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.

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.