TCC Virgilio Rocha Ximenes
-
Upload
virgilio-ximenes -
Category
Technology
-
view
963 -
download
0
description
Transcript of TCC Virgilio Rocha Ximenes
FUNDAÇÃO EDSON QUEIROZ
UNIVERSIDADE DE FORTALEZA – UNIFOR CENTRO DE CIÊNCIAS TECNOLÓGICAS – CCT
CURSO CIÊNCIA DA COMPUTAÇÃO
AMBIENTE INTEGRADO DE TESTE AUTOMATIZADO
VIRGILIO ROCHA XIMENES
Fortaleza – Ceará 2012
VIRGILIO ROCHA XIMENES
AMBIENTE INTEGRADO DE TESTE AUTOMATIZADO
Monografia apresentada para obtenção dos créditos da disciplina de Trabalho de Conclusão - TCC do Centro de Ciências Tecnológicas da Universidade de Fortaleza, como parte das exigências para graduação no Curso de Ciências da Computação.
Orientador: Rafael Garcia Barbosa, MSc.
Fortaleza – Ceará 2012
3
AMBIENTE INTEGRADO DE TESTE AUTOMATIZADO
Virgílio Rocha Ximenes
PARECER: ______________________________
DATA: ___/___/____
BANCA EXAMINADORA:
________________________________________________
Rafael Garcia Barbosa, MSc.
________________________________________________
Alex Silveira da Costa, MSc.
4
AGRADECIMENTOS
Inicialmente, agradeço a Deus, pelo amor, pelas oportunidades
concedidas, pela esperança, pelo conforto, pela vida, e por ter me dado condições
físicas e emocionais para chegar até aqui, pois posso dizer as palavras que estão
nas sagradas escrituras: “Até aqui nos ajudou o Senhor”.
Agradeço aos meus pais, pois, se não fossem eles, eu não estaria aqui, e
pelo carinho e dedicação que nunca deixaram faltar. A minha mãe, pela cobrança e
pela educação que moldaram meu caráter. A meu pai, pela sabedoria e paciência
que me fizeram chegar aonde cheguei.
Agradeço a minha namorada, Ticiana Castelo Branco, pelo apoio,
carinho, pela compreensão, paciência e dedicação durante este período.
Agradeço ao meu orientador, Prof. Rafael Garcia, pela paciência, pelo
conhecimento compartilhado, pela oportunidade e orientação neste estudo.
Agradeço a todos os professores da UNIFOR, em especial ao Roberto
Façanha, a Sandra e ao Fernando Parente, pelo conhecimento transmitido, pela
paciência e atenção dispensada ao longo dos semestres.
Agradeço a todos os meus amigos, Vitor Rifane, Rodrigo Gato, Marilia
Feitoza, Leandro Almeida e tantos outros, pela amizade, pelas brincadeiras, pelas
conversas, pelo apoio e pelas saídas para lanchar no Baixinho.
5
RESUMO
Estudos revelam que o retrabalho é responsável direto pelo atraso e por grande
parte dos custos envolvidos em um projeto. A principal maneira de reduzir o
retrabalho é através dos testes, porém estes são executados manualmente. Este
trabalho objetiva apresentar um ambiente com algumas ferramentas integradas com
o objetivo de automatizar a disciplina de teste. O foco do trabalho é a ferramenta
Jenkins, que é responsável pela criação e manutenção do ambiente integrado de
teste. Abordam-se as principais características da disciplina de testes, bem como
sua automação, suas vantagens e desvantagens. E, por fim, faz-se um estudo de
caso em que se pode aplicar a automação de testes em desenvolvimento de
aplicações. A linguagem de programação alvo é a linguagem Java, por ser a
linguagem adotada pela faculdade.
6
ABSTRACT
Studies reveal that the rework is directly responsible for the delay and for much of the
costs involved in a project. The main way to reduce rework is through tests, but they
are executed manually. This study presents an environment with some integrated
tools with the goal of automating the test discipline. The focus of the work is the tool
Jenkins, who is responsible for the creation and maintenance of the integrated test
environment. It addresses the key features of the discipline of testing and its
automation, advantages and disadvantages. In the end a study case in which one
can apply the automated testing applications under development. The target
programming language is Java, because it is the language adopted by the college.
7
LISTA DE ABREVIATURAS
API – Application Programming Interface (Interface de Programação de Aplicação) CLI – Command Line Interface (Interface de Linha de Comando) CVS – Concurrent Version System (Sistema de Versões Concorrentes) IDE – Integrated Development Environment (Ambiente Integrado de
Desenvolvimento) SCM – Source Code Management (Sistema de Controle de Versão) SQL – Structured Query Language (Linguagem Consulta Estruturada) SVN – Apache Subversion TDD – Test-Driven Development (Desenvolvimento Orientado a Teste) WAR – Web Archive (Arquivo de Aplicação Web) XML – Extensible Markup Language (Linguagem de Marcação Extensível)
8
LISTA DE FIGURAS
Figura 1 – Modelo em “V” do processo de testes …………………………………… 14 Figura 2 – Grafo de complexidade ciclomática de um software …………………… 18 Figura 3 – Utilização da ferramenta de análise estática ……………………………. 32 Figura 4 – Utilização da ferramenta de análise estática ……………………………. 33 Figura 5 – Utilização da ferramenta de análise estática ……………………………. 35 Figura 6 – Utilização da ferramenta de teste unitário em um script ……………….. 37 Figura 7 – Interface gráfica da ferramenta de teste de carga ……………………… 39 Figura 8 – Utilização da ferramenta de teste de carga em um script ……………… 40 Figura 9 – Realização da implantação do ambiente automatizado …………………42 Figura 10 – Telas do sistema que sofrerá a execução das ferramentas de teste… 45 Figura 11 – Configuração do ambiente e visualização dos resultados…………….. 48
9
LISTA DE TABELAS
Tabela 1 – Tabela comparativa entre as ferramentas de análise estática…………. 43
10
SUMÁRIO
INTRODUÇÃO .......................................................................................................... 11 1. TESTE DE SOFTWARE...................................................................................... 13
1.1 Visão geral .................................................................................................... 13 1.2 Técnicas de testes ........................................................................................ 16
1.2.1 Teste caixa-preta ...................................................................................... 17 1.2.2 Teste caixa-branca ................................................................................... 18 1.2.3 Teste caixa-cinza ...................................................................................... 19 1.2.4 Técnicas não funcionais ........................................................................... 19
1.3 Fases ............................................................................................................ 20 1.3.1 Fase de teste unitário ............................................................................... 20 1.3.2 Fase de teste de integração ..................................................................... 21 1.3.3 Fase de teste de sistema ......................................................................... 21 1.3.4 Teste de aceitação ................................................................................... 22 1.3.5 Teste de operação .................................................................................... 23
1.4 Automação de teste ...................................................................................... 23 2 AUTOMAÇÃO DE TESTE ...................................................................................... 25
2.1 Contexto de testes automatizados ................................................................... 25 2.2 Técnicas de revisão ......................................................................................... 25
2.2.1 Ferramentas de verificação de código fonte ............................................... 26 2.2.2 Ferramentas de automação ....................................................................... 27 2.2.3 Ferramentas de gerenciamento ................................................................. 29
2.3 Ambiente para execução de teste automatizado .............................................. 30 2.3.1 Checkstyle .................................................................................................. 30 2.3.2 Findbugs .................................................................................................... 32 2.3.3 PMD ........................................................................................................... 34 2.3.4 JUnit ........................................................................................................... 36 2.3.5 JMeter ........................................................................................................ 38 2.3.6 Jenkins ....................................................................................................... 40
2.4 Conclusões ....................................................................................................... 42 3 ESTUDO DE CASO ............................................................................................... 44
3.1 Especificação ................................................................................................... 44 3.2 Configuração do ambiente ............................................................................... 46 3.3 Análise dos resultados ..................................................................................... 48
CONCLUSÃO ............................................................................................................ 50 REFERÊNCIAS ......................................................................................................... 52
11
INTRODUÇÃO
Um estudo realizado na PUC-Rio mostra que um dos responsáveis pelos
atrasos nos projetos de software é o retrabalho, sendo, também, responsável por
45% dos custos envolvidos em um projeto, e o custo de um retrabalho aumenta de
acordo com a fase do projeto. O retrabalho é caracterizado por mudar o foco dos
profissionais de produzir uma nova funcionalidade para realizar correções de
defeitos em funcionalidades que foram, ou não, já homologadas (STAA, 2011).
A maneira mais eficaz de reduzir o retrabalho é através da execução
sistemática de testes. Entretanto, muitas vezes a qualidade é assegurada através de
testes manuais realizados após o desenvolvimento de um módulo específico ou, até
mesmo, do sistema inteiro. Porém tais testes são lentos e incompletos, além de ser
muito cansativo executar um vasto conjunto destes testes. Esta abordagem de
execução manual dos testes traz consigo vários problemas, pois, com a crescente
complexidade do software, alguns testes ou cenários de teste deixam de ser
executados, facilitando o surgimento de erros de regressão. O erro de regressão
surge quando uma funcionalidade que estava funcionando deixa de funcionar após
alguma alteração no software.
Autores indicam, exaustivamente, o uso de ferramentas de automação de
teste para manter a viabilidade de execução dos testes e o aumento de
produtividade. Isso advém do fato de que, com o tempo, aumenta-se a quantidade
de casos de testes e, sem o uso de uma ferramenta adequada, torna-se impossível
a execução de todos os casos de testes descritos em tempo hábil. Desta forma, será
possível garantir um alto nível de qualidade mesmo após mudanças, pois existirá
uma rotina que será executada sempre que solicitada, garantindo que, para
determinados casos, o software continue funcionando corretamente. Com a
execução automática dos testes, será possível reduzir não só o retrabalho, mas
também o custo envolvido em um projeto, pois uma vez que a rotina de teste seja
escrita, poderá ser reutilizada quantas vezes forem necessárias.
O teste automatizado é executado mais rápido, e com a evolução do
software e do teste, o cenário do caso teste continua a ser executado, facilitando,
assim, o teste de regressão, portanto o que era um problema na abordagem manual
12
não é mais na automática. Existem ferramentas onde é possível realizar testes em
vários níveis, garantindo a qualidade desde o nível mais baixo, o nível de código, até
o nível mais alto, o nível de interface.
Porém, Myers afirma que devem ser evitados testes descartáveis, isto é,
testes que possuem uma vida útil, pois a qualidade do software piora gradualmente
com as iterações de desenvolvimento (MYERS, 2004). Para esta finalidade, existem
os testes de regressão, que permitem quantificar a evolução da qualidade do
software, mantendo e executando testes realizados anteriormente.
O objetivo geral deste trabalho é apresentar diversas ferramentas
utilizadas em testes automatizados, de modo que estas venham a compor um
ambiente integrado, a partir do qual será realizado um estudo de caso. Além disso,
apresentar uma visão geral da área de testes de software, mostrando as vantagens
dos testes automatizados, ferramentas que realizam os diversos tipos de testes e
um ambiente integrado de teste composto pelas ferramentas apresentadas.
Este trabalho está organizado da seguinte forma: no primeiro capítulo
será apresentada uma visão geral da área de teste, bem como as técnicas e as
principais fases. O capítulo 2 trata da automação de teste, através da apresentação
do contexto da automação, das técnicas de revisão e de ferramentas que irão
compor o ambiente. No último capítulo, será apresentado um estudo de caso, onde
será apresentada a montagem e a criação do ambiente integrado de teste, bem
como a execução dos testes e a visualização dos relatórios gerados pelas próprias
ferramentas. No final, serão apresentadas as conclusões, indicando algumas das
vantagens na utilização de um ambiente integrado.
13
1. TESTE DE SOFTWARE
1.1 Visão geral
O software tem feito cada vez mais parte da vida das pessoas, através de
computadores, tablets e, até mesmo, de celulares. Com isso, as pessoas têm ficado
cada vez mais exigentes. Portanto, o desafio é desenvolver software com qualidade
e segurança em um curto período de tempo, mantendo um baixo custo, além de
atender os requisitos do produto.
A atividade de teste vem exatamente para isso, pois, encontrar um bug no
início do desenvolvimento é menos custoso para o projeto, além de tornar o software
mais confiável uma vez que um software testado possui uma confiabilidade maior.
Com esta qualidade agregada devido ao teste, pode-se, também, fazer uma
medição desta qualidade em relação aos erros encontrados (ALMEIDA, 2012).
De acordo com Myers (2004), existe uma psicologia por detrás dos testes
que afirma que os programadores se mostram resistentes aos testes, pois afirmam
que o teste serve apenas para mostrar que não existem erros no programa, ou que o
propósito do teste é mostrar que o programa atende às funcionalidades
corretamente, ou que o teste é o processo de estabelecer a confiança de que o
programa faz aquilo que foi feito para fazer. Porém, se o teste for elaborado sob a
perspectiva de que o programa não possui falhas, este será elaborado de modo a
atingir a sua meta que é a de não encontrar falhas. Por outro lado, se houver a
crença de que o programa possui falhas, a ação será de encontrar o máximo de
erros possíveis ou não conformidades. Portanto, a definição de teste que o testador
deve possuir em mente é a de que o teste é o processo de executar um programa
com a intenção de encontrar erros. E compreender bem a definição de teste pode
fazer uma grande diferença no sucesso de seus esforços.
Na Figura 1, é apresentado o modelo em V, que é um modelo tradicional,
utilizado durante a execução dos testes, que é uma ordem inversa a do
desenvolvimento, pois, no desenvolvimento, a primeira etapa é a especificação de
requisitos, e a última é a codificação. Inicialmente são executados os testes unitários
e, por último, os de aceitação, onde incidem respectivamente em cada um. Portanto,
14
o primeiro teste a ser executado é sobre o que foi elaborado por último, e o último
teste o que foi elaborado logo no começo da fase de desenvolvimento (MORAIS,
2011).
Figura 1 – Modelo em “V” do processo de testes.
Bartie (2007) separa o processo de teste em sete etapas, que consistem
em: Planejamento dos testes, onde se define uma proposta de teste baseada no
prazo, no custo e na qualidade esperada; especificação dos testes, onde se
identifica os casos de testes que deverão ser construídos e modificados de acordo
com as solicitações do cliente; modelagem dos testes, onde se faz a identificação
de todos os elementos necessários para a implementação de cada caso de teste
especificado; preparação do ambiente, etapa que visa disponibilizar um ambiente
de teste pronto para rodar os testes planejados nas etapas anteriores, sem
intervenção humana que interrompa o processo de teste; execução dos testes,
etapa em que ocorre a execução em si e conferência dos testes planejados, de
modo a garantir a conformidade do produto com os requisitos; análise dos
resultados, etapa em que é feito um balanço de acordo com os resultados dos
testes, e, por fim, o encerramento do processo, etapa em que é feito um
fechamento do processo, comparando os resultados alcançados com o esperado.
15
A etapa de planejamento dos testes é uma etapa que contém
características mais gerenciais do que técnicas, e deve ser subdivida nas seguintes
etapas: estudo do projeto, avaliação de impacto, análise de esforço, definição de
possíveis cenários e aprovação do planejamento. O estudo do projeto é uma
avaliação realizada sobre o que se espera do software a ser construído bem como
os riscos do projeto e os respectivos impactos, avaliando, também, os requisitos sob
a perspectiva de custo, prazo e esforço. A avaliação de impacto pode ser vista como
a avaliação das exigências de criação e modificação de casos de teste, adequações
ao processo de teste, aquisição e adequação às ferramentas de teste, além da
modificação do ambiente. A definição de possíveis cenários é o momento em que há
uma busca por uma identificação de cenários diversos que alteram o prazo, o
esforço, o custo ou a qualidade do projeto, há também a definição do cronograma-
macro, os riscos e o plano de ação para cada cenário. A aprovação do planejamento
é a parte em que se deseja obter o aceite das propostas de cenários e a divulgação
das propostas aceitas.
Após o planejamento dos testes, há a especificação dos testes, onde
há um estudo dos requisitos, a identificação dos casos de testes e o refinamento do
projeto de teste. O estudo dos requisitos busca avaliar os requisitos funcionais e não
funcionais, identificando as inconsistências e estabelecendo o aceite dos
documentos. Na subetapa de identificação dos casos de testes, identifica-se cada
requisito e seu respectivo caso de uso, identificando, em cada caso de uso, seus
fluxos (básico, alternativo e exceção) e os casos de testes que irão incidir sobre
cada fluxo. Paralelamente, a arquitetura dos testes deve ser especificada, avaliando
adequações na automação para a preparação do ambiente, da execução dos testes
e da análise dos resultados. Após isso, o refinamento do projeto de teste serve para
reavaliar as estimativas iniciais de custo, prazo e esforço, reavaliar riscos do projeto
e estabelecer um cronograma detalhado baseado no cronograma-macro.
Depois do planejamento dos testes, vem a atividade de modelagem de
testes, que é o momento de criação dos roteiros de testes, incluindo procedimentos
para iniciar, executar, validar e realizar uma limpeza após a execução do caso de
teste, além de detalhar a massa de entrada de dados, identificando opções
parametrizáveis para gerar testes variados, mantendo a rastreabilidade entre o caso
de teste e a massa de dados de entrada. A massa de dados de saída também deve
16
ser detalhada através da identificação dos pontos de validação, da análise dos
dados, comparando os dados esperados com os dados efetivamente retornados e,
também, garantindo a rastreabilidade. E, por fim, tem-se a elaboração do plano de
execução dos testes, que inclui a especificação das configurações necessárias para
a execução dos testes.
Em seguida, vem a preparação do ambiente, que é feita através das
configurações especificadas e informações geradas, além, é claro, da instalação da
versão do software a ser testado.
Neste momento, tem-se a execução dos testes, que é feita pela
execução dos testes progressivos, que são disparados em funcionalidades
disponibilizadas a cada nova versão, e os testes regressivos, que são executados
sobre funcionalidades que estavam homologadas nas versões anteriores. Além da
execução, propriamente dita, tem-se a identificação de não conformidades com os
requisitos, tanto para os testes progressivos quanto para os regressivos.
Após a execução, há a análise dos resultados, que vem para revisar os
resultados em não conformidades levantados pela execução dos testes, revisar
testes progressivos em conformidade, atualizar o baseline, formalizar os defeitos
encontrados, através do isolamento de cada caso de teste que apontou como
resultado uma não conformidade da coleta de evidências que comprovam a não
conformidade, do detalhamento das condições que indicam a não conformidade, da
classificação de cada defeito encontrado.
Então, finalmente, tem-se o encerramento do processo, que é feito pela
extração de indicadores, como, por exemplo, quantidade de erros por funcionalidade
ou, até mesmo, um gráfico apresentando a evolução ou regressão do software, pelo
resumo do processo de testes e a avaliação final do processo.
1.2 Técnicas de testes
A atividade de teste não depende de tecnologia, uma vez que é possível
testar software em diferentes paradigmas, embora o paradigma orientado a objeto
venha a facilitar o desenvolvimento desta atividade. Como dito anteriormente, o
17
objetivo do teste é executar um programa com a intenção de encontrar erros,
independente, portanto, de tecnologia.
Segundo Myers (2004), dentre os princípios do testador, existem três que
devem ser observados constantemente. Testar é o processo de executar um
programa com a intenção de encontrar erros. Um bom caso de teste é aquele que
tem alta probabilidade de encontrar um erro ainda não encontrado; um teste bem
sucedido é aquele que detecta um erro ainda não encontrado.
1.2.1 Teste caixa-preta
O teste caixa-preta, também chamado de teste funcional, avalia o
comportamento externo do sistema. Para usar esta metodologia, o testador deve ver
o software, literalmente, como uma caixa preta. Sua meta é ser completamente
despreocupado sobre o comportamento interno e a estrutura do programa. Deve se
concentrar, portanto, em encontrar circunstâncias em que o programa não se
comporte de acordo com as especificações (MYERS, 2004).
Segundo Pressman (2005), este teste tem por objetivo encontrar erros
das seguintes categorias: funções incorretas ou omitidas, erros de interface, erros de
estrutura de dados ou de acesso à base externa, erros de comportamento ou
desempenho, erros de iniciação ou de término.
Numa situação ideal, todas as possibilidades são testadas, mas, na
maioria dos casos, isso é muito difícil, ou quase impossível. Portanto quanto mais
entradas forem testadas, mais rico será o teste. A abordagem mais utilizada, na
prática, é obter uma amostra que represente os possíveis valores de entrada.
Um dos problemas deste tipo de teste é que os casos de teste são
derivados da especificação, e esta, por sua vez, pode estar ambígua em relação ao
sistema produzido, e como resultado as entradas especificadas podem não ser as
mesmas aceitas para o teste.
18
Apesar de necessário, esse tipo de teste é insuficiente para identificar
certos riscos em um projeto de software.
1.2.2 Teste caixa-branca
Complementar ao teste caixa-preta, tem-se o teste caixa-branca, ou teste
estrutural, analisando diretamente o código-fonte para analisar aspectos como: teste
de condição, teste de fluxo de dados, teste de ciclos, teste de caminhos lógicos ou
complexidade ciclomática.
Segundo Myers (2004), o objetivo é fazer com que cada declaração no
programa seja executada pelo menos uma vez. Se o testador executar, via caso de
teste, todos os possíveis caminhos de controle de fluxo pelo programa, então o
programa será completamente testado. Porém, se considerarmos um programa
comum, com uma estrutura de repetição, que repete vinte vezes um dado conjunto
de instruções e, dentro desse conjunto de instruções, temos algumas estruturas de
controle de fluxos aninhadas, há que testar todas as possibilidades da Figura 2,
sendo cada nó do grafo um conjunto de instruções e cada aresta um possível
caminho.
Figura 2 – Grafo de complexidade ciclomática de um software
19
Uma das possíveis desvantagens do uso deste tipo de teste é que nem
sempre os testes que envolvem as estruturas de um sistema vislumbram as
funcionalidades e iterações esperadas do sistema, o que torna este tipo de teste
desnecessário ou, até mesmo, inviável. Outra desvantagem é a inserção de erros
através do acesso ao código interno de um sistema.
1.2.3 Teste caixa-cinza
O teste caixa-cinza é uma combinação dos testes caixa-branca e caixa-
preta, pois envolve ter acesso ao algoritmo e estrutura de dados, com o intuito de
desenvolver casos de teste a serem executados como caixa-preta.
Um exemplo de teste caixa-preta seria quando o código de duas unidades
é estudado, através da abordagem caixa-branca, para projetar casos de teste que
serão conduzidos através de interfaces expostas, através da abordagem caixa-preta.
Esta metodologia pode ser usada em outros níveis de teste, embora seja bastante
utilizada em teste de integração.
A atual implementação da metodologia caixa-cinza é altamente
dependente do uso de uma aplicação utilizada para executar e validar o teste em
questão, o depurador. Estudos confirmam que esta metodologia pode ser aplicada
em tempo real usando o software executando na plataforma de destino, o que
expande as capacidades desta metodologia, por incluir não apenas o caminho para
cobertura de verificação, mas também o melhor e o pior caso. Também possibilita
verificar e validar requisitos de performance, requisitos funcionais e estruturais em
um único caso de teste com o mesmo formato usado para verificar e validar
requisitos funcionais (COULTER, 2001).
1.2.4 Técnicas não funcionais
Estas técnicas são chamadas de não funcionais, não por estarem
vinculadas a funcionalidades do sistema, mas sim por estarem vinculadas a
restrições de usabilidade. Portanto, são técnicas que avaliam questões como
segurança, desempenho, usabilidade, entre outros aspectos.
20
Existem outras técnicas de teste, cada uma com um objetivo específico,
como, por exemplo, o teste de regressão para analisar se determinados
componentes continuam funcionando após alguma alteração; teste de desempenho,
para verificar se o desempenho do software está dentro de um limite aceitável dentro
de determinado cenário; teste de stress, para analisar o comportamento do sistema
em condições anormais de demanda. Para verificar se um software é adequado ao
uso, tem-se o teste de usabilidade; ou para verificar seu funcionamento a partir da
liberação do produto para pequenos grupos de usuários trabalhando em um
ambiente controlado, teste alfa, ou não controlado, teste beta (SANTOS, NETO,
2009).
1.3 Fases
Segundo Myers (2004), existem duas abordagens que chamam atenção,
a Top-down e a Bottom-up. Na abordagem top-down, ou incremental, incrementa-se
o módulo a ser testado com as novas funcionalidades e testa-o. Por outro lado, na
abordagem bottom-up, testa-se primeiro as unidades mais básicas, até testar o
módulo. Devido à dificuldade de se realizar testes na abordagem top-down, a
abordagem bottom-up é a mais escolhida.
Como visto anteriormente, existem diversos tipos de testes, e cada tipo de
teste tem um foco diferente, para testar características diferentes. Serão abordados
os seguintes tipos de testes: teste unitário, teste de integração, teste de sistema e
teste de aceitação.
1.3.1 Fase de teste unitário
Segundo Pressman (2005), o teste unitário, ou de unidade, focaliza o
esforço de verificação na menor unidade de projeto do software. A complexidade
dos testes e dos erros descobertos é reduzida, por conta da limitação do escopo
estabelecido para o teste. Este tipo de teste enfoca a lógica interna de
processamento e de estrutura de dados dentro dos limites de um componente.
Pela definição, tem-se que o teste unitário é um teste do tipo caixa-
21
branca, pois a estrutura de dados local é examinada para garantir que os dados
armazenados temporariamente mantenham sua integridade durante todo o algoritmo
testado. Todos os caminhos independentes ao longo da estrutura de controle são
analisados, para garantir que todos os comandos da unidade tenham sido
executados pelo menos uma vez. As condições limites também são testadas, para
garantir que a unidade trabalhe adequadamente nos limiares estabelecidos. Testes
de fluxo de dados são executados inicialmente, pois se os dados não entram e saem
corretamente, os outros testes são questionáveis (PRESSMAN, 2005).
1.3.2 Fase de teste de integração
Segundo Pressman (2005), uma questão pertinente é: “Após o teste
unitário, verificamos que as unidades estão funcionando individualmente, por que
duvidar que eles não funcionem conjuntamente?” Dados podem ser perdidos através
de uma interface ou chamadas a sub-rotinas; quando combinadas, podem não
produzir o resultado esperado.
O teste de integração é a fase em que se verifica a interface entre os
componentes. As unidades devem ser integradas e testadas conjuntamente. Este
tipo de teste pode expor defeitos nas interfaces ou nas interações. O objetivo deste
teste é verificar funcionalidades, desempenho e confiabilidade. Este tipo de teste é
uma técnica sistemática para construir a arquitetura do software enquanto conduz
testes para descobrir erros associados às interfaces. Normalmente, aplica-se,
também o teste de regressão neste momento para verificar se novos erros foram
introduzidos com a adição de novas unidades ou alteração das existentes.
1.3.3 Fase de teste de sistema
O teste de sistema não é um processo de teste de funções de um sistema
completo ou programa, pois isso seria redundante com o teste funcional. O propósito
deste teste é comparar o software com o objetivo original. O teste de sistema é o
processo de tentar demonstrar a forma como o programa não cumpre os seus
objetivos; e, por definição, este teste é impossível se não houver um conjunto de
objetivos mensuráveis para o software (MYERS, 2004).
22
Segundo Myers (2004), existem algumas categorias principais de teste de
sistema, não que todas sejam aplicáveis a todos os softwares existentes, mas que
devem ser observadas, que são: teste de instalação, onde pode ser realizado
apenas na documentação, como um exercício mental sobre a documentação,
analisando se ela é suficiente; teste de carga, que é submeter o software a uma
carga alta de dados com o intuito de mostrar que o software se torna inutilizável para
uma determinada massa de dados; teste de stress, que é submeter o software a um
volume máximo de dados em um curto espaço de tempo, ou simular o número
máximo de usuários acessando ou de ações ao mesmo tempo; teste de usabilidade,
importante para verificar se as interfaces de usuário são especificas para os
usuários, são fáceis de entender e de aprender, as mensagens de erro são fáceis de
analisar e diagnosticar ou precisam de um PhD em ciências da computação; teste
de segurança, que verifica se os mecanismos de proteção incorporados ao software
irão, de fato, proteger os dados de invasões impróprias; teste de desempenho, que é
projetado para medir o desempenho de um software no contexto de um sistema
integrado e requer instrumentação tanto de hardware, para verificar utilização de
recursos, quanto de software, para verificar instruções ou registrar eventos; teste de
recuperação é um teste que força o erro de diversos modos e verifica se a
recuperação da falha é adequadamente realizada.
1.3.4 Teste de aceitação
O teste de aceitação é um tipo de teste caixa-preta, realizado antes de o
sistema ser disponibilizado. Tem por objetivo comparar os requisitos iniciais e as
atuais necessidades do usuário final. Normalmente, são conduzidos por um grupo
restrito de usuários finais em um ambiente similar, ou idêntico, ao que será utilizado
pelo software. Não é objetivo, portanto, encontra falhas, pois estas já foram
detectadas e resolvidas; o objetivo é verificar se o software faz aquilo que lhe foi
solicitado. Nesta fase, ocorrem os processos de verificação e validação para verificar
se o que foi especificado foi entregue e se o que foi entregue atende às
expectativas.
23
1.3.5 Teste de operação
O teste de operação é a fase em que o teste é conduzido pelos
administradores do ambiente final onde o software será disponibilizado. Nesta fase,
devem ser feitas simulações para garantir que o sistema entre em produção com
êxito. Envolve testes de instalação, segurança, confiabilidade, entre outros, de modo
a garantir o suporte ao negócio. Esta fase é aplicável somente a softwares que são
próprios de uma dada organização. Em alguns casos, o software a ser implantado é
um software substituto, portanto deve-se garantir que o suporte ao negócio será
mantido.
1.4 Automação de teste
A execução manual de um caso de teste é rápida e efetiva, mas a
execução e repetição de um vasto conjunto de testes é uma tarefa muito
dispendiosa e cansativa. É considerado normal que os testadores não verifiquem
novamente todos os casos a cada mudança. É partindo desta ideia que surgem os
erros de software, trazendo prejuízo para as equipes de desenvolvimento que
perdem muito tempo para identificar e corrigir os erros, além do estresse causado
tanto para a equipe quanto pelo usuário final causado pelo atraso na entrega, e do
descrédito atribuído à empresa, que entrega software com qualidade duvidosa.
Como é necessário muito esforço para executar todo o conjunto de testes
manualmente, dificilmente toda a bateria de testes será executada novamente a
cada alteração, o que facilita a entrada de erros de regressão, e a tendência é que
isso se repita até que a manutenção se torne uma tarefa tão custosa que a
reconstrução comece a ser levada em consideração (BERNARDO, KON, 2008).
Com a crescente exigência por software de qualidade, padrões de
qualidades impostos pelas pessoas de um modo geral e o advento de algumas
metodologias que recomendam, ou até explicitam, o uso intensificado dos testes
automatizados, como, por exemplo, o XP e TDD, que reconhecem que prevenir
defeitos é mais fácil e barato que identificá-los e corrigi-los posteriormente, o uso de
testes automatizados vem se tornando cada vez mais frequente.
24
Testes automatizados são rotinas que exercitam funcionalidades do
software sendo testados e fazem verificações automáticas nos efeitos colaterais
obtidos. A grande vantagem é que todos os casos de teste podem ser fácil e
rapidamente repetidos a qualquer momento e com pouco esforço (BERNARDO,
KON, 2008).
Alguns testes, por exemplo, podem ser facilmente reproduzidos
automaticamente, o que manualmente seria muito difícil, ou quase impossível, por
exemplo, simular inúmeros usuários acessando o sistema, através de uma
ferramenta, é necessário, apenas, uma simples configuração, o que chega a ser
trivial. Por outro lado, nem sempre é vantajoso automatizar os testes, pois existem
situações em que o teste manual é mais adequado. Por exemplo, se a interface de
usuário for mudar consideravelmente, qualquer automação teria que ser feita
novamente, ou quando o software é muito simples que não valha a pena o uso de
testes automatizados, o teste manual continua sendo uma boa opção. Então, antes
de se automatizar um determinado teste, deve-se analisar a necessidade dele, pois,
caso determinado teste não tenha a necessidade de ser reexecutado, não há motivo
para automatizá-lo (SANTOS, NETO, 2009).
A automação de um conjunto de teste geralmente demanda bem mais
esforço que sua execução manual, mas, quando automatizado, sua execução é
bastante simples. Assim, em algumas situações, automatizar é a melhor maneira de
economizar tempo e recurso (SANTOS, NETO, 2009).
Portanto, o teste automatizado não exclui o processo manual, pelo
contrário, entra como uma abordagem auxiliar excluindo as tarefas repetitivas ou
impraticáveis. Pois, assim como há algumas vantagens em automatizar, existem
algumas vantagens em testes manuais.
No próximo capitulo, será apresentado o contexto de automação de
testes, bem como algumas técnicas de revisão, algumas ferramentas de teste,
através da abordagem do objetivo, e como utilizar cada uma.
25
2 AUTOMAÇÃO DE TESTE
Antes de decidir automatizar um conjunto de testes, é preciso analisar o
software e quais testes serão construídos. O principal motivo para se automatizar um
teste é a necessidade de executá-lo diversas vezes. Em um caso típico, existe a
necessidade de se executar testes várias vezes. Isso normalmente é suficiente para
justificar a automação dos testes (SANTOS, NETO, 2009).
2.1 Contexto de testes automatizados
A execução manual de um caso de teste é rápida e efetiva, mas a
execução e repetição de um vasto conjunto de testes executados manualmente é
uma tarefa cara e entediante. É normal e compreensivo que os testadores não
verifiquem todos os casos de testes a cada mudança do código. E tão critico quanto
este cenário é o efeito “bola de neve”, pois, ao se realizar uma correção, dificilmente
toda a bateria de teste será executada, o que leva a erros de regressão
(BERNARDO e KON, 2008).
O teste, portanto é um elemento fundamental na garantia da qualidade.
Contudo, a sua realização de forma sistemática exige tempo e recurso. Assim, é
importante que os testadores utilizem ferramentas que o automatizem de alguma
forma. Os testes automatizados, embora venham a exigir mais tempo para
programar, dão mais segurança na manutenção e permitem a execução a qualquer
momento (SANTOS, NETO, 2009).
A automação de um conjunto de testes, geralmente, demanda bem mais
esforço que sua execução manual, mas, depois de automatizado, a execução é
bastante simples, portanto, automatizar os testes é uma boa maneira de economizar
tempo e dinheiro. Porém, mesmo automatizando parte do processo de teste, o
Retorno de Investimento (ROI) não é imediato, pois nem sempre ele tem um retorno
em curto prazo.
2.2 Técnicas de revisão
26
Cunha (2010) afirma que as ferramentas automatizadas de teste podem
ser classificadas como ferramentas de verificação de código fonte, ferramentas
de automatização na execução dos testes e ferramentas de gerenciamento. As
ferramentas são agrupadas de acordo com a função que executam. Esta
classificação auxilia na obtenção de ferramentas apropriadas para cada tipo de
análise a ser executada sobre o software e na obtenção de métricas, que auxiliam
na medição da qualidade do produto.
2.2.1 Ferramentas de verificação de código fonte
As técnicas de inspeção de código são uma forma de análise estática,
onde o programa é analisado sem ser executado. Estas inspeções seguem alguns
checklists de erros e heurísticas que identificam problemas comuns. Para alguns
erros e heurísticas é possível automatizar o processo de verificação em relação a
essas listas, o que resultou no desenvolvimento de analisadores estáticos
automatizados (SOMMERVILLE, 2007).
Os verificadores estáticos são ferramentas de software que varrem o
código fonte ou mesmo o código objeto, sem a execução do software. Este tipo de
ferramenta é utilizado para verificar se o software foi produzido dentro de padrões
estabelecidos de codificação, identificar código que não será executado, também
chamado de código morto, retirar classes de defeitos, etc. Este tipo de ferramenta
não verifica se o código realiza o que deveria realizar, portanto não verifica a
funcionalidade, analisando somente se o código está bem escrito (CUNHA, 2010).
Os verificadores estáticos de código podem verificar regras de estilo de
programação, erros ou ambos. Regras de estilo podem ajudar a prevenir certos tipos
de erros e melhorar a qualidade do software, porém as violações a essas regras não
implica, necessariamente, em um erro, mas podem ser vistas como um alerta de que
um trecho de código é crítico de alguma forma (TERRA, BIGONHA, 2008).
Portanto, é possível listar alguns benefícios da análise estática, que
seriam: encontrar erros e códigos de risco; fornecer um retorno objetivo aos
programadores para ajudá-los a reconhecer onde foram precisos ou imprecisos;
fornecer ao líder de projeto uma oportunidade para estudar o código-fonte, o projeto
27
e a equipe de uma perspectiva diferente; e retirar certas classes de defeitos, o que
possibilita que a equipe concentre-se mais nas deficiências do projeto (TERRA,
BIGONHA, 2008).
2.2.2 Ferramentas de automação
A automação de teste pode ser alcançada pelo uso de softwares
específicos para controlar a execução dos testes. A comparação dos resultados
esperados com os resultados obtidos, a configuração das pré-condições de teste e
outras funções de controle e relatório de teste podem ser obtidas através destes
softwares. Normalmente, a automação de teste envolve automatizar um processo
manual já existente que utiliza um processo descritivo formal.
As ferramentas de automação têm por objetivo auxiliar diretamente na
execução dos testes; através do apoio ao processo de testes. Elas permitem reduzir
as falhas introduzidas pela intervenção humana, aumentar a produtividade a médio e
longo prazo e, principalmente, possibilita tratar a automação de testes como um
projeto, uma vez que será necessário prazo e esforço para o levantamento das
ferramentas a serem utilizadas, configuração das mesmas e adequação do processo
de desenvolvimento para utilização das ferramentas (CUNHA, 2010).
Os tipos de automação são, normalmente, agrupados de acordo com a
forma como os testes automatizados interagem com a aplicação. Os tipos são
agrupados em dois paradigmas: baseados na interface gráfica, onde os testes
interagem diretamente com a interface gráfica através da simulação de um usuário;
e baseados na lógica de negócio, onde os testes exercitam as funcionalidades da
aplicação sem interagir com a interface gráfica. Este último implica, muitas vezes,
em alterar a aplicação para torná-la testável (CAETANO, 2007).
Quanto ao tipo de automação, as ferramentas de testes automatizados
costumam ser agrupadas em cinco tipos: baseadas na interface gráfica (capture /
playback); dirigidas a dados (data-driven); dirigidas a palavra-chave (keyword-
driven); baseadas na linha de comando (command line interface – CLI); baseadas na
interface de programação de aplicativos (Application Programming Interface – API) e
o Test Harness.
28
Na abordagem de testes automatizados baseados na interface gráfica, os
testes são realizados por meio da interface gráfica fornecida pela aplicação.
Normalmente a ferramenta fornece um recurso para capturar (capture) as ações do
usuário enquanto ele estiver usando a aplicação. Estas ações são gravadas em um
script, que pode ser reproduzido (playback) em outro momento.
Os testes automatizados dirigidos a dados representam uma vertente dos
testes baseados na interface gráfica. Basicamente, funcionam como um mecanismo
para auxiliar a execução de testes que repetem as mesmas ações várias vezes,
porém com dados diferentes. A principal vantagem é a reutilização dos scripts, o
que, consequentemente, diminui a complexidade e o tempo de manutenção.
Os testes dirigidos à palavra-chave foram criados para dar suporte aos
testes de aceitação explicitados pelas metodologias ágeis. Eles são realizados
através da interface gráfica da aplicação. Normalmente a ferramenta oferece um
conjunto pré-definido de palavras-chaves para permitir a criação dos testes. Cada
palavra-chave é um comando de alto nível que representa uma ação do usuário.
Já o teste automatizado baseado na linha de comando afirma que,
normalmente, a lógica de negócio da aplicação não deve ser amarrada à interface.
Em virtude disso, a lógica pode ser exercida através da execução de um conjunto de
comandos e parâmetros pré-determinados. Uma ferramenta de CLI interpreta os
comandos e parâmetros, executa a função selecionada e apresenta o resultado. O
objetivo é fornecer uma interface para o mundo exterior que não seja dependente da
GUI.
Uma API representa um conjunto de operações expostas por uma
aplicação com o intuito de permitir que outras possam acessar ou consumir as suas
funcionalidades. A automação baseada na API faz uso dessa característica para
guiar a execução dos testes. Uma das vantagens do uso da API é que a aplicação
externa se abstrai da forma como as operações são implementadas.
O Test Harness é um tipo de automação de teste baseado na lógica de
negócio que prega o uso racional e inteligente da automação. É um tipo que pode
ser construído por meio de pequenos programas para testar uma API, uma interface
de linha de comando, ou qualquer outra forma. Nesta abordagem não importa o
29
meio, desde que não haja interações com a interface gráfica. O objetivo é exercitar
as funcionalidades críticas do software que realizam variações difíceis de serem
testadas por meios normais.
2.2.3 Ferramentas de gerenciamento
As ferramentas de gerenciamento normalmente são utilizadas para fazer
a gestão de testes e defeitos. Por exemplo, uma ferramenta que permite que sejam
cadastrados os defeitos encontrados no software durante os testes. Essas
ferramentas auxiliam a gerenciar quais módulos devem ser testados e a escolher a
data de execução, entre outras atividades. Elas são responsáveis por fornecer uma
interface entre as ferramentas de execução, por realizar o gerenciamento de defeitos
e de requisitos, gerar os resultados e os relatórios de progresso de testes (CUNHA,
2010).
A gestão de defeitos é uma das atividades primordiais de um processo de
teste de software. Por meio de uma gestão, é possível acompanhar a qualidade do
software em teste com base nos defeitos cadastrados pelos testadores ao longo de
um ciclo de teste. Com base nesses dados, é possível identificar áreas
problemáticas da aplicação onde os riscos são maiores e planejar atividades
preventivas (CAETANO, 2007).
A gestão de defeitos pode ser realizada por meio de ferramentas
automatizadas chamadas de bug tracking system. Estas ferramentas oferecem um
repositório onde os membros da equipe podem cadastrar os defeitos, acompanhar o
ciclo de vida destes defeitos e emitir um relatório de gestão.
Já a gestão de testes é o coração de um processo de testes de software.
Ela é importante para o planejamento e controle das atividades de um projeto de
teste. Esta gestão pode ser utilizada através de ferramentas de gerenciamento de
teste (test management system). Estas ferramentas oferecem um banco de dados
onde os líderes de testes poderão criar suítes com casos de testes, atribuir os casos
de testes aos testadores, acompanhar o status da execução deles e emitir os
relatórios com métricas e estatísticas.
30
2.3 Ambiente para execução de teste automatizado
A qualidade e a produtividade da atividade de testes são diretamente
dependentes do critério de testes utilizados e da existência de uma ferramenta de
testes que os suportem. Sem a utilização de uma ferramenta automatizada, a
aplicação de um critério torna-se uma atividade propensa a erros e limitada a
programas muito simples (MALDONADO et al., 2006).
Outro fator importante para um bom ambiente de automatização de teste
é o suporte oferecido pelas ferramentas aos testes de regressão. Os casos de teste
utilizados durante a atividade de teste podem ser facilmente revalidados após uma
alteração.
Atualmente, várias ferramentas de teste podem ser incorporadas ao
ambiente de desenvolvimento, e esta prática é comum, pois as ferramentas são
configuradas em vários níveis. Exemplo disso são as ferramentas checkstyle,
findbugs e PMD. Estas ferramentas realizam a análise estática de código, porém
existem certos testes que são executados por uma ferramenta e por outra não.
Além das ferramentas de análise estática, existem as ferramentas de
teste unitário, como o JUnit, e as que auxiliam em testes de carga, de estresse e de
desempenho, como o JMeter, através da utilização dos testes unitários criados pelo
JUnit.
Estas ferramentas citadas foram escolhidas para uso neste trabalho por
terem foco em Java, por serem gratuitas, de fácil instalação e utilização. Também
podem apresentar os resultados de suas verificações em vários formatos, o que
facilita a integração com ferramentas de integração contínua, como a que será
utilizada, o Jenkins.
2.3.1 Checkstyle
O checkstyle, como dito anteriormente, é uma ferramenta de análise
estática de código utilizada no desenvolvimento do software para verificar se o
31
código gerado atende a um conjunto de regras.
A instalação do checkstyle é extremamente simples, bastando, apenas,
instalar o plug-in na IDE desejada, por exemplo, o Eclipse; e baixar o aplicativo
responsável pela execução.
O checkstyle disponibiliza uma série de módulos que podem ser
configurados para alterar o nível de rigor das regras que serão validadas. Caso a
regra desejada não esteja especificada, é possível definir algumas próprias,
aumentando, assim, a capacidade da ferramenta.
Assim como explicado no tópico 2.2.1 sobre as ferramentas de análise de
código fonte, o checkstyle não verifica se a rotina está funcionando corretamente,
mas checa se o código gerado atende aos padrões de codificação. Inicialmente esta
abordagem parece desnecessária, mas a longo prazo, o código gerado torna-se
mais legível e reutilizável, melhorando, assim, a sua manutenção.
O checkstyle foi desenvolvido em Java, dando-lhe a capacidade de
independência de sistema operacional. Depois de instalado, para executar o
checktyle é extremamente simples, bastando apenas invocá-lo via script de
automação, informando o diretório de fontes, um arquivo de configuração e o tipo de
saída a ser gerado, ou através da interface da IDE, conforme Figura 3.
Esta ferramenta é ideal para projetos onde se deseja forçar os
desenvolvedores e seguir um estilo padronizado de programação. Por ser altamente
configurável e dar suporte a qualquer padrão, ela permite verificar muitos aspectos
do código-fonte.
O checkstyle possui uma grande quantidade de módulos, cujo nível de
rigor pode ser configurado entre obrigatório e opcional. Um módulo verifica a adição
de comentários aos métodos, classes e pacotes, o que facilita o entendimento do
código, uma vez que não será necessário estudar o método ou a classe para
entendê-la. Outro, checa adesão à convenção de nomes para métodos e classes
estabelecidos pela fabricante e que é utilizada pelo mercado. Outro, verifica se
existem blocos de instruções vazios, um bloco de decisão vazio, por exemplo. Existe
um módulo responsável por checar se há condições lógicas muito complicadas, o
32
que dificulta a legibilidade do código. Um módulo verifica se existem procedimentos
que lançam tipos de erros ilegais e/ou genéricos, pois, pela regra definida pela
ferramenta, erros devem ser específicos de modo a facilitar o tratamento deles.
Figura 3 – Utilização da ferramenta de análise estática 2.3.2 Findbugs
O findbugs, assim como o checkstyle, também é uma ferramenta de
análise estática de código, mas com uma diferença: ele opera sobre o código objeto,
o bytecode.
Esta ferramenta trabalha, basicamente, com categorias de problema de
corretude, quando o código parece estar fazendo algo que o desenvolvedor não
pretende ou necessita fazer, como é o caso da atribuição de um valor nulo para uma
variável; más práticas, quando o código viola alguma boa prática, por exemplo, o
código sobrescreve o método equals, mas não sobrescreve o hashCode, pois,
segundo o fabricante da linguagem, a máquina virtual utiliza o hashCode para
verificar se dois objetos são iguais no método equals; vulnerabilidade de código,
33
quando o código permite ações não desejadas, como no caso de um possível
ataque de injeção de SQL.
Assim como o checkstyle, o findbugs também é desenvolvido em Java,
garantindo a portabilidade de sistema operacional. A instalação também é análoga,
seguindo os mesmos passos, que consistem em: baixar o aplicativo para que possa
ser executado através de uma chamada e baixar o plug-in na IDE desejada.
A execução do findbugs também é bastante simples. Depois de instalado,
basta invocá-lo através de um script e informar o diretório de fontes e a localização
dos bytecodes. Ele também pode ser invocado através da interface disponibilizada
na IDE, conforme ilustra a Figura 5.
É possível definir no findbugs o nível de severidade de cada problema
reportado pela ferramenta e indicar a partir de qual nível de severidade se deseja
analisar no código-fonte.
Figura 4 – Utilização da ferramenta de análise estática
O findbugs possui uma grande variedade de módulos, cujo nível de
34
esforço pode ser configurado entre mínimo, padrão e máximo. Em algumas
ocasiões, especialmente em projetos grandes, ocorre estouro de memória quando o
esforço é máximo. Para solucionar este problema, a ferramenta possibilita configurar
a quantidade de memória a ser utilizada.
Existe um módulo da ferramenta que checa se os recursos alocados
foram devidamente liberados, por exemplo, conexões com banco de dados, streams
de arquivos, etc. Existe outro módulo que verifica se as comparações entre objetos
do tipo String são efetuadas corretamente, comparando o valor da propriedade, não
o objeto. Outro módulo verifica se os operadores de curto-circuito estão sendo
utilizados, pois estes operadores otimizam a leitura da expressão lógica. Um módulo
interessante é o que verifica possíveis ataques de injeção de SQL, pois, em alguns
casos, é possível que o usuário realize determinadas operações no banco em que
não é possível pelos meios normais de utilização do software. Outro checa se há
uma possível invocação de uma propriedade com valor nulo, o que ocasionaria um
erro de referência nula. Além desses, há um módulo que verifica se o valor de
retorno de uma função está sendo ignorado.
2.3.3 PMD
O PMD, tal qual as ferramentas anteriores, é uma ferramenta de análise
estática de código.
A instalação do PMD também segue a mesma simplicidade das outras
ferramentas, portanto basta instalar o plug-in da IDE desejada e baixar o aplicativo
para execução.
Esta ferramenta é desenvolvida em Java, assim como as ferramentas
anteriores, e, assim como o checkstyle, o PMD permite a criação de novas regras.
Contudo, a execução do PMD difere um pouco das outras ferramentas, pois ele
possui um add-on chamado Copy-Paste Detector (CPD), que verifica a existência de
código duplicado. Porém, para executar somente o PMD, a ideia é a mesma, como
mostra a Figura 6. Neste caso, faz-se necessário apontar para o arquivo de
configurações, para o diretório de fontes e definir o tipo de saída. Para executar o
CPD, presente na mesma ferramenta, basta invocá-lo, informando o diretório de
35
fontes e a quantidade mínima de tokens para considerar um código duplicado,
conforme ilustrado na mesma imagem.
Assim como o checkstyle, o PMD tem evoluído bastante, pois foram
adicionados verificadores para outros propósitos. E, graças à possibilidade de
expansão da ferramenta, os desenvolvedores podem escrever novos detectores de
padrões de erro através da utilização tanto de Java quanto de XPath, que é um
conjunto de regras definidos em um arquivo XML (TERRA e BIGONHA, 2008).
Tanto o checkstyle quanto o PMD trabalham sobre o código-fonte,
enquanto que o findbugs sobre o código-objeto. Embora as ferramentas sejam
analisadores estáticos e funcionem sobre o mesmo objeto, os objetivos das
ferramentas são completamente distintos, portanto uma ferramenta não exclui a
outra, pelo contrário, complementa, aumentando, assim, o nível e a quantidade de
regras verificadas no código.
Figura 5 – Utilização da ferramenta de análise estática
O PMD possui uma grande variedade de módulos. Um módulo é
responsável por verificar se existe uma concatenação de Strings em um laço de
36
repetição, pois, segundo a fabricante do Java, o objeto String é imutável, portanto
uma concatenação gera um novo objeto, ocupando mais memória. Para otimizar
este processo, existem os construtores de String, que são o StringBuilder ou o
StringBuffer. Existe outro que é responsável por verificar se existem trechos de
código muito aninhados, o que vem a dificultar a legibilidade do código. Também é
possível verificar com outro módulo a existência de código desnecessário, ou código
“morto”, que é aquele trecho de código que jamais será executado. Outro módulo
checa a complexidade ciclomática de um trecho de código, com a prerrogativa de
que este trecho precisa ser reescrito. Quando o método é excessivamente longo,
outro módulo alerta sobre isso, afirmando que existem procedimentos do método
que podem ser extraídos para novos métodos. Se o nome de uma determinada
variável é curto, de uma a três letras, outro módulo lançará um erro, pois nomes
muito pequenos dificultam o entendimento da finalidade da variável. Além de existir
um módulo para verificar a obrigatoriedade do uso das chaves, para tornar o código
mais legível.
2.3.4 JUnit
O JUnit é um framework de teste utilizado para a realização de teste
unitário automatizado do tipo caixa-branca, onde o programador pode criar um
modelo padrão de testes para ser executado de forma sequencial.
Existem algumas vantagens em se utilizar o JUnit, como a possibilidade
da criação rápida de código de teste, aumentando, assim, a qualidade do software.
Uma vez escritos, os testes podem ser executados rapidamente sem a interrupção
da atividade de desenvolvimento. A ferramenta checa os resultados dos testes e
fornece uma resposta imediata. Um benefício importante é o baixo custo, uma vez
que a ferramenta é grátis.
Esta ferramenta é desenvolvida em Java, assim como as demais. Para
instalar basta baixar o aplicativo. Outra grande vantagem desta ferramenta é que ela
é facilmente integrável às várias IDE’s e ferramentas de automação, como o Ant e o
Maven.
37
Para utilizar esta ferramenta através de um script de automação, o
processo é um pouco mais complexo. Neste caso, é necessário alterar o classpath
da aplicação apontando para o diretório que contém os bytecodes, o código fonte do
software, o código fonte dos casos de teste, além, é claro, da própria ferramenta.
Além disso, é necessário indicar qual tipo de saída desejada, conforme mostra a
Figura 6.
No momento da criação dos testes, existem duas rotinas que são
executadas sempre: uma que é chamada antes de executar cada rotina de teste, o
setUp, e outra, que é chamada após a execução de cada rotina de teste, o
tearDown. Outras duas rotinas também são executadas sempre antes de uma
classe de teste, beforeClass; e outra, que é executada após, afterClass. Assim é
possível garantir que o ambiente se encontra com a mesma configuração antes e
depois da execução de cada rotina de teste.
O JUnit trabalha com o conceito de assertivas. Uma das boas práticas é
executar uma assertiva para cada condição e isolar cada uma em uma rotina
distinta, pois assim a complexidade da assertiva é menor e, caso haja uma falha, a
complexidade do erro é reduzida.
Figura 6 – Utilização da ferramenta de teste unitário
38
Ao adotar o JUnit como framework de teste unitário, é possível obter
algumas vantagens uma vez que o framework checa os resultados dos testes e
fornece uma resposta imediata, pois não é necessário executar toda a rotina de
testes para apresentar os resultados. Outra vantagem é o fato de ser orientado a
objetos, tornando a escrita de casos de teste mais fácil e natural para os usuários
Java. Ele fornece uma ótima API para criação de casos de teste, favorecida pelo
conceito de assertivas. Outra vantagem que vale ressaltar é o fato de ser grátis.
2.3.5 JMeter
O JMeter é uma ferramenta utilizada para testes de carga e de
desempenho. Para o JMeter, os usuários do sistema são representados como
threads. Dentro de um script, as threads executam a sequência de passos
determinada. Cada thread simula um usuário.
Thread é uma forma de um processo dividir a si mesmo em duas ou mais
tarefas que podem ser executadas concorrentemente (TANENBAUM, 2011).
O JMeter possui uma interface gráfica para se criar scripts de teste, como
mostra a Figura 7, onde é possível definir as ações do usuários que serão
executadas. Embora o JMeter consiga trabalhar a nível de interface gráfica, esta
ferramenta não consegue interpretar JavaScript, quando se trata de aplicação WEB.
É possível também executar os testes criados através do JUnit, fazendo uso de
ouvintes (listeners) disponibilizados pela ferramenta.
A região amarela mostra uma barra de menu que auxilia na criação de um
arquivo de um plano de teste, com as opções como novo, abrir, fechar, salvar, entre
outras, e também na execução do plano.
Já a região vermelha auxilia na criação dos procedimentos a serem
executados pelo caso de teste, através da definição de thread groups, que serão
executados como os usuários utilizadores da aplicação e na ação de cada usuário.
Por sua vez, a região verde é possíbilita definir os parâmetros que serão
39
utilizados por cada ação. Por exemplo, quantas vezes cada ação será executada.
Isso facilita a criação do plano de teste. Com o JMeter, também é possível fazer
testes em páginas web, porém, como dito anteriormente, ele não executa o código
JavaScript.
Figura 7 – Interface gráfica da ferramenta de teste de carga
O JMeter também é desenvolvido em Java, e também pode ser invocado
através de um script de automação, como mostra a Figura 8. Para invocá-lo, deve-se
informar o caminho para o diretório-raiz da ferramenta, o plano de teste a ser
utilizado e onde deve ser salvo o arquivo de saída. É possível, ainda, indicar a
quantidade de usuários que executará a rotina e quantas vezes ela será executada.
Para gerar o plano de teste, é necessário executar a ferramenta através da interface
gráfica, criar os passos a serem executados e salvar o plano.
40
Figura 8 – Utilização da ferramenta de teste de carga em um script
2.3.6 Jenkins
A integração contínua tornou-se muito importante no mercado de
desenvolvimento de software e isso, provavelmente, ocorreu devido ao grande
impacto causado pelas metodologias ágeis, pois ela garante que todo o sistema terá
um mínimo de funcionamento a cada build, mesmo que a equipe seja grande e
diversas partes do código sejam alteradas ao mesmo tempo (GUERRA, 2008).
O build pode ser executado de diversas formas a qualquer instante,
através de solicitação do usuário, via configuração para executar periodicamente ou
através de configuração para executar a cada commit.
A grande vantagem da integração continua está na resposta imediata.
Quando se dá a execução do build e algo quebra, a compilação ou um teste, a
equipe toma conhecimento imediatamente, através de e-mail ou de um alerta. A
integração contínua é uma forma de trazer mais segurança em relação a mudanças,
41
pois caso algo errado ocorra, a equipe será devidamente avisada.
O Jenkins é uma ferramenta de integração contínua, escrito em Java,
capaz de ser executado em servlet containers, como Tomcat, Jetty, entre outros. Ele
possui suporte para várias ferramentas de SCM, incluindo CVS, SVN e Git, e pode
executar o ANT e o Maven. O Jenkins é a nova versão do Hudson.
No estudo de caso, esta ferramenta será responsável por criar o ambiente
integrado de teste, onde haverá um ambiente que executa a chamada do script de
automação e que será responsável por exibir os relatórios da execução de cada tipo
de teste.
Uma grande vantagem desta ferramenta é a existência de diversos plug-
ins, que ampliam as capacidades da ferramenta e permitem a geração de relatórios
gráficos para cada teste. Com o relatório gráfico, é possível verificar o problema
relatado e encontrar a linha no código fonte onde o problema ocorre.
Ao entrar na tela inicial do Jenkins, deve ser feita a configuração para que
ele possa exibir os relatórios desejados. Para isso, os plug-ins correspondentes
devem ser instalados. Como as ferramentas em estudo são Checkstyle, PMD,
Findbugs, JUnit e JMeter, os seus respectivos plug-ins serão instalados, conforme
mostra a Figura 9.
(a) (b)
42
(c) Figura 9 – Fluxo de onde ir para instalar os plug-ins: Tela inicial do jenkins (a), como
acessar a lista de plug-ins (b), lista de plug-ins disponíveis (c). 2.4 Conclusões
As ferramentas apresentadas, de forma geral, são utilizadas
concomitantemente, de modo a compor um ambiente integrado de teste
automatizado. Embora existam ferramentas de mesma categoria, como checkstyle,
Findbugs e PMD, os objetivos destas são diferentes. Enquanto a primeira verifica se
o código atende a padrões de codificação, a segunda analisa padrões de erros e
sugere otimizações no código, e a última verifica outros padrões de erros e de
codificação, sugerindo uma “limpeza” no código, através da remoção de códigos não
utilizados. Para ilustrar melhor, a Tabela 1 mostra de forma resumida a diferença
entre estas ferramentas.
43
Tabela 1 – Tabela comparativa entre as ferramentas de análise estática
CARACTERÍSTICA CHECKSTYLE FINDBUGS PMD
Comentário de código Sim Não Não
Bloco catch vazio Sim Não Sim
Atribuição em subexpressão Não Não Sim
Conexão com banco de dados
não encerrada
Não Sim Sim
Não utilização de operador
lógico de curto-circuito
Não Sim Sim
Nome de variável Sim, verifica se
inicia com letra
minúscula
Não Sim, verifica se
inicia com letra
minúscula e se
tem mais de 4
caracteres
Utilização de comparação em
vez de método de comparação
Sim Sim Sim
Ignorar valor de retorno Não Sim Não
No próximo capítulo, será apresentado o estudo de caso com o ambiente
montado, mostrando o funcionamento das ferramentas no ambiente integrado.
44
3 ESTUDO DE CASO
O estudo de caso visa apresentar o funcionamento das ferramentas no
que se refere à execução dos testes de sistemas. Ele apresenta alguns exemplos de
testes executados sobre uma aplicação existente, rodando testes com as seguintes
ferramentas checkstyle, findbugs e pmd, para análise estática de código, testes
unitários com o JUnit; teste de carga e desempenho com o JMeter em um ambiente
gráfico que executa um script Ant e apresenta o relatório de cada tipo de teste.
O objeto de estudo consiste em configurar um projeto no Jenkins, aplicar
as ferramentas, configurar os relatórios e analisar os resultados.
3.1 Especificação
Como o foco do trabalho é apresentar um ambiente integrado de teste
automatizado, testes estes baseados em técnicas caixa-branca e utilizando a
ferramenta de integração contínua Jenkins, foi utilizada a aplicação para executar os
testes, simulando a utilização deste ambiente integrado em um ambiente de
desenvolvimento real.
Com o intuito de demonstrar o funcionamento das ferramentas, e por
consequência do ambiente, foi escolhido um cenário de execução onde serão
executados os testes.
O cenário consiste em uma aplicação Web de um sistema de
gerenciamento de eventos, que possui uma tela de cadastros de eventos, outra para
criação de dormitórios, outra de alocação de pessoas nos dormitórios, um formulário
para efetuar o recebimento de pagamento e opções para geração de relatórios, além
da tela de login, conforme mostra a Figura 10, que sofrerá as execuções das
ferramentas de análise estática que indicarão os pontos de falha ou melhoria, dos
testes unitários e do teste de desempenho.
45
(a) (b)
(c) (d)
Figura 10 – Contendo algumas telas do sistema Web: Tela de login de acesso ao
sistema (a), tela de cadastro de evento (b), tela de cadastro de dormitório (c) e a tela de cadastro de participante (d).
Para realizar o cadastro de evento ou de dormitório, o usuário deve ser
um administrador. Esta verificação é realizada na camada de controle. Já para
realizar o cadastro de participante não se faz necessário que seja um administrador.
A validação dos dados é realizada na cama de modelo.
O checkstyle foi configurado para verificar regras que se atenham
somente a convenção de codificação da linguagem. Já o Findbugs e o PMD foram
configurados para executarem as regras padrões, executadas quando não se é
explicitada nenhuma configuração adicional, e serão configurados para executarem
com esforço máximo, coletando a maior quantidade de falhas possível.
Finalmente, após as execuções, serão gerados relatórios para
apresentarem os resultados das execuções.
46
3.2 Configuração do ambiente
Inicialmente será necessário alterar o script de automação de build do
projeto para configurar as ferramentas para exportarem seus resultados como
arquivo XML. Esta configuração se faz necessária para que os plug-ins das
ferramentas consigam interpretá-los e exibi-los de forma gráfica. Após isso, todas as
outras atividades serão realizadas na ferramenta de integração contínua.
Portanto, o próximo passo é configurar o projeto dentro da ferramenta,
atribuindo-lhe um nome e escolhendo o tipo do projeto; para o estudo de caso, será
escolhido o tipo de projeto free-style.
Este tipo de projeto contém alguns elementos que facilitam a sua criação
e configuração, em que um dos elementos consiste em uma configuração que
indique a ferramenta SCM, como CVS (sistema de versões concorrentes), ou SVN
(Apache Subversion), que mantém o código fonte. Ferramentas SCM facilitam a
gerência de configuração através do versionamento do software; outra configuração
é responsável por controlar quando a ferramenta irá executar uma construção, pois,
em certos casos, é interessante que a construção seja executada em determinado
período, como ocorre em alguns frameworks de mercado que possuem a construção
noturna (nightly build), como o Hibernate ou JBoss, ou a cada alteração no código.
Existe uma configuração responsável por indicar quais scripts são responsáveis pela
construção, que será responsável por orquestrar a construção; há uma configuração
que possibilita o armazenamento de fingerprints, que são os artefatos que devem
ser armazenados e vinculados à versão da construção, como resultados dos testes,
documentação, resultado dos testes, executáveis, entre outros. Também é possível
configurar para notificar, através de e-mail, algumas pessoas com o resultado da
construção, isso facilita o acompanhamento do projeto por parte do gerente ou dos
desenvolvedores.
Após isso, será possível configurar, dentre outras características, os
passos a serem executados durante e após a execução do script. A apresentação
dos relatórios é uma ação pós-construção, pois é na construção que os testes são
executados e os resultados são gerados e exportados para arquivo do tipo XML.
47
Após a execução da construção, nota-se uma alteração na interface, que
agora possibilita ver os resultados das ferramentas. A partir das novas opções é
possível visualizar os resultados através de um relatório gráfico que é alterado de
acordo com as construções executadas. É possível visualizar a categoria de erro, o
pacote, a unidade e o trecho de código que contém o erro encontrado.
Através do relatório, é possível acompanhar o progresso, regresso, ou a
constância do projeto uma vez que o gráfico se altera a cada construção realizada.
Também é possível navegar pelo relatório com o intuito de encontrar o pacote, a
unidade ou a linha de código da unidade em que a falha ocorreu. Após selecionar o
relatório desejado, clicando no gráfico ou nas opções que aparecem à esquerda,
serão listados os pacotes contendo as unidades que possuem aquela categoria de
defeito ou falha e, após selecionar o pacote, serão exibidas as unidades e, ao
selecionar a unidade, serão exibidas as linhas que possuem a falha, conforme
mostra a Figura 11.
(a) (b)
(c) (d)
48
(e) (f)
Figura 11 – Fluxo de configuração de um projeto: Tela inicial do Jenkins, destacando a opção que habilita a criação de novo projeto (a), tela de configuração do nome e do tipo do projeto (b), configuração dos relatórios das ferramentas (c), novas opções habilitadas após a execução e geração dos relatórios (d), apresentação dos pacotes que possuem certas categorias de erro (e), e unidade que possui os erros analisados (f).
Para os testes realizados pelo JUnit, o resultado é apresentado quando
ocorre uma falha. Os resultados são apresentados textualmente e o status do build é
marcado como instável. A indicação é o ícone amarelo ao lado do nome do projeto.
3.3 Análise dos resultados
De acordo com os resultados obtidos na execução do cenário proposto,
observou-se que as ferramentas de análise estática apresentam o resultado
esperado, desde a execução dos testes até a apresentação dos resultados, com a
possibilidade de uma checagem configurável. Esta configuração pode ser geral ou
por projeto, e a invocação desta configuração fica a cargo de cada ferramenta,
através do script de automação. A criação e a manutenção do ambiente também são
facilitadas graças ao Jenkins, que automatiza estes processos. A facilidade de
acesso à informação e de compreensão desta também são auxiliadas pelos plug-ins
da ferramenta de integração contínua.
Há muitas vantagens na utilização do Jenkins como ferramenta de
integração contínua, como a vantagem da facilidade e disponibilidade de acesso e
de compreensão da informação, pois a ferramenta de integração contínua procura
agrupar por ferramenta de teste, grupo de erro e pacote de unidades, e exibir um
49
gráfico em área 2D, de modo a tornar mais claro e objetivo os resultados das
execuções dos testes. Outra vantagem é a capacidade de customizar o
comportamento da ferramenta, fazendo com que seja possível adequar tanto o
processo de desenvolvimento existente quanto a ferramenta em si.
Por outro lado, existem cenários em que o ambiente não apresentou o
resultado esperado, pois eram cenários que estavam desenvolvidos de modo a não
facilitar, ou até mesmo impedir, o desenvolvimento de testes unitários, devido ao alto
grau de acoplamento e à baixa coesão. No estudo de caso, estava bastante
complicado simular um cenário de cadastro de evento ou de dormitório uma vez que
as validações estavam espalhadas pelo código quando deveriam estar agrupadas. A
boa prática de desenvolvimento afirma que não é aconselhável realizar validações
na camada de modelo.
Também foram detectados alguns problemas, como o plug-in para o JUnit
apresentar, ocasionalmente, uma falha que impedia a geração do relatório gráfico,
fazendo com que a saída fosse simplesmente textual, embora seja possível rastrear
o ponto de falha.
Portanto, em linhas gerais, pode-se afirmar que o ambiente integrado de
teste possui boa aplicabilidade, devido à sua facilidade de instalação, configuração e
manutenção. As ferramentas, isoladamente, auxiliam no desenvolvimento e na
manutenção do software, e também servem de alerta para pontos onde existem
erros em potencial.
Devido à integração das ferramentas com uma IDE, é possível, também,
não gerar um processo extra, evitando adicionar trabalho à equipe de
desenvolvimento, mantendo, assim, esta focada em seu serviço. Em longo prazo, a
equipe de desenvolvimento tratará de evolução do software, reduzindo o retrabalho
e, consequentemente, o custo do projeto.
50
CONCLUSÃO
Neste trabalho são demonstradas as fases de criação, utilização e
aplicação de um ambiente integrado de teste automatizado, através de ferramenta
de análise estática de código, como as ferramentas Checkstyle, Findbugs e PMD,
teste unitário com JUnit e teste de desempenho com o JMeter. Neste caso, foi
abordada desde a invocação de cada chamada através de um script de automação,
passando pela configuração de cada ferramenta, até a exportação dos resultados,
tudo em um ambiente integrado de teste.
Inicialmente é apresentada a visão geral de testes, mostrando o seu
planejamento, o plano de execução, a execução, a análise dos resultados e o
encerramento do processo. Em seguida, são apresentadas as técnicas de teste,
mostrando as principais características de cada uma. Depois são ilustradas as fases
de teste, e, por fim, é definida uma proposta de automação, pois a execução manual
destes testes levaria muito tempo. A ideia é que a execução automatizada é mais
rápida e evolui juntamente com o software, obtendo ganho no tempo de resposta e
executando os mesmos testes.
Adiante, é apresentado o contexto dos testes automatizados, mostrando
que automatizar um teste é uma decisão de projeto que deve ser encarada de
acordo com a necessidade do que se espera do produto. São apresentadas técnicas
de revisão e categorias de ferramentas, onde cada ferramenta apresentada possui
uma gama de configurações e realizam análises estáticas sobre o código, auxiliando
o desenvolvimento e a manutenção pela equipe de desenvolvimento. As ferramentas
de testes unitários, que seriam responsáveis por testar os fluxos do sistema de
forma rápida e efetiva. Por fim, é apresentada uma ferramenta que integra todas as
outras apresentadas em um ambiente limpo e configurável, sendo responsável por
realizar as construções do produto e apresentar os resultados de forma clara e
objetiva.
Em seguida, é demonstrado, através de um estudo de caso, a criação e a
configuração do ambiente integrado, mostrado as vantagens e desvantagens do
ambiente. O objetivo é apresentar e avaliar o funcionamento e a execução dos
51
testes em um dado cenário, e apresentar os resultados de modo a acompanhar a
evolução do software em relação ao tempo de desenvolvimento.
Diante da análise efetuada sobre as ferramentas levantadas no estudo, o
Jenkins destacou-se por oferecer integração com outras ferramentas através de
plug-ins, facilitando a coleta e apresentação dos resultados. Além disso, também
existe a facilidade de configuração do projeto e de configuração da utilização das
ferramentas. Como parte integrante do ambiente de teste de desenvolvimento, o
JMeter se destaca por facilitar o teste de desempenho que, em um ambiente de
teste manual, torna-se muito difícil, ou até mesmo impossível.
Portanto, a criação de um ambiente integrado de teste é essencial para
projetos de médio e grande porte uma vez que nele haverá informações necessárias
para auxiliar no processo de tomada de decisão quanto ao projeto, mostrando de
forma clara o seu andamento, apresentando pontos que necessitam de um cuidado
especial, por exemplo, trechos que demoram a ser executados, ou que rapidamente
chegam a uma situação de demora.
Vale ressaltar que não é possível mensurar o valor economizado em
virtude da utilização dos testes. Dentre as práticas comuns, está a de avaliar
comparativamente com outros projetos semelhantes, porém em que não foram
adotadas rotinas automatizadas de teste.
A partir deste trabalho, podem ser originados trabalho futuros, como o uso
de ferramentas de captura e repetição de eventos sobre a interface gráfica, como,
por exemplo, o Selenium, e a realização destes testes, simulando o acesso de
múltiplos usuários através do JMeter, ou o desenvolvimento de testes para
dispositivos móveis, abordando o Selenium for Android.
52
REFERÊNCIAS
ALMEIDA, Carla. Introdução teste de Software. Disponível em: <http://www.linhadecodigo.com.br/artigo/2775/introducao-ao-teste-de-software.aspx>. Acesso em: 03 ago. 2012. BERNARDO, Paulo Cheque. KON, Fabio. A Importância dos Testes Automatizados. (Engenharia de Software Magazine, p. 1-7, 2008). BARTIE, Alexandre. Processo de Teste de Software – Parte 01. Disponível em: <http://imasters.com.br/artigo/6102/des_de_software/processo_de_teste_de_software_-_parte_01>. Acesso em: 01 ago. 2012. CAETANO, Cristiano. Automação e Gerenciamento de Testes. São Paulo: Digital Works. CAETANO, Cristiano. Introdução à Automação de Testes Funcionais. Disponível em: <http://www.testexpert.com.br/?q=node/178>. Acesso em: 27 set. 2012. CUNHA, Simone. Ambientes de Teste. Disponível em: <http://testwarequality.blogspot.com.br/p/ambientes-de-testes.html>. Acesso em: 19 set. 2012. GUERRA, Cauê. Integração Contínua e o processo Agile. Disponível em: <http://blog.caelum.com.br/integracao-continua/>. Acesso em: 16 out. 2012. PRESSMAN, Roger S. Engenharia de Software. 6 ed. São Paulo: Pearson Education do Brasil, p. 315-347, 2005. MALDONADO, Jose Carlos. BARBOSA, Ellen Francine. VINCENZI, Auri Marcelo Rizzo. DELAMARO, Marcio Eduardo. SOUZA, Simone do Rocio Senger de. JINO, Marcio. Introdução ao Teste de Software. (Universidade de São Paulo, p.1-49, 2006).
MORAIS, Lenildo. MATOS, Renata. Transição de Testes Tradicionais para Ágeis: Uma Experiência Prática.
MYERS, Glenford J. The art of software testing. (Corey Sandler, p. 5-20, 2004).
NOGUEIRA, Elias. Automação de Teste - Decisão por Automatizar. Disponível em: <http://sembugs.blogspot.com.br/2010/04/automacao-decisao-por-automatizar.html>. Acesso em: 8 abr. 2010. TANENBAUM, Andrew S. Sistemas Operacionais Modernos. 3 ed. São Paulo: Prentice Hall, 2011. p. 50-105.
53
TERRA, Ricardo. BIGONHA, Roberto S. Ferramentas para Análise Estática de Códigos Java (Departamento de Ciência da Computação - UFMG, p. 1-6, 2008).
SOMMERVILLE, Ian. Engenharia de Software. 8. ed. São Paulo: Pearson Education, 2007. Cap. 22, p. 339-353.
STAA, Arndt von; JUNIOR, Gilberto Pavoni. Retrabalho corrói eficiência do teste de Software, Brasil 2011. Disponível em <http://itweb.com.br/48984/retrabalho-corroi-eficiencia-do-teste-de-software/> Acesso 04/2012.