Você está na página 1de 221

Padres de testes automatizados

Paulo Cheque Bernardo


DISSERTAO APRESENTADA
AO
INSTITUTO DE MATEMTICA E ESTATSTICA
DA
UNIVERSIDADE DE SO PAULO
PARA
OBTENO DO TTULO
DE
MESTRE EM CINCIA DA COMPUTAO
Programa: Cincia da Computao
Orientador: Prof. Dr. Fabio Kon
Durante o desenvolvimento desta pesquisa, o autor recebeu apoio do Projeto Qualipso
nanciado pela European Commission.
So Paulo, junho de 2011
Padres de testes automatizados
Esta tese/dissertao contm as correes e alteraes
sugeridas pela Comisso Julgadora durante a defesa
realizada por Paulo Cheque Bernardo em 04/07/2011.
O original encontra-se disponvel no Instituto de
Matemtica e Estatstica da Universidade de So Paulo.
Comisso Julgadora:
Prof. Dr. Fabio Kon IME-USP (Orientador) - IME-USP
Prof. Dr. Alfredo Goldman vel Lejbman IME-USP
Prof. Dr. Mrcio Eduardo Delamaro ICMC-USP
Agradecimentos
Agradeo especialmente minha famlia: meus pais Carlos e Gersi e meus irmos Pedro, Carlos e
Srgio, alm de meu tio Nairson, no s por serem os principais responsveis por tornarem possvel a
minha trajetria acadmica, como tambm por terem me ensinado os valores de integridade e carter.
Tambm agradeo ao meu professor e orientador Fabio Kon, por toda conana que depositou em
mim desde a graduao, pelas diversas oportunidades prossionais e acadmicas proporcionadas, pela
pacincia e pelo incentivo durante os momentos difceis, almde ser umgrande exemplo de competncia
e disciplina.
Bons amigos da graduao e mestrado tambm so responsveis diretos por este trabalho, devido
troca de conhecimento e, principalmente, por todo o apoio e incentivo. Por isso, agradeo a Alexandre
Onishi, lvaro Miyazawa, Adalberto Kishi, Ana Paula Mota, Camila Pacheco, Andr Guerra, Beraldo
Leal, Celso Shimabukuro, Cristina Fang, Dairton Bassi, Daniel Cordeiro, Eduardo Katayama, Erich
Machado, Flvio Mori, Gustavo Duarte, Mario Torres, Paulo Meirelles, Raphel Cobe, Ricardo Lazaro
e Ricardo Yamamoto.
Durante o mestrado trabalhei em rgos pblicos, empresas e cooperativas e em todos esses locais
adquiri conhecimento e experincia que foramfundamentais para o desenvolvimento deste trabalho. Por
isso, agradeo a todos que me ajudaram das instituies AgilCoop, Assemblia Legislativa do Estado
de So Paulo, Pr-Reitoria de Ps-Graduao da Universidade de So Paulo, UOL e Nokia Siemens
Networks. Em especial, tambm agradeo ao projeto QualiPSo pelos mesmos motivos e tambm pelo
incentivo minha pesquisa.
4
Padres e Antipadres de Testes de Unidade
Padres
(Testabilidade) Injeo de Dependncia (Dependency Injection): Seo 6.4.1, Pgina 75
(Testabilidade) Objeto Humilde (Humble Object): Seo 6.4.2, Pgina 81
(Testabilidade) Objeto Tolo (Dummy Object): Seo 6.4.3, Pgina 84
(Testabilidade) Objeto Stub (Test Stub): Seo 6.4.4, Pgina 86
(Testabilidade) Objeto Falsicado (Fake Object): Seo 6.4.5, Pgina 87
(Testabilidade) Objeto Emulado (Mock Object): Seo 6.4.6, Pgina 89
(Testabilidade) Objeto Espio (Test Spy): Seo 6.4.7, Pgina 90
(Organizacional/Robustez/Testabilidade) Objeto Prottipo: Seo 6.4.8, Pgina 95
(Qualidade) Teste por Comparao de Algoritmos: Seo 6.4.9, Pgina 98
(Qualidade) Teste por Probabilidade: Seo 6.4.10, Pgina 100
(Qualidade) Vericar Inversibilidade: Seo 6.4.11, Pgina 103
(Qualidade) Vericar Valores Limites: Seo 6.4.12, Pgina 106
Antipadres
(Organizacional) Gancho para os Testes (Test Hook): Seo 6.5.1, Pgina 111
(Organizacional) Testes Encadeados (Chained Tests): Seo 6.5.2, Pgina 112
a
Padres de Testes com Persistncia de Dados
Padres
(Organizacional) Uma Instncia de Banco de Dados por Linha de Execuo: Seo 7.2.1, Pgina
118
(Robustez) Gerao Dinmica de Dados: Seo 7.2.2, Pgina 119
b
Padres e Antipadres de Testes de Interface de Usurio
Padres
(Organizacional) Tela como Unidade: Seo 8.4.1, Pgina 8.4.1
(Organizacional) Estado Inicial da Tela: Seo 8.4.2, Pgina 8.4.2
(Organizacional) Camada de Abstrao de Funcionalidades: Seo 8.4.3, Pgina 8.4.3
(Organizacional) Fotograa do Teste: Seo 8.4.4, Pgina 8.4.4
(Robustez) Localizar Elemento por ID: Seo 8.4.5, Pgina 8.4.5
(Robustez) Localizar Elemento por Tipo do Componente: Seo 8.4.6, Pgina 8.4.6
(Robustez) Localizar Clula de Tabela pelo Cabealho e Contedo: Seo 8.4.7, Pgina 8.4.7
Antipadres
(Organizacional) Navegao Encadeada: Seo 8.5.1, Pgina 149
(Robustez) Localizar Elemento pelo Leiaute: Seo 8.5.2, Pgina 149
(Robustez) Vericaes Rgidas: Seo 8.5.3, Pgina 149
c
Lista de Ferramentas/Arcabouos/Sistemas
Ferramentas de Testes Criadas pelo Autor
Django Dynamic Fixture: code.google.com/p/django-dynamic-fixture
Python-QAssertions: code.google.com/p/python-qassertions
Util4Testing: sourceforge.net/projects/util4testing
Util4Selenium: sourceforge.net/projects/util4selenium
Outras Ferramentas Criadas pelo Autor
Card Game Engine: code.google.com/p/cardgameengine
Sistemas Citados que o Autor Ajudou a Desenvolver
Janus: sistemas.usp.br/janus
GinLab: ginlab.com
Ferramentas de Testes Automatizados
JUnit: junit.org
TestNG: testng.org
Hamcrest: code.google.com/p/hamcrest
Mockito: mockito.org
Python-Mockito: code.google.com/p/mockito-python
EasyMock: easymock.org
JMock: jmock.org
Parallel-Junit: https://parallel-junit.dev.java.net
JUnit-Max: www.junitmax.com
CUnit: cunit.sourceforge.net
Python UnitTest: pyunit.sourceforge.net/pyunit.html
JSUnit: jsunit.net
Jaml-Unit: www.isr.uci.edu/~lopes/
BDoc: code.google.com/p/bdoc
MockEJB: mockejb.org
HTMLUnit: htmlunit.sourceforge.net
JWebUnit: jwebunit.sourceforge.net
Selenium-WebDriver: seleniumhq.org,openqa.org
Selenium-Grid: selenium-grid.seleniumhq.org
Selenium-IDE: seleniumhq.org/projects/ide
Selenium-RC: seleniumhq.org
d
Fest: code.google.com/p/fest
Marathon: java-source.net/open-source/testing-tools/marathon
Jemmy: https://jemmy.dev.java.net
Fit: fit.c2.com
Fitnesse: fit.c2.com
Cucumber: cukes.info
RSpec: rspec.info
JDave: www.jdave.org
JBehave: jbehave.org
TestDox: agiledox.sourceforge.net
Testability Explorer: code.google.com/p/testability-explorer
Emma: emma.sourceforge.net
Eclemma: eclemma.org
Continuum: continuum.apache.org
CruiseControl: cruisecontrol.sourceforge.net
JMeter: jakarta.apache.org/jmeter
Outras Ferramentas
Firefox: www.mozilla.com
Django: www.djangoproject.com
Grails: grails.org
Lift: liftweb.net
Rails: rubyonrails.org
Maven: maven.apache.org
Spring-JDBC: static.springsource.org/spring/docs/2.0.x/reference/jdbc.html
Spring-Framework: www.springsource.org
HyperSQL (HSQLdb): hsqldb.org
SQLite: www.sqlite.org
VirtualBox: www.virtualbox.org
Windows Virtual PC: www.microsoft.com/windows/virtual-pc
VMWare: www.vmware.com
i
ii
Resumo
A qualidade dos sistemas de software uma preocupao de todo bom projeto e muito tem se estudado
para melhorar tanto a qualidade do produto nal quanto do processo de desenvolvimento. Teste de
Software uma rea de estudo que tem crescido signicativamente nos ltimos tempos, em especial
a automao de testes que est cada vez mais em evidncia devido agilidade e qualidade que pode
trazer para o desenvolvimento de sistemas de software. Os testes automatizados podem ser ecazes e
de baixo custo de implementao e manuteno e funcionam como um bom mecanismo para controlar
a qualidade de sistemas.
No entanto, pouco conhecimento sobre a rea e erros comuns na escrita e manuteno dos testes
podem trazer diculdades adicionais aos projetos de software. Testes automatizados de baixa qualidade
no contribuem efetivamente com o controle de qualidade dos sistemas e ainda demandam muito tempo
do desenvolvimento.
Para evitar esses problemas, esta dissertao apresenta de forma crtica e sistemtica as principais
prticas, padres e tcnicas para guiar o processo da criao, manuteno e gerenciamento dos casos
de testes automatizados. Inicialmente, so feitas comparaes entre a automao de testes e outras
prticas de controle e garantia de qualidade. Em seguida, so apresentados os problemas e solues mais
comuns durante a automao de testes, tais como questes relacionadas a tipos especcos de algoritmos,
sistemas com persistncia de dados, testes de interfaces de usurio e tcnicas de desenvolvimento de
software com testes automatizados. Para nalizar, a dissertao traz uma reexo sobre o gerenciamento
e a abordagem da automao de testes para tornar o processo mais produtivo e ecaz.
Palavras-chave: Testes Automatizados, TDD, XP, Mtodos geis, Teste de Software
iii
iv
Abstract
The quality of software systems is a concern of every good project and much has been studied to im-
prove the quality of the nal product and process development. Software Testing is an increasing area,
especially test automation, which is in evidence due to the speed and quality that it may bring to the
development of software systems. Automated tests can be effective and can have a low cost of imple-
mentation and maintenance to ensure and control the quality of the systems.
However, little knowledge about the area and common errors in writing and maintaining tests may
bring additional difculties to the software projects. Low quality automated tests do not contribute
effectively to quality control systems and still take a long time of development.
To avoid these problems, we present critically and systematically the core practices, standards and
techniques to guide the process of creation, maintenance and management of automated test cases. Ini-
tially, comparisons are made between the test automation, other control practices, and quality assurance.
Next, we present the most common problems and solutions for the automation of tests, such as issues
related to specic types of algorithms, systems with data persistence, testing user interfaces and tech-
niques for software development with automated tests. Finally, this essay reects on the management
and approach to test automation to make the process more productive and effective.
Keywords: Automated Tests, TDD, XP, Agile Methods, Software Testing
v
vi
Prefcio
Esta dissertao de mestrado organizada em onze captulos divididos em trs partes: Introduo e
Conceitos (Parte I), Prticas, Padres e Tcnicas para Testes de Correo (Parte II) e Gerenciamento de
Testes Automatizados (Parte III).
Em todo o decorrer das trs partes da dissertao, muitas ferramentas e sistemas so utilizadas ou
mencionadas para fortalecer as discusses. Por isso, nas pginas iniciais foi adicionada uma listagem de
todos os programas citados, destacando quais tiveram participao do autor desta dissertao. O objetivo
informar, de forma prtica e coesa, os respectivos endereos Web para referncia.
A Parte I composta de quatro captulos introdutrios que abordam inicialmente o contexto e as
motivaes do estudo de testes automatizados. Posteriormente, apresentada a nomenclatura dessa
rea de estudo e que ser utilizada no decorrer do trabalho. Para nalizar, sero discutidas algumas
recomendaes bsicas para quaisquer projetos que utilizem Testes Automatizados.
J a Parte II dedicada s informaes tcnicas que ajudam na implementao dos Testes Automati-
zados de Correo. Essa parte possui muitos exemplos de cdigo-fonte e de ferramentas; as linguagens
de programao utilizadas so Python, Java, Scala e C. Grande parte das informaes apresentadas
nessa parte esto na forma de padres, que uma maneira estruturada e coesa de apresentar solues
para problemas recorrentes. Para agilizar o estudo desses padres por consulta, foi includo nas pginas
inicias uma listagem de todos os padres e antipadres citados, contendo os nmeros da sees e das
pginas correspondentes.
Por m, a Parte III discute questes de gerenciamento de projetos que possuem Testes Automatiza-
dos. Primeiramente, so apresentadas as principais mtricas relacionadas com Testes Automatizados.
Por ltimo, so resumidas as principais concluses encontradas por esse estudo, alm de novas pesquisas
que podem ser realizadas como extenses do presente trabalho.
vii
viii
Sumrio
Lista de Figuras xv
I Introduo e Conceitos 1
1 Introduo 3
1.1 Objetivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.2 Motivao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.3 A quem se destina . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.4 Trabalhos Relacionados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2 Testes Automatizados 9
2.1 Cenrio de Desenvolvimento com Testes Manuais . . . . . . . . . . . . . . . . . . . . . 9
2.2 A Abordagem dos Testes Automatizados . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.3 Histria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.4 Mtodos geis de Desenvolvimento . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.4.1 Programao eXtrema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.5 Software Livre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.6 Qualidade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.7 Concluses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3 Denies e Terminologia 23
3.1 Abordagens de Controle de Qualidade . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
3.2 Termos e Siglas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
3.3 Tipos de Testes Automatizados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
3.3.1 Teste de Unidade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
3.3.2 Teste de Integrao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
3.3.3 Teste de Interface de Usurio . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
3.3.4 Teste de Aceitao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
3.3.5 Teste de Desempenho . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
3.3.6 Teste de Carga . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
3.3.7 Teste de Longevidade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
3.3.8 Testes de Segurana . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
3.4 Tcnicas de Teste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
3.4.1 Testes Aleatrios (Random Tests) . . . . . . . . . . . . . . . . . . . . . . . . . 35
3.4.2 Teste de Fumaa (Smoke Tests) . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
3.4.3 Teste de Sanidade (Sanity Tests) . . . . . . . . . . . . . . . . . . . . . . . . . . 36
3.5 Consideraes Finais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
ix
4 O Processo de Automao de Testes 41
4.1 Viso Geral . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
4.2 Quem Deve Implementar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
4.3 Quando Implementar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
4.4 Onde Executar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
4.5 Quando Executar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
4.6 Documentao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
4.7 Consideraes Finais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
II Prticas, Padres e Tcnicas para Testes de Correo 49
5 Introduo da Parte II 51
5.1 Testes de Correo de Qualidade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
5.2 Indcios de Problemas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
5.3 Denio de Padro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
5.4 Denio de Antipadro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
6 Testes de Unidade 59
6.1 Arcabouos para Testes de Unidade . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
6.1.1 Set up e Tear down . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
6.2 Objetos Dubls (Test Doubles) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
6.3 Boas Prticas de Automao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
6.3.1 Cdigo-Fonte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
6.3.2 Refatoraes Comuns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
6.3.3 Orientao a Objetos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
6.3.4 Orientao a Aspectos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
6.3.5 Reexo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
6.3.6 Mdulos Assncronos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
6.4 Padres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
6.4.1 Injeo de Dependncia (Dependency Injection) . . . . . . . . . . . . . . . . . 75
6.4.2 Objeto Humilde (Humble Object) . . . . . . . . . . . . . . . . . . . . . . . . . 81
6.4.3 Objeto Tolo (Dummy Object) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
6.4.4 Objeto Stub (Test Stub) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
6.4.5 Objeto Falsicado (Fake Object) . . . . . . . . . . . . . . . . . . . . . . . . . . 87
6.4.6 Objeto Emulado (Mock Object) . . . . . . . . . . . . . . . . . . . . . . . . . . 89
6.4.7 Objeto Espio (Test Spy) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
6.4.8 Objeto Prottipo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
6.4.9 Teste por Comparao de Algoritmos . . . . . . . . . . . . . . . . . . . . . . . 98
6.4.10 Teste por Probabilidade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
6.4.11 Vericar Inversibilidade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
6.4.12 Vericar Valores Limites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
6.5 Antipadres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
6.5.1 Gancho para os Testes (Test Hook) . . . . . . . . . . . . . . . . . . . . . . . . . 111
6.5.2 Testes Encadeados (Chained Tests) . . . . . . . . . . . . . . . . . . . . . . . . 112
x
7 Testes com Persistncia de Dados 113
7.1 Banco de Dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
7.1.1 Congurao do Ambiente de Teste . . . . . . . . . . . . . . . . . . . . . . . . 114
7.2 Padres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
7.2.1 Uma Instncia de Banco de Dados por Linha de Execuo . . . . . . . . . . . . 118
7.2.2 Gerao Dinmica de Dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
8 Testes de Interface de Usurio 123
8.1 Princpios Bsicos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
8.2 Testes que Simulam Usurios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
8.2.1 Gravadores de Interao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
8.3 Desempenho dos Testes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
8.4 Padres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
8.4.1 Tela como Unidade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
8.4.2 Estado Inicial da Tela . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
8.4.3 Camada de Abstrao de Funcionalidades . . . . . . . . . . . . . . . . . . . . . 137
8.4.4 Fotograa da Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
8.4.5 Localizar Elemento por ID . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
8.4.6 Localizar Elemento por Tipo do Componente . . . . . . . . . . . . . . . . . . . 146
8.4.7 Localizar Clula de Tabela pelo Cabealho e Contedo . . . . . . . . . . . . . . 147
8.5 Antipadres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
8.5.1 Navegao Encadeada . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
8.5.2 Localizar Componente pelo Leiaute . . . . . . . . . . . . . . . . . . . . . . . . 149
8.5.3 Vericaes Rgidas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
8.6 Concluses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
9 Tcnicas de Desenvolvimento de Software com Testes Automatizados 151
9.1 Testes Aps a Implementao (TAD) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
9.2 Testes a Priori (TFD) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
9.3 Desenvolvimento Dirigido por Testes (TDD) . . . . . . . . . . . . . . . . . . . . . . . . 155
9.4 Desenvolvimento Dirigido por Comportamento (BDD) . . . . . . . . . . . . . . . . . . 156
9.5 Concluses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
III Gerenciamento de Testes Automatizados 161
10 Mtricas 163
10.1 Mtricas para Testes Automatizados . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
10.2 Cobertura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
10.3 Testabilidade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
10.3.1 Padres e Antipadres Inuenciam a Testabilidade . . . . . . . . . . . . . . . . 168
10.3.2 Quando Utilizar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
10.4 Outras mtricas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
10.5 Concluses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
11 Consideraes Finais 175
11.1 Pontos para Pesquisa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
Apndices 181
A Teste de Carga com JMeter 181
xi
B Biblioteca CUnit 187
xii
Lista de Figuras
1.1 Pesquisa AgilCoop - Cidades onde foram realizadas as entrevistas. . . . . . . . . . . . . 5
1.2 Pesquisa AgilCoop - Informaes das empresas participantes. . . . . . . . . . . . . . . . 5
1.3 Pesquisa AgilCoop - Tabela de cursos oferecidos. . . . . . . . . . . . . . . . . . . . . . 6
1.4 Pesquisa AgilCoop - Interesse das empresas pelos cursos. . . . . . . . . . . . . . . . . . 6
1.5 Interseco de reas de estudos - alguns dos principais autores. . . . . . . . . . . . . . . 8
2.1 Popularidade de Navegadores Web em novembro de 2009 (Fonte: W3Counter). . . . . . 19
2.2 Popularidade de Sistemas Operacionais em novembro de 2009 (Fonte: W3Counter). . . . 20
2.3 Indicao normalizada de popularidade de linguagens de programao no comeo de
2011. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.4 Outra indicao de popularidade de linguagens de programao: 2008 e 2009. . . . . . . 21
3.1 Exemplo de teste de unidade. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
3.2 Exemplo de teste de interface Web com Java. . . . . . . . . . . . . . . . . . . . . . . . 30
3.3 Exemplo de teste de leiaute Web com Java. . . . . . . . . . . . . . . . . . . . . . . . . 31
3.4 Exemplo de teste aleatrio. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
3.5 Exemplo de teste de fumaa. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
3.6 Exemplo de teste de sanidade. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
3.7 Exemplo de converso do teste aleatrio para teste de sanidade. . . . . . . . . . . . . . . 37
3.8 Tipos de testes de software. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
6.1 Denindo mtodos de teste com JUnit 3.5. . . . . . . . . . . . . . . . . . . . . . . . . . 61
6.2 Denindo mtodos de teste com JUnit 4 ou superior. . . . . . . . . . . . . . . . . . . . 61
6.3 Exemplos de vericaes com JUnit e Hamcrest. . . . . . . . . . . . . . . . . . . . . . 63
6.4 Exemplo de Teste em Java com JUnit e Hamcrest. . . . . . . . . . . . . . . . . . . . . . 64
6.5 Mtodos de set up e tear down do arcabouo TestNG para Java. . . . . . . . . . . . . . . 65
6.6 Exemplo tpico de uso dos mtodos set up e tear down. . . . . . . . . . . . . . . . . . . 66
6.7 Tipos de Objetos Dubls. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
6.8 Objeto Compra com implementao acoplada ao objeto Desconto. . . . . . . . . . . . . 76
6.9 Teste complicado do objeto Compra. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
6.10 Objeto Compra com implementao mais organizada, mas ainda acoplada ao objeto
Desconto. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
6.11 Objeto Compra desacoplado de suas dependncias. . . . . . . . . . . . . . . . . . . . . 79
6.12 Teste do objeto Compra refatorado. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
6.13 Exemplo de funcionalidade com muitas responsabilidades. . . . . . . . . . . . . . . . . 82
6.14 Funcionalidade de busca de pessoas refatorada, utilizando um Objeto Humilde. . . . . . 82
6.15 Exemplo de Objeto Tolo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
6.16 Uma classe python com mtodos abstratos. . . . . . . . . . . . . . . . . . . . . . . . . 91
6.17 Exemplo de teste com Objeto Espio. . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
6.18 Exemplo de teste de Objeto Espio com Python-Mockito. . . . . . . . . . . . . . . . . . 93
xiii
6.19 Objeto Prottipo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
6.20 Exemplo emPython de testes da biblioteca Django-Dynamic-Fixture utilizando o padro
Objeto Prottipo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
6.21 Algoritmo eciente para clculo do M.D.C. entre dois nmeros inteiros. . . . . . . . . . 99
6.22 Exemplo de Teste por Comparao de Algoritmos. . . . . . . . . . . . . . . . . . . . . 99
6.23 Exemplo de teste que verica a correo de um teste pela probabilidade. . . . . . . . . . 101
6.24 Exemplo de teste que verica a correo de um teste pela probabilidade. . . . . . . . . . 102
6.25 Algoritmo ingnuo de criptografar and descriptografar textos. . . . . . . . . . . . . . . . 104
6.26 Teste de inversibilidade dos algoritmos de criptograa e descriptograa. . . . . . . . . . 105
6.27 Assero de Inversibilidade da ferramenta Python-QAssertions. . . . . . . . . . . . . . . 105
6.28 Funo escrita em C que calcula a multiplicao de matrizes. . . . . . . . . . . . . . . . 106
6.29 Teste da multiplicao de matrizes usando a biblioteca CUnit. . . . . . . . . . . . . . . 107
6.30 Teste escrito em Scala dos valores limites das regras do Poker. . . . . . . . . . . . . . . 108
6.31 Exemplo de vericao de validao com casos limites com gerao de casos de teste. . 109
6.32 Exemplo de vericao de validao com casos limites sem gerao dos casos de teste. . 110
6.33 Exemplo de vericao de validao com casos limites para diversos parmetros. . . . . 110
6.34 Antipadro Gancho para os Testes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
6.35 Um exemplo de esqueleto de cdigo Java do antipadro Testes Encadeados. . . . . . . . 112
7.1 Exemplo de dados estticos em um arquivo no formato YAML. . . . . . . . . . . . . . . 119
7.2 Exemplo em Python de classe de gerao dinmica de um objeto de dados especco. . . 121
7.3 Exemplo do padro de Gerao Dinmica de Dados com a biblioteca genrica de objetos
de dados Django Dynamic Fixture. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
8.1 Diagrama simplicado do padro MVC. As linhas slidas indicam associaes diretas
enquanto as tracejadas representam associaes indiretas. . . . . . . . . . . . . . . . . . 124
8.2 Exemplo de teste de interface Web com HtmlUnit. . . . . . . . . . . . . . . . . . . . . . 127
8.3 Tela de conguraes a ser testada. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
8.4 Tela principal do sistema que contm links e atalhos de teclado para abrir a tela de
conguraes a ser testada. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
8.5 Exemplo de teste com a ferramenta Fest de uma tela sem o padro Tela como Unidade. . 132
8.6 Refatorao do exemplo da Figura 8.5 para utilizar o padro Tela como Unidade. . . . . 132
8.7 Exemplo de teste de uma pgina Web de autenticao sem o padro Tela como Unidade. 133
8.8 Refatorao do exemplo da Figura 8.7 para utilizar o padro Tela como Unidade. . . . . 133
8.9 Exemplo de organizao sem o padro Estado Inicial da Tela. . . . . . . . . . . . . . . . 135
8.10 Exemplo de organizao com o padro Estado Inicial da Tela. . . . . . . . . . . . . . . 135
8.11 Organizao recomendada de testes de interface de usurio. . . . . . . . . . . . . . . . . 137
8.12 Exemplo de testes de uma pgina Web de autenticao sem utilizar o padro Camada
de Abstrao de Funcionalidades. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
8.13 Refatorao do exemplo da Figura 8.12. Essa classe faz parte da Camada de Abstrao
de Funcionalidades. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
8.14 Continuao da refatorao do exemplo da Figura 8.12. Camada que contm as veri-
caes utilizando a Camada de Abstrao de Funcionalidades. . . . . . . . . . . . . . 140
8.15 Acares sintticos para melhorar ainda mais a legibilidade dos testes. . . . . . . . . . . 140
8.16 Aspecto fornecido pela biblioteca Util4Selenium para bater fotograas da interface. . . . 143
8.17 Classe base que ativa o padro Fotograa da Interface. . . . . . . . . . . . . . . . . . . 144
8.18 Exemplo de classe de teste que utiliza a classe base SeleniumTestCase. . . . . . . . . . 144
8.19 Exemplo de localizao de um elemento por ID com WebDriver e HTMLUnit. . . . . . 145
8.20 Exemplo de localizao de um elemento pelo tipo com WebDriver e HTMLUnit. . . . . 146
8.21 Busca da clula de uma tabela pelo leiaute. . . . . . . . . . . . . . . . . . . . . . . . . 147
xiv
8.22 Exemplo de Localizar Clula pelo Cabealho e Contedo com o HTMLUnit. . . . . . . 148
9.1 Fluxo do TAD. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
9.2 Fluxo do TFD. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
9.3 Ciclo de TDD. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
9.4 Esqueleto de histria sugerido por BDD. . . . . . . . . . . . . . . . . . . . . . . . . . . 157
9.5 Exemplo de histria no formato sugerido por BDD. . . . . . . . . . . . . . . . . . . . . 157
9.6 Esqueleto de histria sugerido por BDD. . . . . . . . . . . . . . . . . . . . . . . . . . . 158
9.7 Exemplo de histria no formato sugerido por BDD. . . . . . . . . . . . . . . . . . . . . 158
9.8 Ciclo de ATDD. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
10.1 Exemplo de cdigo para vericao da cobertura. . . . . . . . . . . . . . . . . . . . . . 165
10.2 Exemplo de testes para vericao da cobertura. . . . . . . . . . . . . . . . . . . . . . . 165
10.3 Visualizao da cobertura do cdigo-fonte com a ferramenta Eclemma. . . . . . . . . . 166
10.4 Grau de testabilidade do mdulo Workbench do software Eclipse, medido com a ferra-
menta Testability-Explorer. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
10.5 Exemplo de implementao de construtores que tornam os objetos difceis de serem
testados. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
10.6 Exemplo de implementao de construtores que tornamos objetos fceis de seremtestados.170
10.7 Exemplo de implementao de mtodos que so difceis de serem testados. . . . . . . . 170
10.8 Exemplo de implementao de mtodos que so fceis de serem testados. . . . . . . . . 170
A.1 Conguraes do Plano de Teste com JMeter. . . . . . . . . . . . . . . . . . . . . . . . 181
A.2 Conguraes dos Usurios que sero simulados pelo JMeter. . . . . . . . . . . . . . . 182
A.3 Conguraes padres do servidor. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183
A.4 Requisio HTTP GET na pgina inicial do sistema em teste. . . . . . . . . . . . . . . . 183
A.5 Requisio HTTP POST para realizar uma busca no sistema. . . . . . . . . . . . . . . . 184
A.6 Um dos grcos que pode ser gerado pelo JMeter. . . . . . . . . . . . . . . . . . . . . . 185
B.1 Biblioteca CUnit. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188
xv
xvi
Parte I
Introduo e Conceitos
1
Captulo 1
Introduo
Garantir a qualidade de sistemas de software um grande desao devido alta complexidade dos pro-
dutos e s inmeras diculdades relacionadas ao processo de desenvolvimento, que envolve questes
humanas, tcnicas, burocrticas, de negcio e polticas. A falta de qualidade nos sistemas de software
causa grandes prejuzos economia mundial [107] e j foi responsvel por grandes tragdias que cus-
taram vidas humanas, mesmo com todo o esforo dedicado ao avano das tecnologias e das metodolo-
gias de desenvolvimento. Idealmente, os sistemas de software devem no s fazer corretamente o que
o cliente precisa, mas tambm faz-lo com segurana e ecincia. Ainda, para que os sistemas sejam
durveis, necessrio que ele sejam exveis e de fcil manuteno.
A nossa experincia [35, 36] mostra que, salvo honrosas excees, na indstria de software
brasileira, essas caractersticas so muitas vezes asseguradas atravs de testes manuais do sistema aps o
trmino de mdulos especcos ou at mesmo do sistema inteiro. Essa abordagem manual e em muitos
casos ad hoc leva ocorrncia de muitos problemas, tais como erros de regresso, logo ela deveria ser
evitada.
Esta dissertao se inspira na losoa dos Mtodos geis de Desenvolvimento de Software [38] e
em prticas recomendadas pela Programao eXtrema (XP) [17], com nfase em Testes Automatizados,
que uma tcnica voltada principalmente para a melhoria da qualidade dos sistemas de software. Ela
tambm se baseia fortemente na teoria de Testes de Software [95, 54] para aplicar as recomendaes dos
testes manuais na automao dos testes.
Alm da teoria dos testes automatizados, sero apresentados detalhes tcnicos com exemplos de
cdigo-fonte e discusses sobre estratgias de automao de testes. Esses tpicos esto distribudos em
trs partes: I - Introduo e Conceitos, II - Prticas, Padres e Tcnicas para Testes de Correo e III -
Gerenciamento de Testes Automatizados.
Aprimeira parte traz discusses sobre testes automatizados e seus benefcios comparados comoutras
prticas de controle e garantia de qualidade, como anlises formais e testes manuais. So apresentados
argumentos para apoiar nossa tese de que testes automatizados uma prtica de desenvolvimento ecaz
e de baixo custo que ajuda a aumentar a qualidade dos sistemas de software.
A segunda parte da dissertao destaca os principais padres e antipadres que tornam os testes
automatizados bons e ruins, respectivamente. Ela possui um captulo introdutrio que discute o que
um teste de correo de qualidade e tambm captulos especializados em testes de unidade, interface de
usurio e persistncia de dados. O captulo de testes de unidade envolve discusses sobre como fazer
testes em sistemas programados com reexo, programao orientada a objetos e orientada a aspectos.
Na Parte III existem informaes para ajudar equipes e gerentes a gerenciar a produtividade da
criao e manuteno dos testes automatizados assim como a qualidade do produto nal. Um dos
captulos apresenta as principais mtricas de acompanhamento para testes automatizados, abordando
estratgias de acompanhar o progresso dos testes em diferentes tipos de projetos.
Depois da discusso de todos esses tpicos, o leitor ter adquirido os conhecimentos fundamentais
3
de mtodos geis e testes de software assim como um vasto conhecimento sobre a automao de testes
para favorecer a escrita e manuteno produtiva de testes automatizados de qualidade. Tudo isso para
alcanar com xito o objetivo principal do desenvolvimento de software que a criao de programas e
sistemas de qualidade que atendam as necessidades da sociedade.
1.1 Objetivos
Este trabalho tem como objetivo principal ser um guia para estudo, criao e manuteno de testes
automatizados de qualidade. A automao de testes uma prtica gil, ecaz e de baixo custo para mel-
horar a qualidade dos sistemas de software, mas necessrio conhecimento, organizao e experincia
para evitar que antipadres ou falhas no gerenciamento reduzam o custo-benefcio dessa prtica para o
desenvolvimento de software.
A primeira parte da dissertao, Introduo e Conceitos, tem como objetivo introduzir o tema e
denir os principais conceitos de testes automatizados, assim como relacionar essa prtica a outras
reas de estudo como mtodos geis, testes de software, controle de qualidade e software livre. Testes
automatizados englobam conceitos de diversas comunidades de desenvolvedores e testadores, por isso a
importncia de identicar os aspectos mais pertinentes de cada grupo de estudo.
J a segunda parte, Prticas, Padres e Tcnicas para Testes de Correo, tem como objetivo re-
unir os aspectos mais importantes para o desenvolvimento e manuteno de bons testes automatizados
que veriquem a correo dos sistemas de software. So detalhadas diferentes situaes que exigem
cuidados durante a escrita dos testes e tambm so apresentadas solues para problemas rotineiros.
A parte Gerenciamento de Testes Automatizados tem como objetivo discutir a realizao da prtica
de testes automatizados durante o processo de desenvolvimento para proporcionar a melhoria da quali-
dade do produto nal. Desenvolvedores e gerentes podem seguir vrias abordagens para administrar os
testes automatizados dependendo do tipo de projeto.
Contudo, este trabalho no pretende ensinar ou detalhar ferramentas e arcabouos de testes autom-
atizados, pois isso tornaria o texto obsoleto em curto espao de tempo. Tambm no objetivo deste
trabalho comparar matematicamente ou atravs de experimentos controlados, testes automatizados com
mtodos formais e matemticos, apesar de ser um estudo de grande interesse para trabalhos futuros.
1.2 Motivao
A qualidade de um sistema de software pode ser denida por diversos aspectos como sugere o padro
ISO 9126
1
e a literatura de qualidade de software [126, 45, 115], sendo que a mais bsica e importante
a correo. Segundo o Instituto de Padres e Tecnologias dos Estatos Unidos (National Institute of
Standards and Technology, NIST), erros de software causaram em 2002 prejuzos de aproximadamente
59,5 bilhes de dlares economia dos Estados Unidos [107]. Logo, podemos concluir que algo precisa
ser melhorado no desenvolvimento de software, incluindo ferramentas, processos e capacitao dos
desenvolvedores.
O processo predominante de desenvolvimento de software na indstria se baseia nos mtodos de
desenvolvimento derivados do modelo em cascata [118], que valorizam a busca por qualidade em fases
bem denidas e no m do processo de desenvolvimento. Esse modelo contraria a nova tendncia de
controlar a qualidade do software baseada na preveno de erros [37]. Essa propeno j havia sido
prevista em 1979 por Glenford J. Myers [105], quando escreveu o primeiro livro da rea de testes de
software, e foi comprovada por diversos casos de sucesso [6].
Aautomao de testes uma prtica til para prevenir erros durante a implementao e a manuteno
do sistema. Testes a priori e Desenvolvimento Dirigido por Testes (vide Seo 3.2) tambm so forte-
1
ISO 9126 uma norma para qualidade de software.
4
mente baseados na preveno de erros j que os testes so criados antes mesmo da prpria implemen-
tao do sistema, proporcionando uma alta cobertura de vericao.
No entanto, implementar e manter grandes e completas baterias de testes automatizados uma tarefa
complexa e sujeita a erros, por isso necessrio conhecimento e experincia para que elas sejam bem
escritas para garantir de maneira efetiva a qualidade do sistema e baratear o desenvolvimento.
O tema Automao de Testes ainda recente no Brasil e de muito interesse por parte das empre-
sas nacionais. Em 2007 a cooperativa de desenvolvimento gil AgilCoop
2
realizou uma pesquisa na
regio sudeste (Figura 1.1) em empresas de diversos tamanhos e tempo de mercado (Figura 1.2) para
compreender o interesse das empresas pelos mtodos geis.
Figura 1.1: Pesquisa AgilCoop - Cidades onde foram realizadas as entrevistas.
Figura 1.2: Pesquisa AgilCoop - Informaes das empresas participantes.
Nesta pesquisa, a AgilCoop realizava um questionrio oferecendo diversos cursos relacionados a
mtodos geis (Figura 1.3). A m de obter uma ordenao dos cursos mais relevantes, foram feitas
diversas anlises estatsticas sobre as informaes coletadas. Por m, os critrios adotados foram o
interesse pelo curso e seu nmero esperado de alunos, representados pelos eixos Interesse Mdio e
Nmero de Alunos da Figura 1.4, respectivamente. O resultado indicou, com um bom destaque, que
o maior interesse das empresas era obter maior conhecimento sobre testes automatizados, representado
pelo item 7 do grco.
Esta dissertao tem potencial para ajudar a sanar parte das diculdades encontradas na automao
de testes e, dessa maneira, tornar-se uma contribuio til, tanto para novas pesquisas sobre o tema
2
agilcoop.org.br
5
Figura 1.3: Pesquisa AgilCoop - Tabela de cursos oferecidos.
Figura 1.4: Pesquisa AgilCoop - Interesse das empresas pelos cursos.
6
quanto para a rea empresarial. Ela utiliza como base os princpios das Metodologias geis e reune
alguns dos principais conceitos da rea de Teste de Software, seja atravs de discusses ou da adaptao
de alguns conceitos na forma de padres. Alm disso, so sugeridas novas solues para problemas
recorrentes que ainda no foram bem documentadas ou que foram pouco exploradas.
1.3 A quem se destina
A leitura desta dissertao indicada principalmente para programadores, mas tambm pode ser til
para analistas de qualidade e gerentes de projetos. Ela aborda desde temas tcnicos de computao at
tpicos de engenharia de software.
Os programadores vo conhecer a rea Teste de Software e suas principais tcnicas que ajudam a
melhorar a qualidade do sistema. Tambm iro encontrar as recomendaes bsicas sobre a automao
de testes e solues que ajudam a aperfeioar a escrita dos Testes Automatizados de Correo, seja
atravs do uso de padres e ou de outras tcnicas.
Para os programadores, todos os captulos do trabalho podem ser teis. Especialmente para os
pouco experientes em Testes Automatizados, fundamental a leitura dos Captulo 3 para facilitar o
entendimento da dissertao e para ajudar no estudo de trabalho de outos autores, sejam artigos cient-
cos, livros ou mesmo Internet. O Captulo 4 tambm interessante, pois apresenta uma viso geral do
processo de automao de testes.
Caso o programador j tenha experincia comTestes Automatizados, ele pode estudar primeiramente
os captulos da Parte II, de acordo com suas necessidades. Ainda, o Captulo 10 da Parte III possui
discusses avanadas sobre implementao do cdigo-fonte dos sistemas e dos testes.
J os analistas de qualidade podero conhecer novas tcnicas de Testes de Software, alm de con-
hecimentos bsicos e avanados de Testes Automatizados. A Parte I fundamental, principalmente
devido s comparaes feitas com os testes manuais no Captulo 2 e s denies da terminologia uti-
lizada pela dissertao no Captulo 3.
A Parte II tambm interessante de ser estudada por esses prossionais, em particular, os padres
do tipo Qualidade e o Captulo 9, que explora tcnicas de desenvolvimento com testes automatizados
e que possui discusses sobre a interao da equipe de desenvolvimento com clientes e requisitos. A
Parte III tambm possui discusses sobre Qualidade de Software, em especial, mtricas interessantes de
serem coletadas em sistemas que possuem testes automatizados.
Por m, os gerentes de projetos, alm de aumentar seus conhecimentos sobre testes automatizados
e mtodos geis, conhecero tcnicas de desenvolvimento que so recomendadas para analistas de qual-
idade e desenvolvedores. Ainda, iro se defrontar com recomendaes referentes ao gerenciamento de
software com automao de testes. Resumidamente, as Partes I e III so as mais interessantes para esses
leitores, pois so mais abrangentes e menos tcnicas.
1.4 Trabalhos Relacionados
A prtica de automao de testes surgiu da integrao de conceitos das reas de orientao a objetos,
testes de software e mtodos geis de desenvolvimento [13, 16]. Por isso, todo o conhecimento destas
reas pertinente e ajuda para um melhor aproveitamento do texto. A Figura 1.5 apresenta alguns dos
principais autores de cada grupo de pesquisa para referncia.
Testes Automatizados uma tcnica disseminada principalmente pela comunidade de mtodos
geis, por isso, conhecimento dos princpios geis ou de algum mtodo gil especco pode melho-
rar o aproveitamento da leitura deste trabalho. Dissertaes anteriores em nosso grupo de pesquisa
apresentam reexes [46] e experincias [57] sobre o assunto, alm de outros trabalhos que abordam
prticas pontuais, como mtricas de software para acompanhamento da evoluo de projetos [128]. Em
7
Figura 1.5: Interseco de reas de estudos - alguns dos principais autores.
relao ao tema especco do trabalho, existem teses [53, 141] e livros [95, 99] que servem de referncia
e complementam o conhecimento de automao de testes.
8
Captulo 2
Testes Automatizados
Testes automatizados (em oposio aos testes manuais) a prtica de tornar os testes de software inde-
pendentes de interveno humana. Testar uma prtica intrnseca ao desenvolvimento de sistemas, mas
testes de software s comearam a se tornar uma rea de estudo da engenharia de software na dcada de
1970 e, desde ento, tm ganho cada vez mais importncia.
Hoje, existem grandes comunidades de prossionais especializados, conhecidos como testadores ou
analistas de qualidade, e diversos estudos e cursos com nfase nessa prtica. Muitas empresas possuem
grandes setores dedicados exclusivamente ao controle e garantia de qualidade.
Assim como os testes manuais, os testes automatizados tm como objetivo melhorar a qualidade
de sistemas atravs da vericao e validao, mas a automao dos testes expande a rea de estudo
de testes de software e muda os paradigmas de implementao, manuteno e execuo dos testes.
Contudo, todo o conhecimento de testes de software pode ser aproveitado para automao.
A efetiva automao requer o uso de ferramentas especcas e de linguagens de programao de alto
nvel, portanto, necessrio um slido conhecimento de cincia da computao para a criao de testes
de qualidade. Como veremos no Captulo 9, existem tcnicas de escrita de testes automatizados que
mudam completamente a maneira que programadores implementam um software.
Os testes automatizados tambm podem ser aproveitados para outros ns. Por exemplo, possvel
utiliz-los para conhecer os efeitos colaterais de ferramentas e arcabouos. J os testes de interface de
usurio e de aceitao podem ser utilizados para demonstraes do software ou mesmo como um manual
do usurio.
Ainda, relatrios gerados a partir dos casos de testes podem ser utilizados como documentao dos
requisitos e do sistema. Esse tipo de documentao dinmica, pois pode ser gerada automaticamente
e sem esforo, sempre que as baterias de testes forem executadas. Um benefcio desse tipo de docu-
mentao que ela dicilmente se torna obsoleta, j que ela se autoverica toda vez que os testes so
executados, isto , se algum teste falhar, o relatrio indica que aquele requisito no mais satisfeito.
2.1 Cenrio de Desenvolvimento com Testes Manuais
O modo convencional de desenvolvimento de uma funcionalidade estudar o problema, pensar em uma
soluo e, em seguida, implement-la. Aps esses trs passos, o desenvolvedor faz testes manuais para
vericar se est tudo funcionando como o esperado. normal que erros sejam detectados ao longo do
processo de desenvolvimento; os desenvolvedores precisam encontrar o erro com tcnicas de depurao
e, ento, corrigir e refazer o conjunto de testes manuais. Este ciclo se repete at que os desenvolvedores
sintam-se seguros com o cdigo-fonte produzido ou, em situaes desastrosas, at que o prazo termine.
Com o objetivo de identicar possveis erros remanescentes, tambm comum submeter o software
a uma avaliao de qualidade aps o trmino do desenvolvimento e antes de coloc-lo emproduo. Esse
9
controle de qualidade a posteriori geralmente realizado com o auxlio de testes manuais executados
por desenvolvedores, usurios ou mesmo por equipes especializadas em teste de software.
Este cenrio comum principalmente em empresas que utilizam metodologias rgidas que pos-
suem fases bem denidas, geralmente derivadas do modelo de cascata [123]. Esse tipo de metodologia
frequentemente leva apario de diversos problemas recorrentes na indstria de software, tais como
atrasos nas entregas, criao de produtos com grande quantidade de erros e diculdade de manuteno
e evoluo, devido principalmente s limitaes da realizao dos testes manuais.
A execuo manual de um caso de teste rpida e efetiva, mas a execuo e repetio manual de um
vasto conjunto de testes uma tarefa dispendiosa e cansativa. comume compreensivo que os testadores
priorizem os casos de testes mais crticos e no veriquem novamente todos os casos a cada mudana
signicativa do cdigo; desse cenrio que surgem diversos erros de software. Erros de software podem
trazer grandes prejuzos para as equipes de desenvolvimento que perdem muito tempo para identicar e
corrigir os erros e tambm para o cliente que, entre outros problemas, sofre com constantes atrasos nos
prazos combinados e com a entrega de software de qualidade comprometida.
Mas o aspecto mais crtico deste cenrio o efeito bola de neve. Como necessrio muito esforo
para executar todo o conjunto de testes manuais, dicilmente a bateria inteira de testes executada
novamente a cada correo de um erro, como seria desejvel. Muitas vezes, a correo de uma falha
pode adicionar erros de regresso que so defeitos adicionados em mdulos do sistema que estavam
funcionando corretamente mas que foram danicados por alguma manuteno desastrada. A tendncia
esse ciclo se repetir at que a manuteno do sistema se torne uma tarefa to custosa que passa a valer
a pena reconstru-lo completamente.
2.2 A Abordagem dos Testes Automatizados
Muitos mtodos geis (vide Seo 2.4), como Lean [112], Scrum [131] e XP [17] recomendam que todas
as pessoas envolvidas em um projeto trabalhem controlando a qualidade do produto todos os dias e a
todo momento, pois baseiam-se na ideia de que prevenir defeitos mais fcil e barato que identic-los
e corrigi-los a posteriori. A Programao eXtrema (XP), em particular, recomenda explicitamente testes
automatizados para ajudar a garantir a qualidade dos sistemas desenvolvidos.
Testes automatizados so programas ou scripts simples que exercitam funcionalidades do sistema
em teste e fazem vericaes automticas nos efeitos colaterais obtidos [56]. A independncia da in-
terveno humana permite o aproveitamento dos benefcios de um computador, como a velocidade de
execuo, reprodutibilidade exata de um conjunto de aes, possibilidade de execuo paralela de testes,
exibilidade na quantidade e momento das execues dos testes e a facilidade da criao de casos com-
plexos de testes.
Uma das grandes vantagens dessa abordagem que os casos de teste podem ser facilmente e rapi-
damente repetidos a qualquer momento e com pouco esforo. Os testes podem ser executados paralela-
mente
1
, por exemplo atravs de grades computacionais
2
. A reprodutibilidade dos testes permite simular
identicamente e inmeras vezes situaes especcas, garantindo que passos importantes no sero ig-
norados por falha humana e facilitando a identicao de um possvel comportamento no desejado.
Alm disso, como os casos para vericao so descritos atravs de um cdigo interpretado por um
computador, possvel criar situaes de testes bem mais elaboradas e complexas do que as realizadas
manualmente, possibilitando qualquer combinao de comandos e operaes. Ainda, a magnitude dos
testes pode tambm facilmente ser alterada. Por exemplo, relativamente fcil simular centenas de
usurios acessando um sistema ou inserir milhares de registros em uma base de dados, o que no
factvel com testes manuais.
1
Muitos arcabouos j facilitam a criao de testes paralelos, tais como Parallel-Junit, JUnit verses superiores a 4.6 e
TestNG.
2
A ferramenta SeleniumGrid cria uma grade computacional para execuo de testes escritos com a ferramenta Selenium.
10
Todas essas caractersticas ajudam a solucionar os problemas encontrados nos testes manuais, con-
tribuindo para diminuir a quantidade de erros [147] e aumentar a qualidade do software [43]. Como
relativamente fcil executar todos os testes a qualquer momento, mudanas no sistema podem ser feitas
com segurana, o que ajuda a aumentar a vida til do produto.
Na maioria das vezes, os testes automatizados so escritos programaticamente, por isso necessrio
conhecimento bsico de programao, mas existem tambm diversas ferramentas grcas que escondem
os detalhes de implementao possibilitando que clientes e outros prossionais que no sejam desen-
volvedores tambm consigam escrever seus prprios testes. Ainda existem as ferramentas que separam a
descrio do cenrio de teste da sua implementao. Dessa forma, os clientes podem descrever os testes
enquanto os desenvolvedores implementam trechos de cdigo que ligam a especicao do cliente ao
sistema em teste.
2.3 Histria
A ideia de testar manualmente sempre existiu, desde a poca dos cartes perfurados at a do software de
milhes de linhas de cdigo, pois uma prtica comum e trivial de vericar algo que precise ser posto
prova. Segundo Craig Larman e Victor L. Basili, nos anos de 1960, a Agncia Espacial Americana
(NASA) utilizou prticas de desenvolvimento dirigido por testes (Seo 9.3) nos cartes perfurados do
Projeto Espacial Mercrio [84].
Testar uma prtica intrnseca ao desenvolvimento e antiga a necessidade de criar scripts ou
programas para testar cenrios especcos [54], principalmente para os cenrios nos quais testar man-
ualmente era invivel. No entanto, utilizar testes automatizados como uma premissa bsica do desen-
volvimento um fenmeno relativamente recente, com incio em meados da dcada de 1990 [132].
Algumas prticas de desenvolvimento j evidenciavam a necessidade da criao de scripts de teste, tais
como trechos de cdigo utilizados para imprimir valores de variveis (depurao com comandos print)
e mtodos main espalhados em trechos internos do cdigo-fonte para fazer execues pontuais do pro-
grama.
Contudo, o termo teste de software comeou a se tornar um jargo na computao aps o lanamento
do livro The Art of Software Testing, de Glenford J. Myers [105, 120] e publicado em 1979. J em 1988,
David Gelperin e Bill Hetzel escreveramo artigo The Growth of Software Testing [62] onde classicavam
a histria do teste de software e previam sua tendncia para o futuro.
Como foi discutido no artigo The Growth of Software Testing, at 1956 o desenvolvimento de soft-
ware era orientado para depurao, isto , fazia-se o software e, quando encontrado um erro, era feita
sua busca e correo. J entre 1957 e 1978, o desenvolvimento era orientado para demonstrao, onde
havia uma camada adicional no desenvolvimento para vericao dos erros. Entre 1979 e 1982, era
orientado para destruio, onde havia uma preocupao em provar que o software estava correto atravs
de muitos testes que procuravam encontrar erros no sistema, i.e., destru-lo. Depois de 1983 at 1987,
orientado para avaliao, onde havia uma tentativa de encontrar os erros o mais cedo possvel, para evi-
tar depurao. Aps 1988, os autores sugeriram que o desenvolvimento de software seria orientado para
preveno, o que foi concretizado com a popularizao dos testes automatizados, com as recomendaes
dos mtodos geis e com o desenvolvimento dirigido por testes [33].
Os testes automatizados disseminaram-se atravs de ferramentas especializadas, que facilitam a es-
crita, manuteno e execuo dos testes. Essas ferramentas permitem separar o cdigo-fonte dos testes
e do sistema, evitando que os casos de testes interram no comportamento do sistema. O primeiro ar-
cabouo conhecido o Taligent Test Framework criado por Alan Liu e David McCusker em 1991 e
publicado em 1995 [132], mas que no se popularizou. Por volta de 1994, Kent Beck criou o arcabouo
SUnit para linguagem SmallTalk [13], que at hoje utilizado como referncia para arcabouos semel-
hantes para outras linguagens de programao.
11
O SUnit era to simples que Kent Beck no imaginava que ele teria algum valor, mas ao utiliz-
lo para testar algumas estruturas de dados de um sistema em que trabalhava, ele acabou encontrando
um nmero considervel de defeitos. A partir desse caso de sucesso, a prtica de testes automatizados
disseminou-se entre diversas comunidades. Em 1998, Kent Beck e Erich Gamma desenvolveram o
arcabouo JUnit para a linguagem Java, inspirado no SUnit, e foi ento que os testes automatizados
comearam a se tornar uma prtica altamente disseminada nas boas equipes de desenvolvimento de
software em todo o mundo. Em 2002, Kent Beck lanou o livro Test-Driven Development: By Example
[16], que prope um novo paradigma de desenvolvimento, onde a implementao do software guiada
pela criao de casos de testes automatizados.
Atualmente, a automao de testes considerada por diversas metodologias, principalmente entre
aquelas identicadas com os mtodos geis, como uma prtica bsica para garantir a qualidade de um
software. Muito se tem estudado, novos conceitos e tcnicas de desenvolvimento foram criadas e as
ferramentas esto cada vez mais poderosas e prticas. Isso tudo facilita no apenas a escrita de testes
para trechos especcos de cdigo, mas tambm para a integrao de mdulos, interfaces grcas e
bancos de dados.
O retrato da importncia que se tem dado aos testes automatizados est nas implementaes de
muitas ferramentas de software populares que j trazem consigo mdulos para integrao e realiza-
o dos testes. Por exemplo, Maven que uma ferramenta para gerenciamentos de projetos, assim
como Ruby on Rails, Grails e Lift que so arcabouos para aplicaes Web, fornecem uma arquitetura
padronizada para a criao de casos de testes automatizados. A linguagem Python tambm incentiva
a automao dos testes, fornecendo em sua biblioteca padro um arcabouo para testes de unidade. A
linguagem Ruby possui o RSpec que integrado por diversos arcabouos para programao Web com
Ruby.
2.4 Mtodos geis de Desenvolvimento
A evoluo da engenharia de software deu-se a partir do modelo de cascata que propunha fases estanques
para o desenvolvimento de software [123]. Do aprimoramento do modelo de cascata surgiram novos
processos, tais como o modelo em espiral e o Rational Unified Process (RUP) [31], todos com
grande nfase na documentao do processo.
Devido grande quantidade de fracassos de projetos de software [66, 67, 65], nas ltimas dcadas
alguns lderes de projetos adotaram modos de trabalho que se opunham a este modelo tradicional, e
tiveram grandes sucessos [57]. At que em 2001, 17 desses lderes, que possuam formas de trabalho
semelhantes, juntaram-se para debater metodologias de desenvolvimento na tentativa de criar um novo
mtodo que agregasse as melhores ideias. No entanto, essa discusso levou concluso de que era
difcil denir um mtodo perfeito para todas as situaes; no entanto, chegou-se a um consenso de 12
princpios, que foram sintetizados nas premissas do Manifesto gil [18].
Dentre os mtodos geis que satisfazem o manifesto, existem os que focam em aspectos mais geren-
ciais, como Lean [109, 112] e Scrum [131], e outros que tambm do nfase a prticas de desenvolvi-
mento de software tal como a Programao eXtrema (XP) [17]. Todos preconizam o controle de quali-
dade disseminado por toda a equipe e durante todo o desenvolvimento.
O controle de qualidade no desenvolvimento com mtodos geis normalmente associado au-
tomao de testes, j que essa prtica surgiu da mesma comunidade. Automao de testes uma das
prticas primrias de XP [15]. As baterias de testes podem ser executadas sem esforo a todo momento,
o que possibilita a vericao contnua da qualidade do sistema durante e aps a implementao.
No entanto, a automao de testes no exclusiva dos mtodos geis e nem depende signica-
tivamente de outras prticas, por isso uma tcnica de desenvolvimento independente que pode ser
empregada por qualquer equipe utilizando qualquer metodologia, mesmo as mais tradicionais. Tambm
importante ressaltar que os mtodos geis no se opem a quaisquer revises adicionais que sejam
12
feitas para aumentar a qualidade, apenas no uma prtica primria da losoa.
2.4.1 Programao eXtrema
A Programao eXtrema, tambm conhecida como XP (de Extreme Programming), foi criada por Kent
Beck em 1996, o mesmo criador do arcabouo de testes SUnit [13], que serviu de referncia para
muitos outros arcabouos de testes automatizados. XP surgiu de um desao de reverter a situao de
um projeto de folha de pagamento da empresa Chrysler, que j havia estourado os limites de custos
e prazos. Para isso, o projeto adotou uma nova metodologia, que aplicava, ao extremo, um conjunto
de prticas recomendadas de programao [19, 6] com disciplina e organizao. Devido ao sucesso do
projeto, Kent Beck reuniu as prticas que trouxeram os mritos da metodologia e a ocializou como
Programao eXtrema, atravs do primeiro livro de XP [15].
Dentre as prticas recomendadas por XP temos os Testes Automatizados [44], que esto diretamente
relacionados a outras prticas da metodologia. Algumas das prticas de XP dependem fortemente dos
testes para que sejam executadas com sucesso. Por isso, para aplicar XP apropriadamente, fundamental
o emprego efetivo de testes automatizados. A seguir, descrevemos as principais prticas de XP que se
relacionam diretamente com testes automatizados.
Refatorao
Refatorao o processo de alterar um sistema de software para aperfeioar a estrutura interna do
cdigo-fonte sem alterar seu comportamento externo [59, 110]. Este processo, realizado atravs de
passos pequenos e sistematizados, um artifcio poderoso para aprimorar o design da aplicao e
melhorar a legibilidade e clareza do cdigo. Existem ferramentas que auxiliam na automatizao dessa
tarefa [14, 122, 79] e estudos de refatoraes em outras rea do projeto, tais como banco de dados [4].
No entanto, como toda manuteno de cdigo, refatorao tambm est sujeita a introduzir erros
no projeto, seja atravs do descuido ou do manuseio incorreto de ferramentas. Por isso, essencial
que exista uma boa bateria de testes automatizados que assegure que os comportamentos no foram
modicados indevidamente. Do ponto de vista do cliente, um erro introduzido em uma parte do sistema
que estava funcionando corretamente pode ser frustrante, por isso o uso de testes automatizados em
conjunto com a refatorao uma prtica fundamental.
Propriedade coletiva do cdigo
Propriedade coletiva do cdigo a prtica que prope que todos os membros da equipe so responsveis
de alguma maneira por todo o cdigo-fonte e, portanto, todos tm total liberdade para trabalhar em cima
do cdigo criado por outro membro. Essa prtica fundamental para no tornar um projeto dependente
de um programador especco, assim como ajuda na velocidade do desenvolvimento, dado que qualquer
trecho do cdigo pode ser modicado a qualquer momento, aumentando a disponibilidade de trabalho e
direcionando os esforos em algo que agrega valor diretamente ao produto nal.
No entanto, esta prtica traz riscos j que cada desenvolvedor possui ideias e maneiras prprias
de solucionar problemas de computao. O conito de solues pode desorganizar o cdigo-fonte e
estragar o que estava funcionando. Portanto, esta uma operao muito suscetvel a erros e merece
um controle de qualidade com alta cobertura de casos de testes que possam ser executados a qualquer
momento e de forma gil, como possvel com testes automatizados.
Design incremental
uma das prticas mais conitantes com as metodologias tradicionais, pois ela incentiva a no planejar
todo o esqueleto da aplicao de uma s vez, e sugere que o design seja construdo gradativamente de
13
acordo com o aprendizado da equipe e as necessidades prioritrias do cliente.
Entretanto, alteraes de design e de arquitetura no sistema podem ser muito perigosas j que po-
dem afetar diversos mdulos do sistema, ou seja, muitas classes podero ter de ser refatoradas. Essas
alteraes so ainda mais crticas quando utilizadas linguagens com tipagem dinmica, que no possuem
ajuda do compilador para vericao de tipos de variveis, pois as interfaces de muitas classes podem
ser alteradas, o que possibilita a insero de erros de integrao.
Por isso, a extrema importncia de testes que sejam abrangentes, como os testes automatizados de
integrao e aceitao. Tcnicas de escrita de testes, como Desenvolvimento Dirigido por Testes e por
Comportamento (vide Captulo 9), tambm inuenciam diretamente no design, dado que ele emerge
medida que novos casos de testes so adicionados.
Integrao Contnua
Integrao Contnua uma premissa do desenvolvimento incremental e das entregas frequentes ao
cliente. Ela tem como objetivo integrar rotineiramente o sistema e todas suas dependncias para ver-
icar que nenhuma modicao tenha danicado o sistema, sejam elas alteraes no cdigo-fonte, em
conguraes ou mesmo em dependncias e outros fatores externos [52].
Parte do processo de vericao feito pelo prprio compilador que verica erros estticos do
cdigo-fonte e de mapeamentos de dependncias. J os erros de lgica, de congurao e integrao de
componentes s podem ser vericados em tempo de execuo, por exemplo, atravs de testes autom-
atizados. Muitas ferramentas para automao de testes j possuem artifcios que facilitam a execuo
automtica dos casos de testes, o que facilita a congurao nos ambientes de integrao contnua.
Entregas Frequentes
O ciclo de entrega de verses para o cliente deve ser curto, assim a equipe foca seu tempo nas tarefas
mais prioritrias e o cliente consegue dar feedback rpido a respeito do software produzido. Segundo
as metodologias geis, dessa aproximao, entre cliente e equipe de desenvolvimento, que o software
evolui da melhor forma para atender s principais necessidades do cliente.
Entregas frequentes implicam alteraes rotineiras no cdigo do sistema, tornando o software alta-
mente vulnervel a erros de regresso, que um dos principais tipos de erro que os testes automatizados
ajudam a prevenir. Essas alteraes vo se tornando cada vez mais perigosas medida que o sistema
ca mais extenso e mais complexo, por isso fazer entregas frequentes s so interessantes quando h
segurana para fazer as modicaes.
Tracking
Acompanhamento do projeto ou tracking uma das atividades propostas em XP para ajudar a geren-
ciar o desenvolvimento do software. Esta atividade se d atravs da coleta, observao e interpretao
de mtricas (Captulo 10). As mtricas que sero coletadas e analisadas dependem do contexto atual
do sistema e das decises tomadas pela equipe, isto , a metodologia no possui regras ou mtricas
obrigatrias que devem ser monitoradas.
Entretanto, o acompanhamento da qualidade do produto nal natural em projetos srios que val-
orizam a criao de bons produtos. Todavia, qualidade um aspecto subjetivo, ento necessrio
utilizar diversas mtricas que consigam representar satisfatoriamente a qualidade do produto nal. Entre
uma innidade de aspectos que podem ser acompanhados, esto o design, elegncia e simplicidade do
cdigo-fonte, assim como as mtricas de testes automatizados. Como os testes inuenciam diretamente
na qualidade do produto nal, as mtricas so fundamentais para o acompanhamento e gerenciamento
da qualidade do projeto.
14
Metfora, Envolvimento real com o Cliente e Testes de Aceitao
A comunicao efetiva fundamental para o sucesso de um sistema de software, contudo ela no
trivial. Mesmo um texto sem ambiguidades pode ter interpretaes diferentes por seres humanos, j que
a discrepncia de conhecimento e de vocabulrio podem levar a mltiplas interpretaes. natural que
pessoas de comunidades especcas tenham um modo de falar e escrever peculiar, utilizando termos
prprios ou mesmo um vocabulrio formal que no rotineiro para outras comunidades.
por isso que XP incentiva um envolvimento real com o cliente, para que a equipe e os clientes
eliminem problemas de m interpretao e criem um vocabulrio prprio a partir de metforas que todos
consigam interpretar da mesma maneira. Uma forma de facilitar a criao de metforas atravs dos
testes de aceitao que criam uma ponte de comunicao entre cliente e desenvolvedores por meio de
documentos teis que ajudam a encontrar defeitos e a certicar que o sistema vlido, isto , faz o que
deveria ser feito.
Como foi descrito no decorrer de toda essa Seo, testes automatizados esto fortemente relacionado
com as principais prticas de mtodos geis. Para algumas delas, a escrita de testes automatizados um
pr-requisito, enquanto, para outras, a automao dos testes traz muitas vantagens.
2.5 Software Livre
Omovimento de Software Livre (tambmconhecido como Software Aberto ou Open Source) juntamente
com a Internet explicitou a natureza e o potencial das redes colaborativas [22, 23], que possibilitam
a criao de sistemas imensos como o GNU Linux
3
e com uma quantidade enorme de dados como
a Wikipedia
4
. Hoje existem diversas frentes de incentivo e de estudo de Software Livre
5
que visam
aumentar o uso de todo seu potencial, alm buscar formas de melhorias para as contribues e para o
gerenciamento dos projetos. O projeto QualiPSo
6
faz parte de uma dessas frentes, que possui, como um
de seus objetivos, estudar formas para aumentar a qualidade dos sistemas de software livre, como, por
exemplo, atravs de testes automatizados.
Para os criadores e mantenedores de projetos livres, o resultado esperado que o projeto tenha
uma boa repercusso e que tenha contribuies de qualidade. Para uma boa repercusso, a qualidade
do sistema essencial e pode ser conseguida mediante os testes automatizados ou de outra prtica que
est no controle e no domnio dos mantenedores. No entanto, as colaboraes nem sempre seguem
os mesmos padres de qualidade, elas podem ser muito heterogneas, no padronizadas e de pessoas
distantes e desconhecidas, o que pode dicultar e atrasar a comunicao. Dessa forma, cada contribuio
precisa de um estudo cuidadoso para certicar que ela est agregando algum valor ao sistema e no est
adicionando defeitos em outros mdulos do projeto.
Essa falta de agilidade na aceitao de contribuies e o medo que pode existir na incluso de cdigo
de colaboradores podemser melhorados ou mesmo sanados comajuda de testes automatizados. Os testes
documentam a quais situaes o sistema foi submetido e trazem segurana para modicaes do cdigo,
pois permitem avaliar se erros de regresso foram adicionados a qualquer momento.
Essa insegurana recproca para os colaboradores que tambm tm como objetivo obter boa
aceitao das suas contribuies, alm de querer que o projeto evolua da melhor maneira possvel. Alm
disso, se o colaborador evidencia aos mantenedores do projeto que sua contribuio de qualidade,
ento a chance dela ser includa no projeto aumenta. Por isso, importante que todas as contribuies
sejam acompanhadas de uma boa bateria de testes automatizados.
Por m, a prtica de testes automatizados traz benefcios para todas as pessoas envolvidas com
3
www.linux.org
4
wikipedia.org
5
ccsl.ime.usp.br
6
www.qualipso.org
15
o software livre. Os usurios que obtm um produto de melhor qualidade, alm de ganharem com a
velocidade e tornarem menos burocrtico o processo de melhorias do projeto.
2.6 Qualidade
O principal objetivo dos testes automatizados melhorar a qualidade do software, mas qualidade um
termo muito amplo, podendo indicar uma innidade de aspectos em um contexto especco, como,
por exemplo, desempenho, segurana, exibilidade, estruturao interna do cdigo, usabilidade, entre
outros [136, 148]. Apesar da qualidade ser um conceito elusivo e difcil de ser medido [48], os testes
automatizados podem contribuir para melhoria dos sistemas. Por isso, nas subsees seguintes, h
a descrio dos possveis elos entre determinada caracterstica de qualidade e testes automatizados.
Alguns dos aspectos citados esto na norma internacional ISO 9126, outros so termos rotineiros de
Engenharia de Software.
Correo
Correo a caracterstica de um software fazer corretamente o que foi proposto [77] e o aspecto
de qualidade mais bsico e fundamental de qualquer sistema de software. Alguns erros de correo so
supruos e nem chegam a incomodar os usurios, j outros so intolerveis, podendo tornar um sistema
inutilizvel e acabar com sua reputao.
Existem diversos tipos de testes que vericam a correo dos sistemas, tais como os testes de
unidade, integrao, interface e de aceitao, os quais sero descritos na Seo 3.3. Para criao destes
testes necessrio denir os dados de entrada de um mdulo do sistema e quais devem ser os dados de
sada desejados. Os resultados esperados so comparados com os resultados obtidos atravs da anlise
dos efeitos colaterais (valor de retorno, alterao do valor de variveis etc.) causados pela execuo
daquele mdulo com os dados de entrada correspondentes.
A correo dos sistemas depende de cada uma de suas unidades, assim como da integrao correta
das camadas e mdulos do sistema. As unidades podem ser compostas de algoritmos bem coesos, que
no dependem de outros mdulos para processar as informaes, ou de algoritmos que precisam de
objetos colaboradores para produzir um resultado coerente. Em outros casos, especialmente em classes
abstratas, podem existir trechos de cdigo que apenas denem parte da estrutura da soluo de um
problema. No entanto, possvel denir cenrios de testes que veriquem a correo dessas classes,
assim como pode ser vericado se a sua estrutura atende s necessidades.
Em outras situaes, os algoritmos podem ter muitas possibilidades de combinaes de dados de
entrada e sada, o que torna invivel ou at impossvel fazer testes para cada uma das combinaes.
Para esses casos, pode ser criada uma bateria de testes de correo baseada em certas caractersticas do
algoritmo e outra bateria de testes mais abrangente e menos especca (testes aleatrios e de sanidade)
que pode vericar uma quantidade maior de casos que podem dar mais segurana de que no foram
cometidos erros desastrosos.
Contudo, raros so os casos onde possvel provar a correo do sistema apenas com baterias de
testes. Como dizia Dijkstra, Testes so muito ecazes para mostrar a presena de erros, no sua ausn-
cia [50]. Para provar a correo de ummdulo comtestes necessrio vericar todos os casos possveis,
isto , deve haver uma quantidade nita de combinaes de dados de entrada e sada.
Outra forma de se provar a correo de um sistema atravs de modelos matemticos e formais, que
geralmente so processos de alto custo, pois exigem pessoas muito especializadas. Um malefcio dessa
alternativa a falta de praticidade para alterao do cdigo do sistema, pois para cada alterao preciso
refazer o modelo matemtico. Essa rigidez de desenvolvimento torna impraticvel o emprego de outras
tcnicas recomendadas por mtodos geis, tais como entregas frequentes e refatorao.
16
Para sistemas crticos, como os espaciais, de aviao e sistemas mdicos, imprescindvel a prova
e/ou uma bateria completa e minuciosa de cenrios de testes. Para esses casos, uma possvel soluo
desenvolver o sistema com prticas geis, incluindo os testes e, no nal de uma entrega, podem ser feita
avaliaes matemticas para certicar que o sistema est correto.
Robustez
Meyer dene robustez como a habilidade de sistemas de software reagirem apropriadamente sob
condies adversas [100, 135], tais como entradas invlidas de usurios, infraestrutura lenta ou concor-
rncia de processos. Tambm segundo Meyer, a robustez complementa a correo. A correo trata do
comportamento descrito pela especicao; a robustez caracteriza o que no foi especicado.
Normalmente, as histrias ou requisitos do cliente no contm, de maneira explcita, que o sistema
deve reagir corretamente sob certas condies no triviais que um software pode estar sujeito. Muitas
vezes, essas informaes so responsabilidade do desenvolvedor bem capacitado para tomar as devidas
precaues no momento oportuno.
Programaticamente possvel simular erros de software e de hardware. Muitas ferramentas pos-
suem artifcios para facilitar a escrita de casos de testes de situaes de erro, facilitando a vericao e
tornando o cdigo dos testes mais legvel. Tambm possvel criar objetos falsos que simulam erros de
hardware e infraestrutura, lanando as excees ou os cdigos de erro relacionados.
Flexibilidade
Uma boa arquitetura no deve ser apenas robusta, preciso que ela seja exvel para aceitar a adio
de novas funcionalidades com pouco trabalho e sem requerer um conhecimento profundo da arquitetura
j existente. A orientao a objeto e Padres de Projeto [61] fornecem boas alternativas que facilitam a
criao de software exvel.
Quando pensamos em testes automatizados, tambm temos de considerar que a arquitetura do sis-
tema seja testvel (Captulo 10), para que o custo-benefcio dos testes automatizados seja alto. Esta
caracterstica est diretamente ligada com a simplicidade e boa modularizao do design do sistema,
que a proposta da orientao a objetos e Padres de Projeto. Quando a implementao de um software
dirigida por casos de teste (Seo 9.3), o design emerge com simplicidade e com alta testabilidade, e,
portanto, o design tende a car altamente exvel.
Ecincia
A misso de otimizar sistemas uma preocupao de todo bom programador, mas a realizao no
criteriosa dessa tarefa pode resultar na criao de um projeto mal arquitetado e com cdigo-fonte pouco
legvel. Esta otimizao realizada de forma aleatria bem ilustrada pela frase de Donald Knuth
7
:
Otimizao prematura a raiz de todo mal [81]. A recomendao bsica otimizar os gargalos do
sistema, que geralmente consomem uma grande porcentagem de todo o tempo gasto na execuo do
software. Comumente estes gargalos so encontrados atravs da ajuda de Prolers
8
, que executam
mdulos do sistema medindo seu desempenho. Otimizar partes do sistema que no so os gargalos
trazem um benefcio desprezvel, potencialmente, a um alto custo em termos de clareza de cdigo e
dispndio de recursos humanos.
7
Donald Knuth professor emrito da Universidade de Stanford e autor de livros importantes como a srie The Art of
Computer Programming e criador de programas mundialmente conhecidos como o Tex.
8
Proler uma ferramenta para a anlise de desempenho por meio da medio do tempo e frequncia da chamada de
funes.
17
Os testes automatizados tambm exercitam trechos especcos do sistema e podem disponibilizar
o tempo de execuo de cada teste. Mas importante notar que o objetivo das baterias de testes que
buscam erros no medir o desempenho do sistema. Primeiro, porque as ferramentas de testes no so
especcas para isso e, portanto, no substituem o uso de Prolers. Segundo, porque queremos que as
baterias de testes sejam executadas muitas vezes por minuto.
Consequentemente, importante que o tempo de execuo seja muito pequeno, o que nem sempre
acontece quando queremos encontrar gargalos. Por ltimo, muitas vezes os casos de testes no ilustram
com delidade a situao real de uso do sistema, por exemplo quando utilizado Objetos Dubls (Seo
6.2), que so implementaes falsas para facilitar a escrita dos testes. Por isso, os valores no tm credi-
bilidade para serem utilizados para otimizar o sistema. Contudo, testes lentos at podem ser indicativos
de gargalos do sistema.
Existem diversos tipos de testes que servem especicamente para identicar pontos de inecincia
do sistema, como testes de desempenho, de estresse, carga e longevidade. Todos eles geralmente exigem
uma grande quantidade de dados, usurios ou tempo no decorrer das simulaes, por isso, invivel a
realizao manual dos testes e sem o auxlio de ferramentas adequadas.
Segurana
A segurana de sistemas de software fundamental principalmente para os programas mais visados por
pessoas mal intencionadas, como os que envolvem dinheiro ou informaes sigilosas que podem trazer
grandes prejuzos para empresas e pessoas. No caso de aplicaes Web, a ateno deve ser redobrada
porque elas cam expostas a usurios annimos e mal intencionados e, portanto, cam mais suscetveis
a ataques [145].
Um sistema de software pode possuir diversas fontes para possveis vulnerabilidades de segurana.
Hoje, mesmo os sistemas pequenos possuem em geral muitas dependncias de bibliotecas, middleware
e arcabouos, todas com possibilidade de conter falhas de segurana, alm do seu prprio cdigo-fonte
e do sistema operacional. Servidores de aplicaes tambm so crticos neste aspecto, j que qualquer
verso insegura pode trazer consequncias negativas para milhares de usurios.
Portanto, idealmente todos os testes de segurana devem ser executados a cada atualizao de soft-
ware do servidor ou das dependncias do projeto para averiguar que vulnerabilidades de aplicaes, do
servidor ou mesmo de conitos entre verses, tenham sido inseridas no processo. Por isso, a automao
dos testes de segurana fundamental devido a facilidade da repetio de todos os casos de testes.
Durabilidade
Produtos de software podem estar sempre em manuteno, pois podem ter de incorporar novas fun-
cionalidades, adaptar-se a novas plataformas e atingir novos mercados. Alm disso, correes e melho-
rias colaboraram com o sucesso do software. A durabilidade de um software se caracteriza pelo tempo
em que utilizado [7].
Um software pode car obsoleto por diversas razes, tais como concorrncia de outros produtos e
surgimento de novas geraes de tecnologias. Uma razo que geralmente acompanhada por prejuzos
quando o custo de manuteno do sistema se torna to grande que prefervel reconstru-lo do incio.
A diculdade de manuteno pode estar associada s tecnologias envolvidas, falhas de arquitetura do
software e tambm ao ciclo de erros de regresso, que o processo de adicionar novos erros durante
uma manuteno de outra falha.
Os erros de regresso podem diminuir drasticamente o tempo de vida til de um sistema, isso porque
o tempo gasto com essas manutenes no agrega novas funcionalidades ao sistema, podendo deixar a
evoluo do software estagnada. Ainda, o sistema pode perder sua credibilidade com os usurios e
18
clientes devido aos erros, alm de tornar o trabalho cada vez mais desgastante para a equipe de desen-
volvimento.
Um sistema no seguro para mudanas, ou seja, sem uma bateria de testes que possa ser executada
a qualquer momento de maneira gil, est sempre sujeito aos erros de regresso quando o software
modicado. Os mtodos geis ressaltam que mudanas em um sistema de software so normais e
devem ser encaradas com naturalidade, sejam elas grandes mudanas arquiteturais ou simples correes
de leiaute, mas elas precisam ser feitas sem riscos de prejudicar a qualidade do sistema.
Portabilidade
Atualmente, existe uma grande diversidade de ambientes distintos que um programa precisa se adaptar,
no s em relao a sistemas operacionais, como tambm navegadores Web e dispositivos mveis. Por
isso, fundamental para o sucesso e lucratividade de um software que ele seja portvel para diversos
ambientes para que alcance o maior pblico possvel.
Segundo a W3Counter
9
, em 2009 duas famlias de navegadores dominavam grande parte do mer-
cado: Mozilla Firefox e Microsoft Internet Explorer (Figura 2.1). Alm disso, dentro de uma
mesma famlia de navegadores existem diversas verses intensamente utilizadas, como o caso das
verses 7 e 8 do Internet Explorer e 3 e 3.5 do Firefox que possuem diferenas importantes que
podem trazer problemas de incompatibilidade para as pginas Web, assim como pode acontecer com
uma mesma verso do navegador sobre sistemas operacionais diferentes. Problemas comuns esto rela-
cionados com a no padronizao de tecnologias e falhas na interpretao de tags HTML, comandos
JavaScript e descries CSS
10
.
Figura 2.1: Popularidade de Navegadores Web em novembro de 2009 (Fonte: W3Counter).
Em relao aos sistemas operacionais o equilbrio ainda est muito distante, pois a famlia Windows
domina cerca de 85% do mercado (Figura 2.2). Contudo, 15% uma porcentagem grande pensando no
total de usurios da Internet, portanto a portabilidade entre sistemas operacionais tambm fundamental
para boa repercusso e lucratividade de um software.
A popularizao dos dispositivos mveis, tais como celulares, computadores de mo e smart phones
tambm tem trazido a tona a importncia da portabilidade. Para cada tipo de aparelho existe uma grande
diversidade de marcas e arquiteturas de hardware, que possuem infraestruturas especcas de progra-
mao. Ainda, com as tecnologias de transmisso de dados entre aparelhos como Bluetooth, Wi-Fi e
infravermelho, a necessidade de compatibilidade entre diferentes sistemas acentuada.
9
W3Counter uma pgina Web que agrupa informaes de trfego de milhares de pginas populares da Web.
10
Cascading Style Sheets ou CSS so folhas de estilo que so aplicadas em componentes Web para alterar o design.
19
Figura 2.2: Popularidade de Sistemas Operacionais em novembro de 2009 (Fonte: W3Counter).
As linguagens portveis, que usam mquinas virtuais para interpretar cdigos compilados em um
formato especco (byte codes), tais como Java, Python e Ruby, esto cada vez mais populares (Figura
2.3, obtida em 2011 da pgina Web Programming Language Popularity
11
e Figura 2.4, obtida em 2009
da pgina Web TIOBE Software
12
). Uma das razes que elas facilitam muito a escrita de programas
portveis, j que elas abstraem as diferenas do hardware das mquinas e criam uma API comum para
todas elas. No entanto, no garantido que a linguagem ou outras ferramentas sejam portveis para
todas as funcionalidades de um hardware porque podem haver diferenas enormes de tecnologias que
torna impossvel denir uma API padro para todas as mquinas.
Figura 2.3: Indicao normalizada de popularidade de linguagens de programao no comeo de 2011.
Uma maneira de assegurar que um sistema de software funciona em um determinado ambiente
ser submetido a pelo menos uma bateria de testes. Mas invivel que pessoas realizem este trabalho
repetidamente para cada ambiente, pois o nmero de casos de teste multiplicado pelo nmero de
plataformas a serem testadas. Por exemplo, se temos uma bateria simples de testes para uma aplicao
Web contendo 500 casos de teste e existe uma exigncia da aplicao ser executada pelo menos nos
navegadores mais populares (Firefox 2 e 3 e Internet Explorer 6 e 7) sob o sistema operacional mais
popular (Windows), teremos um total de 2000 casos de testes a serem executados.
No caso dos testes automatizados, basta executar a mesma bateria de testes em diferentes sistemas
operacionais e plataformas para se certicar que nenhum erro de incompatibilidade ocorreu. J no caso
de aplicaes Web, existem hoje ferramentas, como a Selenium
13
, que auxiliam a criao de testes
11
A pgina Web Programming Language Popularity (http://www.langpop.com) faz pesquisas em alguns grandes portais
de buscas e de incubadoras de sistemas de software para coletar informaes que so agrupadas e analisadas estatisticamente
para tentar denir a popularidade das linguagens de programao.
12
A ordenao por popularidade da pgina Web TIOBE Software (www.tiobe.com) feita com base em dados coletados em
grandes portais de buscas.
13
Ferramenta para testes de aplicaes de interface Web.
20
Figura 2.4: Outra indicao de popularidade de linguagens de programao: 2008 e 2009.
automatizados portveis entre navegadores, que abstraem as diferenas internas como as de JavaScript
e CSS.
Usabilidade
A usabilidade dos sistemas fundamental para facilitar seu aprendizado e para agilizar o acesso s
informaes pertinentes [133, 98]. Quanto mais intuitiva for a interface, menor ser o tempo gasto com
o estudo e entendimento do sistema. Atualmente, esta caracterstica est cada vez mais em destaque,
por causa do uso intenso do computador, da grande variedade de programas e da imensa quantidade de
contedo disponvel nas pginas Web.
Uma das estratgias de testes de usabilidade se d atravs da observao do uso do sistema por
usurios selecionados de acordo com um perl desejado. As aes dos usurios podem ser lmadas ou
documentadas para futura avaliao. A partir das informaes coletadas feita anlise da facilidade de
uso do sistema.
Na rea de testes automatizados ainda h a necessidade de mais ferramentas especializadas que
facilitem a coleta e interpretao das informaes de usabilidade, mas muito j pode ser feito atravs de
ferramentas de gravao de aes do usurio, de interceptadores de requisies ou ainda com auxlio de
programao orientada a aspectos. A interpretao das aes coletadas a tarefa mais complicada, pois
deve ser baseada em denies subjetivas ou em heursticas de Interao Humano-Computador.
Acessibilidade
Acessibilidade em software a caracterstica de usabilidade de possibilitar que mesmo usurios com
necessidades especiais tenham acesso utilizao de um software. Os usurios especiais so indivduos
que possuem alguma peculiaridade fsica ou pscicolgica que diculta ou impede o uso de sistemas
de software pelas interfaces de usurio tradicionais [42]. Dentre esses usurios especiais esto idosos,
decientes visuais e auditivos, tetraplgicos, entre outros.
Com as ferramentas de testes automatizados de interface Web e de Desktop, possvel criar testes
para vericar a acessibilidade atravs da criao de eventos originrios de dispositivos especcos. Por
exemplo, podemos criar um caso de teste que tenta executar uma determinada ao apenas com eventos
do mouse ou apenas com eventos do teclado. Tambm possvel fazer testes que captam informaes
do leiaute, tais como tamanho das letras dos componentes de texto.
21
Beleza
Dependendo do tipo de sistema e do produto vinculado, beleza um atrativo fundamental para atrair
novos clientes e usurios. Por isso, muitas aplicaes, principalmente as voltadas para Web, possuem
designers, prossionais especializados em arte eletrnica que trabalham com a gerao de mdias e com
a organizao da interface de usurio para torn-la atraente e agradvel.
Esse trabalho artstico, que pode ser realizado antes, depois ou paralelamente ao desenvolvimento do
sistema, pode embutir diferentes tipos de no conformidades no sistema. A interface possui muitas re-
sponsabilidades, por isso ela est sujeita a erros de correo, robustez, portabilidade e falhas especcas
da interface grca, como usabilidade e acessibilidade ruim. Por isso, toda alterao do design precisa
ser encarada como uma mudana do cdigo-fonte, que exige que todos os testes sejam executados no-
vamente. Como esta tarefa pode ser rotineira, principalmente no caso das pginas Web, necessrio a
agilidade dos testes automatizados para a certicao de que a qualidade do sistema no foi prejudicada.
2.7 Concluses
A prtica de testes automatizados est cada dia mais popular e disseminada entre as comunidades de
desenvolvimento de software devido, principalmente, ao incentivo dessa prtica por parte dos mtodos
geis e por linguagens e tecnologias que facilitam a criao e manuteno do cdigo dos testes.
A automao de testes uma prtica de baixo custo de criao e manuteno que ajuda a garantir a
qualidade dos sistemas de software se comparado com outras estratgias, tais como anlises formais que
exigem um alto grau de especializao de prossionais e tambm com testes manuais que no trazem
seguranas para mudanas, no eliminam o trabalho de depurao e de documentao dos testes.
Uma das premissas dos mtodos geis tornar o desenvolvimento de software adaptvel a mudanas,
j que difcil conhecer todos os requisitos e o melhor design desde o comeo. impossvel prever com
exatido e certeza todas as possveis diculdades e fatores externos que podem afetar o andamento de
um projeto, tais como utuaes do mercado e da concorrncia que podem mudar as prioridades dos
requisitos.
O trabalho de depurao, que geralmente acompanhado de testes manuais, no agrega valor di-
retamente ao produto nal, ele apenas ajuda a localizar o motivo de um erro que j foi detectado para
futura correo. Esta tarefa pode ser demorada e estressante para os desenvolvedores, principalmente
quando o erro por uma falha simples que podia ser evitada com um pouco mais de ateno durante o
desenvolvimento.
No caso dos testes automatizados, que evitam o trabalho de depurao, todo o tempo gasto est
vinculado diretamente com a vericao e validade do sistema, mesmo nos casos de fracasso. Por isso,
um tempo de investimento real em qualidade. Alm disso, todo o tempo dedicado para escrita dos
testes traz benefcios durante o decorrer do desenvolvimento do software.
Por m, importante estar ciente que todas as abordagens para melhoria da qualidade dos sistemas
de software exigem interveno humana no processo de criao, sendo assim, todas esto sujeitas a im-
perfeies. Por isso, como nenhuma das abordagens so conitantes entre si, elas podem ser combinadas
com o intuito de agregar os benefcios de cada uma para tornar o processo de controle de qualidade mais
ecaz. Mas o que fundamental dar nfase abordagem que mais trar benefcios dentro do contexto
do sistema.
22
Captulo 3
Denies e Terminologia
A rea de testes de software possui um linguajar prprio, extenso e com muitas nomenclaturas [125],
sendo que algumas possuem interpretaes diferentes nas diversas comunidades, ferramentas e tambm
de autores importantes de um mesmo grupo de pesquisa [99]. Testes de software so estudados pela
comunidade de desenvolvimento gil, pela comunidade tradicional de engenharia de software e tambm
por grupos de testadores e de controle de qualidade, todas com um dialeto prprio, principalmente
porque as abordagens so muito diferentes.
Durante o decorrer desta dissertao, o dialeto utilizado ser primordialmente aquele da comunidade
de mtodos geis, mas com o uso de alguns termos das outras reas de estudo. Neste captulo esto as
principais denies e terminologias do tema testes de software e automao de testes para tornar a
leitura do resto do trabalho mais produtiva.
3.1 Abordagens de Controle de Qualidade
Existem muitas abordagens de teste de software e de controle de qualidade, cada uma com um linguajar
peculiar o que diculta a interpretao e torna o estudo mais lento. Isto pode ser observado no s em
livros e artigos como tambm na Internet, atravs das postagens em blogs, listas e fruns de discusso e
tambm em mini-debates, onde no h uma padronizao rigorosa.
As abordagens de qualidade podem ser divididas em dois grupos: testes estticos que so veri-
caes do cdigo-fonte e da documentao; e testes dinmicos que incluem vericaes do software em
tempo de execuo. Nas abordagens dos testes estticos esto as prticas de revises de cdigo [149],
inspeo [63] e walkthroughs [26]. J no grupo dos testes dinmicos esto os testes manuais e autom-
atizados, que exercitam o software em tempo de execuo. A seguir h a uma denio simplicada
de cada uma das abordagens mais comuns das comunidades tradicionais e gil de desenvolvimento de
software.
Abordagens tradicionais
Os processos tradicionais de gerenciamento de software propem diversas tcnicas e artefatos para au-
mentar a qualidade do produto nal, entre eles esto documentos de requisitos e prticas como Reviso,
Inspeo e Testes Manuais. Do estudo destas tcnicas podemos tirar conhecimento para melhorar a
qualidade dos testes automatizados.
Reviso: a prtica da averiguao minuciosa em busca de erros de artefatos produzidos pelo desen-
volvimento de software, como cdigo-fonte, e documentao [72]. Existem revises tcnicas,
de cdigo-fonte e walkthroughs que so revises realizadas em pares ou em grupos de pessoas
[151, 26].
23
Inspeo: Proposta por Tom Gilb, inspeo um tipo especco de reviso que visa planejar casos de
testes e fazer uma reviso formal da especicao e de documentos para capturar erros, ambigu-
idades e dvidas antes da implementao [63, 137].
Testes Manuais: So realizados por seres humanos que utilizam o sistema em busca de no conformi-
dades e de aspectos de qualidade que podem ser melhorados [100].
Abordagens geis
Os mtodos geis propem novas abordagens de controle de qualidade no desenvolvimento de software,
todas relativamente recentes, mas com fundamentao prtica, terica e emprica. Essas abordagens,
incluindo testes automatizados, possuem propsitos distintos para solucionar problemas diferentes e
recorrentes. A seguir so destacadas trs destas abordagens.
Comunicao Efetiva: Mtodos geis substituem especicaes rigorosas e detalhadas pela prtica de
comunicao frequente e efetiva, idealmente realizada diretamente com o cliente ou com usurios
nais do produto para esclarecer dvidas em relao s histrias (requisitos). Essa abordagem
depende de acordos e contratos especcos entre times de desenvolvimento e clientes para que os
trabalhos sejam realizados sem desentendimentos [3, 40, 1].
Programao em Pares: a prtica onde duas pessoas participam ativamente do desenvolvimento de
uma mesma funcionalidade ao mesmo tempo. A programao em pares tem como principal obje-
tivo a reviso do cdigo-fonte em tempo de implementao, realizada atravs da redundncia de
ideias e da observao de dois programadores distintos [146, 39, 140].
Testes Automatizados: a abordagem de criar scripts ou programas simples de computador que ex-
ercitam o sistema em teste, capturam os efeitos colaterais e fazem vericaes, tudo isso auto-
maticamente e dinamicamente [99].
3.2 Termos e Siglas
Existem muitas convenes e padronizaes para denir certos termos de testes de software, mas para
alguns desses termos a padronizao no seguida rigidamente por todas as comunidades. Alguns de-
les so usados rotineiramente em nossas conversas dirias com signicados diferentes dependendo do
contexto, o que diculta a xao dos padres e consequentemente a interpretao dos estudos tcni-
cos. Abaixo est a descrio de alguns desses termos e algumas observaes referente terminologia
utilizada por este trabalho.
Engano/Defeito/Falha/Erro/No conformidade: Existem padres que diferenciam esses termos [111,
114], onde cada um possui um signicado especco. No entanto, este texto interpreta todos
como sinnimos, e para distinguir os diferentes tipos de erros utilizado explicitamente um texto
adicional autoexplicativo, por exemplo: Erro de distrao do programador. Apesar do termo
car mais longo, evita problemas de ambiguidades e tambm no fere convenes denidas por
ferramentas e outras comunidades.
Vericao: Atividade que verica se o produto est sendo desenvolvido corretamente [29]. A maioria
dos tipos de testes de vericao, tais como os testes de unidade, de interface, de sanidade entre
outros.
24
Validao: Tarefa para avaliar se o software que est sendo desenvolvido o esperado, isto , se atende
especicao [29]. Os testes de aceitao, ou testes do cliente, apontam para os desenvolve-
dores quais os requisitos que devem ser implementados e quais cenrios devem ser satisfeitos,
facilitando a validao do sistema por parte do cliente e indicando para os programadores quando
uma interao do desenvolvimento foi nalizada.
Testes Caixa Branca ou Caixa Transparente ou Caixa de Vidro: Tambm conhecido como teste es-
trutural, so os testes que fazem vericaes baseadas na implementao [95].
Testes Caixa Preta: Tambm conhecido como testes funcionais, so aqueles que vericam funcionali-
dades sem conhecer a implementao [21].
Testes Caixa Cinza: uma mistura dos testes caixa branca e preta, isto , envolve os dois conceitos
dentro de um mesmo cenrio de vericao.
Erros e Testes de Regresso: Quando um erro identicado em um trecho de cdigo que estava fun-
cionando corretamente em verses anteriores do sistema, dizemos que um erro de regresso, isto
, um erro que foi adicionado durante alguma manuteno. Pensando em vericaes manuais,
dizemos que testes de regresso so aqueles que buscam encontrar este tipo de erro. Contudo,
com testes automatizados esses termos so raramente utilizados, pois todos os testes passam a ser
testes de regresso, j que todos ajudam a evitar esse tipo de erro.
Testes de Correo: So tipos de vericaes que buscam erros no sistema, tais como os testes de
unidade, integrao, interface de usurio e aceitao. O teste de longevidade tambm verica a
correo, mas especco para vericar erros que s tendem a ocorrer depois de um certo tempo
de execuo do sistema.
Verses Alfa e Beta: Quando uma verso do software est nalizada e aparentemente estvel, dizemos
que sua verso alfa, pois ele liberado para uso por um grupo especco de usurios de homolo-
gao. J o software que est em ambiente de produo real e permite que qualquer usurio o
utilize para testes, dizemos que a sua verso beta.
Caso de Falso Positivo: Caso de teste que teve sucesso apesar do que est sendo vericado conter erros.
Normalmente isso ocorre por uma falha do teste que no fez todas as vericaes esperadas, mas
tambm pode ser por erros no prprio cdigo da bateria de testes.
Caso de Falso Negativo: Caso de teste que falha apesar do que est sendo vericado estar correto.
Qualquer erro de implementao nos testes pode criar este cenrio.
Padres: Descrevem solues para problemas recorrentes no desenvolvimento de sistemas de software.
Este termo surgiu dos Padres de Projeto (Design Patterns) de sistemas orientados a objetos [61].
Tambm existem padres relacionados com testes automatizados [99], que so solues comuns
para organizar os casos de testes, para criar vericaes mais robustas etc.
Antipadres: Antipadres so erros recorrentes, comumente realizados em diferentes contextos. Um
Antipadro descreve o erro e formas de evit-lo.
Indcios de Problemas: Tambm conhecido como cheiros, so caractersticas do software, do
cdigo-fonte ou at mesmo da forma de desenvolvimento que do indcios que alguma soluo
equivocada foi utilizada.
Testabilidade: uma caracterstica que indica o quo fcil de ser testado um sistema. Um sistema
com alta testabilidade fcil de ser testado.
25
Os termos testes funcionais e estruturais (testes de caixa branca, preta e cinza) no sero utilizados
neste trabalho, e sempre que necessrios sero substitudos por termos que explicitem o objetivo do
teste. Isso por dois motivos: no faz parte dos objetivos do trabalho estudar e comparar essas diferentes
tcnicas de testes pois j existem outros trabalhos sobre isso [95]; e tambm para evitar problemas
de m interpretao durante a leitura desta dissertao ou durante o uso de ferramentas de testes que
utilizam convenes diferentes. Por exemplo, o famoso arcabouo para desenvolvimento Web Ruby
on Rails dene testes funcionais como os de unidade referente a camada dos controladores, do padro
arquitetural MVC [32].
Ser recorrente neste trabalho o uso de siglas que so habitualmente utilizadas pelas comunidades
geis de testes automatizados. Algumas vezes, existe mais de uma sigla para a mesma ideia, ou duas
muito parecidas que podemser confundidas durante a leitura. Por isso, abaixo segue uma breve descrio
daquelas mais comuns, sendo que algumas delas sero mais aprofundadas pelo trabalho enquanto outras
s sero citadas.
SUT System Under Test, ou Sistema em Teste: a aplicao que est sendo exercitada e vericada
pelos testes automatizados.
AUT Application Under Test, ou Aplicao em Teste: Anlogo SUT.
DDD Domain-Driven Design, ou Design Dirigido pelo Domnio: simplicadamente, uma abordagem
de desenvolvimento de software que prope que o design do sistema seja fortemente conectado ao
modelo de negcios, no simplesmente em arquiteturas denidas exclusivamente por desenvolve-
dores ou por ferramentas [8].
TAD Test After Development, ou Testes Aps a Implementao: Tcnica de escrever testes automatiza-
dos depois da implementao (Seo 9.1).
TFD Test First Development, ou Testes Antes da Implementao ou Testes a priori: Tcnica de escrever
testes automatizados antes da implementao (Seo 9.2).
TDD Test-Driven Development, ou Desenvolvimento Dirigido por Testes: Tcnica de desenvolvimento
baseada em iteraes curtas do ciclo: escrita de um teste de unidade, implementao da mnima
poro de cdigo de produo que seja suciente para o teste passar e, por ltimo, refatorao
do cdigo caso seja necessrio. Apesar de os testes serem escritos antes da implementao, esta
tcnica no o mesmo que TFD (Seo 9.3).
BDD Behavior-Driven Development, ou Desenvolvimento Dirigido por Comportamento: um apri-
moramento da linguagem de TDD para criar uma linguagem ubqua entre cliente e equipe de
desenvolvimento, que segue o mesmo princpio dos testes de aceitao. BDD sugere o uso dos
conceitos de DDD para substituir o vocabulrio tradicional de testes de TDD por um vocabulrio
que seja prximo de uma especicao. Dessa forma, BDD pode ser utilizado tanto para os testes
de unidade quanto para os testes de aceitao (Seo 9.4).
ATDD Acceptance-Test Driven Development, ou Desenvolvimento Dirigido por Testes de Aceitao:
Tcnica que sugere que o desenvolvimento siga um ciclo semelhante ao de TDD, mas que envolve
os testes de aceitao e os de unidade. O ciclo sugere que sejam escritos primeiramente os testes
de aceitao de uma histria (conjunto de requisitos), que guiaro a implementao com TDD
dos primeiros testes de unidade para a histria correspondente. Aps os testes de unidade estarem
nalizados, deve ser feito os ajustes nais do teste de aceitao e ento execut-los. Quando
o teste de aceitao obtm sucesso, a histria pode ser nalizada. Dessa forma, os testes de
aceitao tambm so indicadores de quando uma histria foi nalizada.
26
STDD Story Test-Driven Development, ou Desenvolvimento Dirigido por Testes da Histria: Mesmo
que ATDD e que Customer Test Driven Development.
TDDD Test-Driven Database Design, ou Modelagem do Banco de Dados Dirigido por Testes: A ideia
aplicar as prticas de TDD na criao de um esquema de banco de dados [2].
CT Continuous Testing: a prtica de executar os testes automatizados continuamente, atravs de um
programa que detecta qualquer alterao de cdigo [124]. Ela foi originada a partir de TDD, que
requer que os testes sejam executados muitas vezes em poucos minutos. Uma ferramenta de CT
ca observando os arquivos de cdigo-fonte do sistema e dos testes, se algum deles for modicado
e salvo, a ferramenta automaticamente executa uma bateria de testes que ela julgar pertinente. Este
processo diminui a necessidade de interveno humana no manuseio de ferramentas e acelera a
obteno de feedback.
3.3 Tipos de Testes Automatizados
Por causa da popularizao dos computadores e da Internet, o nmero de usurios de sistemas de soft-
ware est crescendo, incluindo o nmero de usurios crianas, idosos e especiais. No obstante, a
sociedade est cada vez mais dependente dos sistemas de software, pois eles esto sendo utilizados cada
vez mais para gerenciar processos importantes. Por isso, a exigncia de qualidade cresce a cada dia e
algumas falhas de software esto cada vez mais em evidncia, como problemas de usabilidade, segu-
rana e desempenho, alm de diversos outros que podem ser desde enganos simples por desateno do
programador at mau entendimento dos requisitos.
Para muitos tipos de erros existem testes especcos, que fazem vericaes seguindo certas pre-
missas e padres. Por isso, fundamental organizar os casos de teste por tipo devido a vrias razes:
1) facilita a manuteno dos testes e a adio de novos cenrios para correo de erros; 2) eles podem
utilizar ferramentas prprias e seguir padronizaes diferentes; 3) o tempo de execuo pode ser variado,
ento baterias de testes lentas no afetaro o feedback rpido que as baterias velozes proporcionam; 4)
facilita a coleta das mtricas por tipo de teste, que pode ser til para identicar pontos de vericao que
precisam de mais esforo.
Cada tipo de teste tambm possui ferramentas especializadas, justamente para facilitar a escrita e
tornar o cdigo mais enxuto e legvel, logo, mais fcil de manter. Um erro comum exercitar ou utilizar
uma ferramenta de umtipo de teste especco para objetivos que no so de sua responsabilidade natural,
o que pode levar criao de testes de baixa qualidade. Portanto, necessrio conhecer o leque de opes
de ferramentas para optar pelas mais apropriadas para o que se est querendo vericar.
Tambm importante notar que alguns tipos de testes s fazem sentido com o auxlio da automao,
devido principalmente a sua complexidade de implementar ou de executar os testes, tais como os de
desempenho, carga e longevidade. Os testes de unidade tambm so mais interessantes quando autom-
atizados, porque, apesar da fcil implementao e execuo, eles geralmente no possuem interface de
usurio intuitiva para possibilitar os testes manuais. Nas sees seguintes sero descritos em mais de-
talhes alguns desses tipos de testes assim como ser abordado o tema de automao de testes para cada
um deles. No nal da seo tambm ser apresentado uma gura e uma tabela criadas pelo autor com o
objetivo de agrupar de forma resumida algumas das principais caractersticas de cada tipo de teste.
3.3.1 Teste de Unidade
Teste de correo responsvel por testar os menores trechos de cdigo de um sistema que possui um
comportamento denido e nomeado. Normalmente, ele associado a funes para linguagens procedi-
mentais e mtodos em linguagens orientadas a objetos.
27
1 # Referncia do PyUnit
2 import unittest
3
4 # Referncia do sistema em teste
5 from mathutils import is_primo
6
7 class PrimoNaturalTests(unittest.TestCase):
8
9 def test_numeros_0_e_1_nao_sao_primos_por_convencao(self):
10 self.assertFalse(is_primo(0))
11 self.assertFalse(is_primo(1))
12
13 def test_numero_2_e_primo(self):
14 self.assertTrue(is_primo(2))
15
16 def test_numero_par_diferente_de_2_nao_eh_primo(self):
17 self.assertFalse(is_primo(4))
18 self.assertFalse(is_primo(6))
19 self.assertFalse(is_primo(1000))
20
21 def test_numero_com_apenas_2_divisores_eh_primo(self):
22 self.assertTrue(is_primo(3))
23 self.assertTrue(is_primo(5))
24 self.assertTrue(is_primo(7))
25
26 def test_numero_com_mais_de_2_divisores_nao_eh_primo(self):
27 self.assertFalse(is_primo(9))
28 self.assertFalse(is_primo(15))
29 self.assertFalse(is_primo(21))
Figura 3.1: Exemplo de teste de unidade.
28
A Figura 3.1 apresenta um exemplo de teste de unidade em Python com auxlio da ferra-
menta unittest, que j vem inclusa na biblioteca padro da linguagem. Neste exemplo, h di-
versos casos de testes (mtodos com nomes iniciados com a palavra test) encapsulados em uma
classe PrimoNaturalTests para um mtodo chamado is_primo que devolve um valor booleano,
indicando se o nmero natural primo. Os mtodos assertTrue e assertFalse so herdados
de unittest.TestCase, que a classe base para a escrita de testes com essa ferramenta. Na
execuo dessa classe, se o teste espera que o mtodo is_primo devolva um valor verdadeiro
(self.assertTrue), mas o mtodo devolve um valor falso, ento lanado uma exceo automatica-
mente que armazenada por objetos de log, contendo qual teste falhou e o motivo. Se o valor esperado
obtido, ento o log armazena que o caso de teste foi executado com sucesso.
3.3.2 Teste de Integrao
Teste de integrao uma denominao ampla que representa a busca de erros de relacionamento entre
quaisquer mdulos de um software, incluindo desde a integrao de pequenas unidades at a integrao
de bibliotecas das quais um sistema depende, servidores e gerenciadores de banco de dados. Um trecho
ou mdulo do sistema pode estar completamente correto, mas no h garantias de que as camadas
superiores, que fazem chamadas a esse trecho de cdigo, esto implementadas corretamente.
Os erros de integrao so frequentes, principalmente quando vamos utilizar bibliotecas de terceiros
que no conhecemos por completo. Alm disso, quanto mais complexa for a arquitetura do sistema,
maior a chance de existirem erros de integrao, j que aumenta a quantidade de troca de mensagens
entre os mdulos. Nos sistemas mal modelados, a situao ca ainda mais crtica. Falhas de design
como intimidade inapropriada entre objetos e o excesso de responsabilidades em um mdulo do sistema
[59] tornam o software difcil de entender e manter, portanto ele ca muito suscetvel a adio de erros
de integrao.
Existem vrias ferramentas que fornecem utenslios para facilitar a escrita dos testes de integrao.
O Maven, ferramenta de gerenciamento de projetos Java, disponibiliza uma arquitetura padronizada
para armazenar os testes de integrao. J o arcabouo Grails, utilizado para desenvolvimento Web
com Groovy, fornece um diretrio para os testes de integrao onde automaticamente os testes so
carregados com os mtodos dinmicos de acesso ao banco de dados, o que facilita os testes de queries e
mapeamentos objeto-relacional, que requerem a integrao dos gerenciadores de banco de dados.
Na Parte II sero discutidos dois subtipos de testes de integrao: os testes com persistncia de
dados (Captulo 7), que podem depender de gerenciadores de banco de dados e de sistemas de arquivos;
e testes de interface de usurio (Captulo 8), os quais podem envolver arcabouos de interfaces grcas
e Web.
3.3.3 Teste de Interface de Usurio
A interface de usurio (Graphical User Interface (GUI) ou Web User Interface (WUI)) um mdulo
peculiar de um sistema de software, pois o nico que mantm contato direto e constante com os
usurios nais do sistema e a partir dela que o usurio normalmente julga se o software de qualidade.
Por isso, qualquer no conformidade dessa camada pode ofuscar todo interior do software, que pode ser
de boa qualidade.
Os testes automatizados de interface vericam a correo por meio da simulao de eventos de
usurios, como se uma pessoa estivesse controlando dispositivos como mouse e teclado. A partir dos
efeitos colaterais dos eventos, so feitas vericaes na interface e em outras camadas para se certicar
que a interface est funcionando apropriadamente.
A Figura 3.2 contm um exemplo de teste de interface Web, uma pgina que contm um formulrio
de login. O exemplo escrito em Java e utiliza as ferramentas TestNG para denir os casos de testes
(Test), o JUnit para fazer as vericaes (assertEquals) e o WebDriver para criao dos eventos de
29
usurio. FirefoxDriver cria um driver que representa o navegador, e ele que cria os eventos de
usurio, tais como cliques do mouse (linha 17) e digitao de teclas do teclado (linhas 15 e 16). A linha
18 faz uma vericao para certicar se a interface foi atualizada corretamente aps a autenticao.
1 // referncias do WebDriver
2 import org.openqa.selenium.By;
3 import org.openqa.selenium.WebDriver;
4 // referncias do TestNG
5 import org.testng.annotations.Test;
6 // referncias do JUnit
7 import static org.junit.Assert.assertEquals;
8
9 public class LoginInterfaceTests {
10
11 @Test
12 public void loginComSucessoHabilitaLinkDeLogout() {
13 WebDriver browser = new FirefoxDriver();
14 browser.get("http://umsite.net");
15 browser.findElement(By.id("username_field")).sendKeys("fulano");
16 browser.findElement(By.id("password_field")).sendKeys("abracadabra");
17 browser.findElement(By.name("login_button")).click();
18 assertEquals("Logout", browser.findElement(By.id("logout_link")).getText());
19 }
20
21 }
Figura 3.2: Exemplo de teste de interface Web com Java.
Como a interface de usurio o carto de visita do programa, no basta apenas ela estar correta,
necessrio que ela seja organizada, atraente e que permita que diferentes grupos de usurios consigam
utiliz-la, por isso importante os testes de leiaute, usabilidade e acessibilidade.
Teste de Leiaute
Os testes de leiaute buscam avaliar a beleza da interface, assim como vericar a presena de erros aps
a renderizao, que so erros difceis de se identicar com testes comuns de interface. Por exemplo,
um teste de interface bsico pode facilmente vericar que um mdulo da interface foi carregado cor-
retamente, mas no garantido que o mdulo est bem desenhado ou mesmo visvel para o usurio
nal.
Alm disso, o leiaute pode variar signicativamente entre diversas plataformas, tais como em difer-
entes gerenciadores de janelas e navegadores Web. Cada plataforma pode possuir suas particularidades,
j que as funcionalidades e algoritmos de renderizao podem variar consideravelmente, por isso uma
bateria de testes de leiaute tambm importante para vericar a portabilidade do sistema.
Ainda h uma carncia de ferramentas que facilitem a automao para estes tipos de testes, prin-
cipalmente porque a grande subjetividade na interpretao do que certo ou errado diculta a criao
de ferramentas completas e exveis. No entanto, muito pode ser feito com auxlio das ferramentas dos
testes de interface, nem que seja para facilitar os testes manuais.
A Figura 3.3 apresenta um exemplo de teste de leiaute semiautomatizado, escrito em Java com
auxlio das ferramentas Selenium e Util4Selenium. O script automatizado de testes contm os mtodos
visitaPaginaPrincipal, visitaPaginaInformacoes e visitaPaginaResultadosDeBusca que
tm instrues da ferramenta Selenium que enviam comandos para o navegador para iteragir com deter-
minadas pginas do sistema.
30
1 // Classe base pra todas clases de teste de layout
2
3 // referncias do TestNG
4 import org.testng.annotations.AfterSuite;
5 import org.testng.annotations.BeforeSuite;
6 // referncias do Util4Selenium
7 import utilities.util4selenium.annotations.Screenshot;
8 import utilities.util4selenium.annotations.Screenshot.ScreenshotPolicy;
9 // referncias do Selenium-RC/Java
10 import com.thoughtworks.selenium.DefaultSelenium;
11 import com.thoughtworks.selenium.Selenium;
12
13 @Screenshot(policy = ScreenshotPolicy.ALWAYS)
14 public class SeleniumTestCase {
15 public Selenium browser;
16
17 @BeforeSuite
18 public void abreNavegador() {
19 browser = new DefaultSelenium("localhost", 4444, "*chrome", "http://localhost
:8080");
20 browser.start();
21 }
22
23 @AfterSuite
24 public void fechaNavegador() {
25 browser.stop();
26 }
27 }
28
29 // Classe de teste de layout
30
31 import org.testng.annotations.Test;
32
33 public class PaginasPublicasLayoutTests extends SeleniumTestCase {
34
35 @Test public void visitaPaginaPrincipal() {
36 browser.open("/");
37 }
38
39 @Test public void visitaPaginaInformacoes() {
40 browser.open("/about");
41 }
42
43 @Test public void visitaPaginaResultadosDeBusca() {
44 browser.open("/search");
45 browser.type("word", "open source");
46 browser.submit("search_form");
47 }
48
49 }
Figura 3.3: Exemplo de teste de leiaute Web com Java.
31
Oresto do trabalho realizado pela ferramenta Util4Selenium, atravs da anotao Screenshot, que
captura a imagemda tela aps o trmino da execuo do mtodo (a poltica ScreenshotPolicy.ALWAYS
determina que sempre um screenshot ser capturado, sem excees).
No nal da execuo temos uma lista de imagens, que alguma pessoa pode observar visualmente em
busca de falhas do leiaute, eliminando as tarefas de navegar entre as pginas e preencher formulrios
repetidamente para diferentes navegadores e a cada mudana de leiaute.
Usabilidade e Acessibilidade
Os testes de usabilidade vericam a facilidade de aprendizado e de uso de um sistema. O requisito bsico
para uma boa usabilidade a correo do sistema e da interface mas, para uma melhor organizao, a
correo deve ser vericada em outras baterias de testes, como as de unidade e interface. Seguindo esse
padro organizacional, os testes de usabilidade devem vericar outras caractersticas, como organizao,
padronizao e clareza da interface, assim como a documentao de ajuda para o usurio.
Para uma boa usabilidade, a organizao da interface deve levar em considerao quais as funcional-
idades mais importantes e as mais utilizadas, o tipo de programa e tambm o pblico alvo. Por isso,
tambm importante os testes de acessibilidade, que so um tipo de teste de usabilidade especco
para usurios com alguma limitao da viso, audio ou motora. Geralmente, esse grupo de usurios
composto por idosos, decientes ou pessoas com doenas especcas, tais como mal de Parkinson,
sndrome do encarceramento etc. As limitaes destes usurios os impedem de utilizar com xito alguns
dispositivos do computador, como o monitor, mouse e teclado.
Os testes de acessibilidade devem vericar se possvel utilizar o sistema com facilidade usando
apenas alguns dos dispositivos. Eles podem vericar os tamanhos e cores e contrastes dos textos e das
imagens, a existncia de atalhos de teclado para os comandos, opes de udio para componentes de
CAPTCHA
1
etc.
Entretanto, apesar da automao tambm ser til para vericar a usabilidade dos sistemas, muitas
vezes eles precisam ser realizados manualmente por causa da grande diculdade de automatiz-los. A
relao custo-benefcio da criao de algoritmos e heursticas de vericao pode ser maior do que a
repetio manual dos testes.
3.3.4 Teste de Aceitao
Tambm conhecido como teste funcional ou de histria de usurio, so testes de correo e validao.
Eles so idealmente especicados por clientes ou usurios nais do sistema para vericar se um mdulo
funciona como foi especicado [96, 87]. Por isso o termo aceitao, pois ele verica se o cliente aceita
as funcionalidades que foram implementadas. Os testes de aceitao devem utilizar uma linguagem
prxima da natural para evitar problemas de interpretao e de ambiguidades, e tambm devem ser
facilmente conectados ao cdigo do sistema para que os comandos e vericaes sejam executados no
sistema em teste [104].
Nas diretrizes da Programao eXtrema, uma histria do cliente no nalizada enquanto os testes
de aceitao no certicarem que o sistema atende aos requisitos especicados. Sendo assim, os testes
de aceitao no s so utilizados para identicar erros de programao e interpretao dos requisitos
como tambm para identicar quando uma histria foi nalizada.
1
CAPTCHA ou Completely Automated Public Turing test to tell Computers and Humans Apart, um teste de desao
cognitivo utilizado como ferramenta anti-spam. Na Internet comum um componente que fornece um pequeno desao como
uma imagem ou um som que facilmente decifrado por um humano, mas muito difcil de ser avaliado por um computador,
assim possvel evitar que scripts automatizados indesejados utilizem o sistema.
32
3.3.5 Teste de Desempenho
Testes de desempenho executam trechos do sistema em teste e armazenam os tempos de durao obtidos,
como um cronmetro. Os testes de desempenho no avaliam a complexidade computacional dos algo-
ritmos, por isso os tempos obtidos esto intimamente relacionados infraestrutura sobre a qual o teste
est sendo executado, podendo variar drasticamente dependendo do hardware, da rede etc. [129, 51].
Os resultados dos testes de desempenho ajudam a identicar os gargalos que precisam de otimizao
para diminuir o tempo de resposta para o usurio [90]. A otimizao pode ser feita atravs de mudanas
em algoritmos e tambm pela adio de caches em pontos especcos do sistema, caso os algoritmos j
sejam sucientemente rpidos.
3.3.6 Teste de Carga
O teste de carga exercita o sistema sob condies de uso intenso para avaliar se a infraestrutura ade-
quada para a expectativa de uso real do sistema [9, 10]. So criadas simulaes com muitos usurios e
requisies ao software realizadas simultaneamente ou dentro de um intervalo pequeno de tempo para
medio de informaes de desempenho. Dependendo do sistema e do que o teste quer avaliar, pode
ser vericado o tempo de resposta de cada requisio ou informaes relativas ao uso de recursos, como
uso da CPU, cache, memria, espao em disco e banda de rede. Tambm podem ser observados os
programas que se relacionam com o sistema, como gerenciadores de banco de dados, mquinas virtuais
e servidores de aplicao.
Aps o trmino da simulao, realizada a tarefa de interpretao subjetiva das informaes cole-
tadas, que pode ser feita manualmente ou atravs de scripts que seguem alguma heurstica especializada
para um contexto. Essas informaes so teis para identicar mdulos do sistema que apresentem mau
desempenho sob uso intenso, como, por exemplo, queries que so executadas repetidamente e que pode-
riam ser inseridas em um sistema de cache. As informaes tambm podem indicar partes do hardware
e da infraestrutura que so mais utilizadas pelo software, portanto quais so as mais importantes para a
execuo satisfatria do sistema.
Outra concluso que pode ser obtida com os testes de carga se o sistema e suas dependncias
so escalveis. Se a vazo das requisies apresentar um aumento linear com o tempo, signica que o
sistema escalvel, portanto, possvel melhorar o desempenho do sistema como upgrade da infraestru-
tura. Se a vazo tiver um crescimento exponencial, ou seja, um crescimento relativamente rpido para
poucos usurios e requisies, ento uma indicao que alguma congurao ou algoritmo precisa ser
melhorado.
Uma ferramenta popular de testes de carga a JMeter, que possibilita testar aplicaes Web, bancos
de dados e outros tipos de aplicaes
2
. Com ela ainda possvel criar testes de estresse e longevidade,
que sero descritos a seguir, alm de testes de desempenho. Um exemplo pode ser visto no Apndice A.
Teste de Estresse
Enquanto o teste de carga visa avaliar se a infraestrutura adequada para as expectativas de uso do
sistema, o teste de estresse, tambm conhecido como teste de carga mxima, visa descobrir os limites
de uso da infraestrutura, isto , qual a quantidade mxima de usurios e requisies que o sistema
consegue atender corretamente e em um tempo aceitvel. A anlise dos resultados pode ser feita atravs
de asseres, mas sempre necessrio uma ltima anlise manual dos dados obtidos pelos testes.
Os valores limites obtidos da simulao de estresse so importantes para o gerenciamento e congu-
rao do hardware e do software. Essa simulao aponta quais so os gargalos de hardware que precisam
de upgrade e tambm orienta a congurao do hardware e do software para melhorar o desempenho
2
O autor utilizou a ferramenta JMeter para realizar testes de carga no sistema Janus.
33
ou mesmo para criar barreiras que impeam que a quantidade mxima de requisies extrapole um lim-
ite seguro. Por exemplo, podemos congurar um servidor de aplicaes Web para barrar quantidades
exageradas de requisies para impedir ataques de negao de servio
3
.
3.3.7 Teste de Longevidade
O teste de longevidade tem por objetivo encontrar erros que s so visveis aps um longo tempo de
execuo do sistema. Esse teste importante porque o sistema pode se comportar de maneira errnea
ou ineciente aps dias ou semanas de execuo ininterrupta, mesmo que ele funcione corretamente sob
uso intenso de usurios e requisies em um curto intervalo de tempo. Esses problemas so geralmente
de cache, replicao, da execuo de servios agendados e, principalmente, de vazamento de memria.
A execuo de servios agendados e de replicao so muito suscetveis a erros do ambiente, como
congurao incorreta do hardware e do sistema operacional e tambm problemas de bloqueio e per-
misso em sistemas de arquivos. Alm disso, comum que uma infraestrutura de hardware seja com-
partilhada entre outros usurios e sistemas de software, os quais possuem comportamento desconhecido
que pode afetar o sistema em teste, por isso importante o teste de longevidade para vericar se existe
em algum momento um impacto direto no desempenho e correo da aplicao.
Erros em sistema de cache tambm so mais facilmente observados com o passar do tempo. Os
sistemas de cache podem ser congurados para serem atualizados depois de um longo perodo de tempo,
por exemplo, uma vez ao dia ou depois de uma semana; dessa forma, s conseguiremos vericar se essa
tarefa est sendo executada corretamente aps este perodo. No entanto, esses problemas ainda podem
ser vericados com o auxlio de testes de unidade e Objetos Dubls (vide Seo 6.2), o que no trivial
para os problemas de vazamento de memria.
Vazamento de memria um problema comum a muitos sistemas de software, no s os que so
implementados com linguagens de programao que exigem a criao de destrutores e que no possuem
coleta de lixo automtica (como C++), como tambm em linguagens mais modernas, como Java [30] e
JavaScript. Mesmo um vazamento de memria aparentemente insignicante pode trazer problemas com
o decorrer do tempo, porque a quantidade de memria gasta pode ser multiplicada pela quantidade de
usurios e requisies que pode ser muito grande.
3.3.8 Testes de Segurana
Os testes de segurana servem para vericar se os dados ou funcionalidades condenciais de um sistema
esto protegidos de fraude ou de usurios no autorizados. A segurana de um software pode envolver
aspectos de condencialidade, integridade, autenticao, autorizao, privacidade, entre outros, todos
sujeitos a ter vulnerabilidades por erros de software ou de infraestrutura [145].
Existem diversas ferramentas especializadas em testes de segurana que simulam os ataques mais
comuns de pessoas mal intencionadas. Contudo, as vulnerabilidades tambm podem ser vericadas com
auxlio de ferramentas de testes de interface ou de unidade, que permitem simular o comportamento de
usurios e inserir informaes maliciosas no sistema. Entre os ataques que possvel simular esto os
que se beneciam da falha de converso ou da fraca validao dos dados de entrada do sistema, assim
como os ataques que injetam cdigo malicioso nos servidores e causam estouro de memria.
3.4 Tcnicas de Teste
Na maioria das vezes os testes de software no provam que o sistema est livre de defeitos, justamente
porque os testes no conseguem cobrir a enorme quantidade de possibilidades de entrada e combinaes
3
Ataques de negao de servio (Denial of Service ou simplesmente DoS) so feitos com o envio intenso de requisies
para um mesmo servidor com o objetivo de estressar o sistema a tal ponto que o sistema pare de funcionar.
34
de resultados a que um software pode estar sujeito. Sendo assim, os testes so realizados at que o time,
incluindo desenvolvedores e clientes, esteja satisfeito quanto qualidade do sistema ou de um algoritmo.
Aps a realizao dos testes, podem ser executadas outras tarefas para certicar que o software atende
bem s necessidades, como anlises formais e matemticas ou mesmo a liberao do sistema em verses
alfa e beta para testes em ambiente real com usurios reais.
A regra geral durante a criao dos testes automatizados pensar em parties de domnio ou classes
de equivalncia de um algoritmo, isto , tentar identicar tanto os casos rotineiros, como as situaes
especiais e excepcionais, e, ento, criar um caso de teste para cada uma delas. No entanto, em alguns
casos isso no basta para dar a conana de que est tudo implementado corretamente, por isso existem
outras tcnicas de testes que podem ser utilizadas para complement-los e reforar a conabilidade do
sistema, aumentando as chances de encontrar erros durante a implementao do cdigo, como atravs
de testes aleatrios, fumaa e de sanidade.
Essas tcnicas, as quais tambm so denidas como tipos de testes, no precisam possuir baterias
exclusivas de casos de testes. Por exemplo, no necessrio organizar uma bateria com apenas casos
de testes de sanidade. Se esses testes seguirem as padronizaes e os princpios da bateria, tais como
desempenho e uso de ferramentas especcas, ento eles podem complementar as baterias de testes j
existentes, como a de testes de unidade.
3.4.1 Testes Aleatrios (Random Tests)
Quando no possvel avaliar todas as combinaes de entrada e sada de um algoritmo e h insegurana
quanto sua correo, pode-se realizar testes com dados aleatrios para tentar encontrar cenrios que
no foram previamente identicados. Para criao dos testes aleatrios necessrio que haja um gerador
dos dados de entrada e tambm uma lgica simples de vericao de resultados, que no implemente o
algoritmo identicamente e que faa comparaes exveis para que os testes sejam consistentes, ou seja,
a aleatoriedade dos dados no devem tornar os testes intermitentes.
Na Figura 3.4, h um exemplo de teste aleatrio para as funes seno e cosseno da biblioteca padro
da linguagem Python. impossvel provar que algoritmos implementados para calcular os valores de
seno e cosseno esto corretos com poucos testes e sem uma formulao matemtica. Portanto, podemos
criar um teste aleatrio que faa vericaes pouco especcas, mas que atinja um grande nmero de
casos a cada vez que o teste executado. Nesse exemplo, utilizado uma propriedade trigonomtrica
como artifcio para vericao.
1 import unittest
2 import random
3 import math
4
5 class SenoCossenoTests(unittest.TestCase):
6
7 def test_aleatorio_para_seno_e_cosseno(self):
8 for i in xrange(0, 100):
9 numero_aleatorio = random.randint(100, 100000)
10 resultado_seno = math.sin(numero_aleatorio)
11 resultado_cosseno = math.cos(numero_aleatorio)
12 # verifica a correo por meio de uma propriedade trigonomtrica
13 resultado = math.pow(resultado_seno, 2) + math.pow(resultado_cosseno, 2)
14 self.assertAlmostEqual(1, resultado)
Figura 3.4: Exemplo de teste aleatrio.
importante notar que os testes aleatrios no so preditivos e podem possuir um comportamento
35
intermitente quando h falhas no sistema. Essas duas caractersticas so antipadres de testes automati-
zados em testes rotineiros, por isso importante documentar com nomes claros as variveis e os mtodos
de casos de testes, destacando que o teste aleatrio, pois isso facilita a identicao e compreenso
dos erros nos relatrios dos testes, evitando gastar tempo excessivo com depurao.
3.4.2 Teste de Fumaa (Smoke Tests)
Testes de fumaa so vericaes simples para busca de grandes erros, que geralmente afetam muitas
funcionalidades e so fceis de se detectar. Eles so geralmente executados antes de outras baterias de
testes mais especializadas, pois, se grandes erros forem encontrados, provavelmente uma grande parcela
dos outros cenrios de vericaes tambm ir falhar. Por isso, os testes de fumaa podem economizar
tempo gasto com a execuo de outras baterias de testes e com a identicao das causas dos problemas.
O nome deste tipo de teste deve-se aos testes de fumaa realizados em hardware. Se uma placa de
hardware no pega fogo ou no solta fumaa durante um teste, ento um primeiro indcio que a placa
pode ter sido corretamente produzida. Esse termo tambm utilizado em outras reas do conhecimento,
por exemplo, existem testes de fumaa para vericar a vedao de encanamentos e de instrumentos de
sopro. pressionado uma fumaa atxica dentro dos objetos para vericar se existem rachaduras.
Testes de fumaa so geralmente pouco especcos e muito abrangentes, alm de rpidos de im-
plementar e de executar. Eles so teis para capturar erros grandes, principalmente alguns erros de
congurao e de ambiente que so facilmente detectados aps a instalao do software.
A Figura 3.5 mostra um exemplo de teste de fumaa de interface Web, utilizando a ferramenta
Selenium
4
. Os testes navegam por pginas do sistema e vericam se elas foram encontradas, isto , no
foi exibido o erro 404 do protocolo HTTP
5
.
1 // referncias do TestNG
2 import org.testng.annotations.Test;
3
4 public class PaginasEncontradasTests extends SeleniumTestCase {
5
6 @Test public void visitaPaginaPrincipal() {
7 selenium.open("/");
8 assertFalse(selenium.isTextPresent("404"));
9 }
10
11 @Test public void visitaPaginaInformacoes() {
12 selenium.open("/about");
13 assertFalse(selenium.isTextPresent("404"));
14 }
15
16 }
Figura 3.5: Exemplo de teste de fumaa.
3.4.3 Teste de Sanidade (Sanity Tests)
Testes de sanidade possuem as mesmas caractersticas dos testes de fumaa, isto , so rpidos,
abrangentes e pouco especcos. No entanto, eles so geralmente desenvolvidos para testes de um m-
4
O sistema Janus da Pr-Reitoria de Ps-Graduao da USP, do qual o autor participou do desenvolvimento, possui uma
bateria de testes de fumaa para vericar a existncia de grandes erros no ambiente de produo.
5
Hypertext Transfer Protocol (HTTP): http://en.wikipedia.org/wiki/Hypertext\_Transfer\_Protocol
36
dulo especco. comum utilizar testes de sanidade para vericar algoritmos essencialmente matemti-
cos, onde possvel utilizar certas propriedades matemticas nas vericaes.
1 import unittest
2 import math
3
4 class RaizQuadradaTests(unittest.TestCase):
5
6 def test_sanidade_para_raiz_quadrada(self):
7 # 10^4 < 123456789 < 10^5
8 value = math.sqrt(123456789)
9 self.assertTrue(value > (10**4))
10 self.assertTrue(value < (10**5))
Figura 3.6: Exemplo de teste de sanidade.
O exemplo da Figura 3.6 apresenta um teste simples de sanidade para um mtodo que calcula a raiz
quadrada de um nmero (math.sqrt()). Por alguma razo
6
no sabemos a raiz de 123456789, ento
utilizamos uma propriedade matemtica para fazer as vericaes: se um nmero natural A maior que
um nmero natural B, ento a raiz quadrada de A maior que a raiz quadrada de B. As duas vericaes
feitas so bem abrangentes e no fornecem um indcio forte que o mtodo est correto, apenas informa
que no foi cometido um erro enorme para este caso de teste.
O exemplo de teste aleatrio citado na seo anterior (Figura 3.4) pode ser convertido em um teste
de sanidade, pois ele tambm um teste que faz vericaes abrangentes atravs do uso de propriedades
matemticas. Basta trocar a gerao aleatria dos dados de entrada por valores denidos, como
mostrado na Figura 3.7. Nesse caso, a vantagem sobre o teste aleatrio que ele um teste reprodutvel
e com menos possibilidade de se tornar intermitente, pois h o total controle dos dados de entrada.
1 import unittest
2 import random
3 import math
4
5 class SenoCossenoTests(unittest.TestCase):
6
7 def test_aleatorio_para_seno_e_cosseno(self):
8 for numero_conhecido in xrange(0, 100):
9 resultado_seno = math.sin(numero_conhecido)
10 resultado_cosseno = math.cos(numero_conhecido)
11 # verifica a correo por meio de uma propriedade trigonomtrica
12 resultado = math.pow(resultado_seno, 2) + math.pow(resultado_cosseno, 2)
13 self.assertAlmostEqual(1, resultado)
Figura 3.7: Exemplo de converso do teste aleatrio para teste de sanidade.
3.5 Consideraes Finais
Um sistema de software est sujeito a uma innidade de tipos de erros diferentes, sendo que muitos
deles so recorrentes no desenvolvimento de software. A vericao destes erros deve ser organizada
6
Poderamos calcular em uma calculadora o resultado da raiz de 123456789 para escrever um teste mais especco, mas
s um exemplo simples para apresentar o conceito.
37
e planejada atravs de baterias de testes especializadas e padronizadas para que os testes sejam mais
ecazes e para que a execuo dos testes fornea o feedback apropriado.
A Figura 3.8, criada pelo autor, organiza os tipos de teste de acordo com sua denio e com as
discusses feitas nas sees anteriores. Ela apenas mostra, de uma forma resumida, o relacionamento
dos tipos de teste. Cada crculo representa um conjunto e as interseces representam se existem rela-
cionamentos entre os tipos de teste. Caso um crculo esteja inserido completamente em outro, signica
que so subtipos de tipo de teste representado pelo crculo maior. Por exemplo, teste de carga no possui
qualquer relacionamento com teste de unidade; e teste de estresse um subtipo de teste de carga.
J a Tabela 3.1, tambm criada pelo autor, aponta algumas caractersticas de cada tipo de teste para
comparao e para ajudar no gerenciamento, assim como adaptar e organizar baterias j existentes que
precisam ser refatoradas. No entanto, a tabela est organizada de modo geral, pois as caractersticas de
cada tipo de teste podem variar de acordo com o contexto e com as ferramentas utilizadas.
38
Figura 3.8: Tipos de testes de software.
h
h
h
h
h
h
h
h
h
h
h
h
h
hh
Tipo de Teste
Caracterstica
Especco Abrangente Isolado Integrado Lento
Unidade o o
Integrao o o
Interface de Usurio o o o o
Aceitao o o o
Desempenho o o o
Carga o o o
Estresse o o o
Longevidade o o o
Segurana o o
Tabela 3.1: Caractersticas dos tipos de testes.
39
40
Captulo 4
O Processo de Automao de Testes
At o momento vimos que alguns dos problemas dos testes automatizados so intrnsicos de cada tipo
de teste. Entretanto, outras diculdades podem ser causadas simplesmente pelo desconhecimento de
boas prticas de organizao de um projeto com automao de testes. Por isso, esse captulo discute e
recomenda formas de se trabalhar para aumentar a produtividade.
4.1 Viso Geral
Os testes automatizados afetam diretamente a qualidade dos sistemas de software, portanto agregam
valor ao produto nal, mesmo que os artefatos adicionais produzidos no sejam visveis para os usurios
nais do sistema. Mas, como qualquer artefato, o cdigo-fonte dos testes automatizados e os documentos
e relatrios gerados requerem qualidade e capricho para que a evoluo e manuteno seja vivel, com
custo de trabalho linear ou mesmo constante, ou seja, que no aumente radicalmente sua complexidade
medida que o projeto evolui.
necessrio que tambm haja preocupao com a qualidade do cdigo-fonte dos testes, pois eles
tambm esto sujeitos problemas similares que podem ocorrer com o software em teste. Consequente-
mente, diversas tarefas de manuteno de cdigo do sistema tambm so aplicadas ao dos testes, tais
como evoluo, refatorao e otimizao [143]. Tudo isso para obter e manter a correo, legibilidade,
modularizao coesa e desempenho, que so algumas das caractersticas bsicas para uma boa bateria
de testes automatizados [76].
Parece no fazer sentido adicionar um artefato sujeito a erros para controlar a qualidade do sistema,
e tambm dedicar uma grande porcentagem do trabalho para algo que tambm precisa de um esforo
para garantir qualidade e que no ser explicitamente visvel para os usurios nais. Entretanto, o
principal aspecto que traz coerncia para a prtica de testes automatizados a simplicidade: testes
automatizados devempossuir umcdigo-fonte trivial, que seja fcil de implementar e de entender. Dessa
forma, a chance de introduzir erros relativamente pequena. Outro aspecto complementar que um
erro introduzido nos testes geralmente fcil de ser identicado em tempo de implementao, pois a
execuo do teste tende a falhar, se ele no falhar porque houve uma replicao do erro no cdigo do
sistema. Essa redundncia de trabalho entre cdigo do sistema e cdigo dos testes cria duas frentes de
busca de erros e traz mais segurana para escrita do sistema e dos testes.
4.2 Quem Deve Implementar
A criao dos testes automatizados pode exigir conhecimento de programao, de testes de software,
da linguagem de negcio e de ferramentas especcas. Portanto, podem ser necessrio prossionais
qualicados para a realizao dessa tarefa. Entre os prossionais com estas qualicaes, geralmente
41
esto os desenvolvedores, testadores ou analistas de qualidade, mas tambm clientes e usurios nais
podem colaborar com esta tarefa.
O que deve ser considerado em primeiro lugar o tipo de teste a ser realizado (vide Figura 3.8),
pois alguns deles requerem conhecimentos completamente especcos, entretanto, para todos eles
necessrio um conhecimento geral de diversas reas. Devido abrangncia de conhecimento necessrio
para a criao de testes, no recomendado responsabilizar apenas um grupo de pessoas com con-
hecimentos especcos pela qualidade do sistema. Por isso, os mtodos geis sugerem disseminar a
preocupao pela qualidade entre todos os membros do time. Assim, todos devem trabalhar colaborati-
vamente para agregar seus conhecimentos para o objetivo nal que comum a todos da equipe: produzir
um sistema de software de qualidade.
No entanto, trabalhar colaborativamente no signica que todos os prossionais iro realizar tarefas
semelhantes, apenas que dever haver uma integrao das ideias. Para que esta troca de informaes
seja efetiva, sempre necessrio uma boa comunicao, transparncia e clareza das informaes, que
podem ser obtidas com a ajuda de reunies frequentes, reas de trabalho informativas e uso de metforas
comuns a todos membros da equipe.
De forma geral, os testes de unidade, mutao e de integrao de mdulos devem ser implementados
com a ajuda principalmente de desenvolvedores e testadores. Os testes de interface grca (incluindo
usabilidade, acessibilidade e leiaute) e de aceitao devem ter participao de todos os membros da
equipe, principalmente dos clientes e dos usurios nais porque o sistema deve atender s suas necessi-
dades apropriadamente. J os testes de desempenho, carga, estresse, longevidade e segurana podem ser
realizados por prossionais especializados, dado que as tarefas costumam ter uma certa independncia
e um padro a ser seguido, mas tambm fundamental a comunicao para concentrar os testes nas
principais reas do sistema.
4.3 Quando Implementar
Projetos que seguem metodologias tradicionais, derivadas do modelo de cascata, tendem a ter uma
equipe de testadores especializados e analistas de qualidade que realizam testes manuais no m de uma
jornada de implementao. Como sugerido pelos mtodos geis, esta organizao no ecaz porque
o feedback obtido dos testes no facilmente e rapidamente aproveitado, pois, geralmente, necessrio
um rduo trabalho de depurao e de reorganizao do cdigo.
Automatizar os testes no m das iteraes tambm no a melhor estratgia, porque um dos princi-
pais benefcios dos testes automatizados, que a segurana contra erros de regresso, no aproveitado
durante todo o desenvolvimento. Em suma, os testes nais passam a ter um custo de implementao
maior que dos testes manuais e pode existir a compensao do tempo gasto com os benefcios da au-
tomao.
Para valer a pena, a automao dos testes, necessrio que eles sejam implementados o quanto antes
para fornecer feedback em tempo de implementao, pois quanto mais cedo uma falha detectada, mais
fcil ser corrigi-la. Fazer alteraes pontuais nas funcionalidades que esto sendo implementadas
mais rpido porque estamos com grande parte do cdigo-fonte em nossa memria recente, dispensando
um estudo adicional para lembrar e entender o cdigo j existente.
Contudo, fundamental estabelecer as prioridades dos tipos de testes necessrios, considerando o
valor que ser agregado ao produto nal. A primeira premissa bsica da qualidade de todo sistema de
software a aceitao do cliente, isto , devemos implementar o que foi pedido. A segunda premissa
bsica a correo, se o software no est correto, os resultados dos outros testes se tornam no con-
veis. Depois destas premissas estarem asseguradas podemos pensar na prioridade de outros aspectos
de qualidade, como desempenho, segurana, beleza e usabilidade. Estas prioridades variam de sistema
para sistema, pois devem ser consideradas detalhes das tecnologias utilizadas, o tipo de software, o
contexto da aplicao e o pblico-alvo.
42
Considerando apenas as caractersticas fundamentais de qualidade (aceitao e correo), o ideal
criar os testes em fase de implementao, particularmente em alguns momentos especiais como antes
mesmo da prpria implementao do sistema, como sugerido pelas tcnicas de Testes a Priori e De-
senvolvimento Dirigido por Testes que sero discutidas no Captulo 9. De forma geral, recomendado
que os testes sejam escritos nas seguintes situaes.
Antes de escrever o cdigo: Evita que os testes sejam deixados de lado, favorece a escrita de testes
simples e tambm inuencia o design da aplicao para ser testvel.
Durante a implementao: Os testes ajudam a renar o design do sistema e at implementar algorit-
mos.
Quando um erro for encontrado: Se um erro foi encontrado quer dizer que o cenrio no foi testado,
ento antes da correo pode ser criado um teste que o simule. Com esse teste teremos segurana
que o problema no reaparecer em futuras modicaes do cdigo.
Quando um teste de aceitao falha: um erro de algum mdulo que propagado por entre as ca-
madas do software, por isso um indcio de que falta um caso de teste de unidade ou de integrao
para algum mdulo do sistema.
Quando um usurio ou cliente encontra um erro: Pode ser um sinal que estejam faltando testes de
unidade e de aceitao. A criao desses testes especialmente til para evitar que ele reaparea,
o que pode tornar a situao ainda mais constrangedora.
4.4 Onde Executar
Com os testes implementados, o prximo passo denir onde eles sero executados. Cada tipo de
teste possui restries prprias relacionadas ao ambiente, mas o que todos tm em comum que podem
depender da exibilidade e portabilidade das tecnologias utilizadas e tambm podem ser inuenciados
por fatores externos, sejam eles de software ou hardware.
Os testes de desempenho, carga, estresse e longevidade requerem idealmente que a infraestrutura
seja a mais parecida com o ambiente real de produo, incluindo conguraes de hardware, sistema
operacional e tambm os processos que so regularmente executados na infraestrutura, isto porque os
resultados obtidos esto diretamente relacionados com o ambiente. Os testes de segurana tambm
dependemda infraestrutura, pois pode haver vulnerabilidades no ambiente que expemmdulos restritos
do software, assim como os testes de usabilidade e leiaute que dependem do desempenho do sistema.
J os testes de correo (unidade, integrao, aceitao etc.) no devem possuir uma dependncia
to rgida quanto ao tipo e congurao do hardware e da infraestrutura. Essa exibilidade necessria
para que os testes sejam executados tanto em mquinas de desenvolvimento como em servidores de
integrao contnua, assim como em outros ambientes que sejam necessrios.
Contudo, nem sempre possvel criar baterias de testes completamente compatveis com diferentes
tipos de ambientes. Ambientes compartilhados, controlados (de homologao ou de controle de quali-
dade) e isolados requerem mudanas signicativas na implementao do cdigo dos testes.
Ambiente compartilhado de testes utilizado por diversos projetos e times de desenvolvimento, alm
de diferentes reas de uma organizao. Ele geralmente semelhante ao ambiente real de produo para
tornar o ambiente de teste o mais prximo do real. Devido ao alto custo destes ambientes, pode ser
invivel possuir um por projeto, por isso a soluo compartilhar um entre todas as equipes.
A escolha destes ambientes favorecida principalmente quando a infraestrutura complexa de ser
criada e congurada, pois minimiza a quantidade de ambientes que precisaro de manuteno. Por
exemplo, trabalhoso lidar com ambientes onde h um grande conjunto de servidores de aplicaes e
gerenciadores de banco de dados distribudos.
43
Portanto, estes ambientes compartilhados devem ser evitados porque a falta de controle do ambiente
por parte dos testes acarreta em diversos antipadres nas baterias de testes, como desempenho ruim,
cdigo pouco legvel e difcil de manter.
O que favorece a escrita de testes de qualidade ter um ambiente de teste controlado, sobre o qual
eles podem fazer diversas suposies de forma a diminuir o cdigo-fonte e melhorar o seu desempenho.
Estes ambientes podem at ser compartilhados, mas deve existir uma organizao entre os projetos que
o utilizam a m de criar um certo nvel de isolamento para os testes. No entanto, muitas vezes isso nem
sempre possvel porque os testes e projetos podem ser conitantes dentro de um mesmo ambiente,
a tal ponto que se torna impossvel organizar de maneira efetiva todas as equipes. Por exemplo, se
um projeto executar um teste de longevidade no ambiente, a infraestrutura pode car inadequada por
um longo perodo de tempo para os outros projetos. Outro problema a falta de autonomia dos testes
para congurar o ambiente apropriadamente, o que pode impossibilitar a criao de casos de testes
importantes.
Assim, mesmo que apenas um projeto utilize o ambiente, ele tambm ser compartilhado entre
os desenvolvedores de um mesmo time, portanto, a execuo dos testes de um desenvolvedor pode
inuenciar a execuo de outro. Logo, o mais adequado para a realizao rotineira dos testes de correo
aquele completamente isolado e independente, pois facilita a escrita dos testes e dispensa a negociao
do ambiente com outros desenvolvedores e times que podem ter prazos e objetivos conitantes.
Um ambiente isolado pode ser o prprio computador de cada desenvolvedor ou testador, isto , a
mquina local, pois geralmente existe mais autonomia para instalar e congurar programas da forma
que se desejar. Tambm pode haver mquinas dedicadas para isso sem a exigncia de imitar o ambiente
de produo, onde podem ser instalados programas de integrao contnua [52] para executar as baterias
de testes desejadas, inclusive com agendamentos de horrios. Para vericar os casos de testes que
requerem o ambiente parecido com o de produo, pode ser criado uma bateria de testes exclusiva e
isolada que sero executados em ambientes compartilhados.
Para quando houver problemas com desempenho devido grande quantidade de testes, pode ser
necessrio paralelizar a execuo dos testes, por exemplo atravs de grades computacionais. A ferra-
menta Selenium Grid, por exemplo, facilita a criao de uma grade computacional para execuo dos
testes Web criados com a ferramenta Selenium.
Quando houver necessidade de testar um programa em diversos sistemas operacionais, navegadores
Web ou ainda com diferentes conguraes de hardware, ser necessrio criar ambientes com cada uma
das exigncias. Uma alternativa com baixo custo a criao e congurao de mquinas virtuais com o
auxlio de emuladores prprios como o VMware, o VirtualPC ou o VirtualBox que permitem a emulao
de mquinas com caractersticas diferentes de hardware e com sistemas operacionais desejados, alm da
possibilidade de instalao de qualquer sistema de software compatvel.
4.5 Quando Executar
Uma grande vantagem da automao de testes em relao a fazer testes manuais que eles podem ser
reproduzidos identicamente a qualquer momento e sem custos adicionais relevantes. Essa possibilidade
proporciona rpido feedback a todo momento que novos resultados so obtidos. Por isso, o recomendado
executar os testes o mais rpido possvel aps qualquer alterao que possa inuenciar a execuo do
programa, como as de cdigo e de congurao, atualizaes de dependncias ou mesmo mudanas na
infraestrutura.
No entanto, alguns tipos de testes no podem ser executados a todo momento porque so intrinseca-
mente lentos, como os testes de desempenho e longevidade. Testes de segurana e usabilidade tambm
podem ser indesejavelmente lentos, dependendo das vericaes e das ferramentas utilizadas. Outros
tipos de teste no precisam ser executados a todo momento, como os de carga e estresse, pois avaliam a
infraestrutura que geralmente no alterada com frequncia. Dessa forma, esses tipos de testes podem
44
ser agendados para serem executados em dias e horrios especcos, denidos de acordo com prazos de
entregas e outras necessidades.
Os tipos de testes com maior prioridade so os de aceitao e de unidade, que so focados nos aspec-
tos bsicos de qualidade: aceitao e correo. O feedback destes tipos de testes so os mais valiosos em
tempo de implementao porque eles permitem revelar com rapidez erros nas novas funcionalidades e
erros de regresso. A frequncia de alteraes no cdigo-fonte pode ser alta, podendo chegar a dezenas
de linhas modicadas por minuto, todas sujeitas a falhas.
Idealmente, os testes de unidade devem ser rpidos porque a sua quantidade pode ser muito grande.
O cdigo-fonte dos testes de unidade pode at ser mais extenso que o prprio sistema em teste, isto
porque para cada mtodo da aplicao podem haver dezenas de mtodos de teste. Com cada caso de
teste demorando milsimos de segundo para ser executado, torna-se vivel a execuo de todos os testes
a cada alterao do cdigo-fonte.
O malefcio de no executar os testes a cada alterao do cdigo que os erros se acumulam, o que
torna mais lenta a compreenso e identicao dos erros, podendo at atrasar o projeto como um todo.
Para evitar que isso acontea e para poupar o trabalho repetido de executar a bateria de testes, foram
criadas ferramentas de Testes Contnuos (Continuous Testing) [124], que detectam quando o cdigo-
fonte foi alterado e executam a bateria de testes automaticamente.
Os testes de aceitao so geralmente demorados, porque eles devem integrar todas as camadas do
sistema, incluindo algoritmos e processos lentos e camadas de persistncia, como banco de dados e
sistemas de arquivos. Por isso, pode ser invivel execut-los com a frequncia dos testes de unidade,
mas devem ser realizados pelo menos uma vez ao dia, por exemplo, em um ambiente de integrao
contnua [52].
Os ambientes de integrao contnua so fundamentais para os projetos desenvolvidos com mtodos
geis porque possibilitam a criao de releases dirios, tambm conhecidos como snapshots ou nightly
builds. Com estes programas possvel automatizar o processo inteiro de construo do software, in-
cluindo a compilao, ligao de dependncias e execuo de diversas baterias de testes. A construo
pode ser programada para ser executada emhorrios especcos, preferencialmente quando os ambientes
no esto sendo utilizados, dessa forma, h a segurana de que as baterias de testes sero executadas fre-
quentemente. Existem ferramentas que facilitam a criao desses ambientes e dessas conguraes, tais
como CruiseControl e Continuum.
O que importante notar que executar os testes com frequncia fundamental. mais vantajoso
executar frequentemente uma bateria pequena de testes do que executar raramente uma bateria grande
de testes. Baterias de testes que no so executadas tendem a car desatualizadas, o que pode reduzir
drasticamente o custo-benefcio da automao de testes.
O custo da criao dos testes automatizados geralmente maior do que o dos testes manuais, justa-
mente por causa do tempo utilizado coma implementao. Por isso, necessrio que este custo adicional
seja compensado com os benefcios da automao, como a possibilidade de execuo de baixo custo da
bateria completa de testes, que auxilia o desenvolvimento e evita o desperdcio de tempo gasto com a
depurao dos sistemas.
Alm disso, as baterias de testes que no so executadas regularmente tendem a se tornar obsole-
tas, caso o sistema em teste continue em desenvolvimento. A manuteno do sistema pode alterar o
design do cdigo-fonte e at mesmo o comportamento do sistema. Dessa forma, os testes podem no
vericar mais o comportamento esperado do sistema e at mesmo no compilar. Tambm importante
notar que quanto maior for o acmulo de casos de testes obsoletos, mais desgastante ser o trabalho de
identicao dos erros, j que cada um deles pode inuenciar de diferentes maneiras os casos de teste.
45
4.6 Documentao
Metodologias tradicionais de desenvolvimento do grande nfase a documentos, tanto referentes ao soft-
ware quanto ao processo de desenvolvimento. Por outro lado, os mtodos geis recomendam priorizar a
colaborao com o cliente em vez de organizar o processo de desenvolvimento atravs de documentos
burocrticos. A comunicao rpida e efetiva dispensa documentos longos e detalhados, que requerem
muito esforo para se manterem atualizados e no agregam mais valor que um software de qualidade.
Com os mtodos geis, os requisitos so organizados em pequenas histrias, contendo informaes
enxutas que direcionam o desenvolvimento.
Os testes de aceitao visam averiguar se as histrias esto implementadas como o esperado. Atravs
de uma linguagem prxima da natural, o cliente descreve exemplos de uso das funcionalidades do sis-
tema e os comportamentos esperados. Exemplos compem uma documentao efetiva que podem acel-
erar o aprendizado do sistema, pois ele apresenta de forma prtica e objetiva como o sistema deve ser
usado.
Por isso, os testes de aceitao podem e devem ser utilizados como um artefato de documentao
executvel do sistema, tanto para os prprios clientes e usurios nais quanto para os desenvolvedores.
A maior vantagem dessa documentao que ela se autoverica dinamicamente, se est atualizada, a
cada vez que a bateria de testes executada, ou seja, se um teste falhar um indcio de que ou aquele
trecho da documentao est obsoleto ou ento o sistema no satisfaz um certo requisito.
Outro tipo de documentao de sistemas de software so os artefatos destinados ao usurio nal, tais
como screencasts, tutoriais, FAQs
1
, manuais de usurio e documentao de APIs
2
, no caso de bibliote-
cas de software. Esses artefatos so indispensveis em qualquer metodologia de desenvolvimento, pois
esto diretamente relacionados com a usabilidade do sistema e com aspectos de mercado e divulgao.
No entanto, trabalhando com mtodos geis, esses artefatos podem ser gerenciados como as funcional-
idades, isto , cada tarefa relacionada com esse tipo de documentao pode entrar em uma pilha de
tarefas para serem priorizadas. No obstante, as tarefas de documentao podem at serem priorizadas
na mesma pilha de tarefas de funcionalidades, j que este tipo de documentao tambm agrega valor
diretamente ao produto nal.
Tambm pode ser interessante utilizar os testes de interface como parte da documentao do usurio
nal, j que muitas ferramentas permitem visualizar os eventos simulados de dispositivos como mouse e
teclado, ou seja, os testes podem servir de demonstrao de uso do sistema. semelhante a um screen-
cast, com as vantagens de ser facilmente editado e de consumir consideravelmente menos memria de
armazenamento. A desvantagem que no vivel fazer edies mais elaboradas, como adio de
udio, narrao e efeitos.
Mais um tipo de documentao tpica em sistemas de software a do cdigo-fonte, direcionada
aos desenvolvedores e outros membros da equipe de desenvolvimento. Esta documentao pode conter
diagramas, textos explicativos e tambm comentrios diretamente no cdigo-fonte, sendo que alguns
deles podem at ser interpretados por ferramentas que geram relatrios organizados para documentao,
tais como o Javadoc
3
.
O que pode complementar a documentao so os relatrios de alguns tipos de testes, como os
de unidade e integrao, pois eles fornecem diversos exemplos de casos de sucesso e de fracasso que
determinados trechos do cdigo estariam sujeitos. Em algumas situaes, pode at ser mais fcil en-
tender um algoritmo a partir de exemplos do que a partir de uma descrio detalhada. Contudo, para
que os relatrios e at o cdigo dos testes possam ser utilizados como documentao, necessrio que
o cdigo esteja muito bem escrito, modularizado e com tima legibilidade, por isso importante dar
nomes coerentes e autoexplicativos para classes, mtodos e variveis.
1
FAQ: Frequently Asked Questions contm uma lista de respostas das perguntas mais frequentes.
2
API: Application Programming Interface ou Interface de Programao de Aplicaes.
3
Ferramenta para gerar documentao de APIs em HTML.
46
Os relatrios dos testes automatizados, que so gerados automaticamente, tambm tm outra utili-
dade: eles podem ser usados como uma certicao de qualidade, j que um documento que apresenta
todos os casos de testes dos quais o software foi submetido. Com os testes manuais necessrio criar ou
alimentar com dados estes documentos manualmente, ou seja, mais um trabalho que pode exigir grande
esforo e que difcil de ser reaproveitado e mantido atualizado.
4.7 Consideraes Finais
Testes automatizados uma prtica muito efetiva para aumentar a qualidade dos sistemas de software,
mas desde que eles tambm sejam de qualidade. O cdigo do teste precisa ser organizado, legvel e ter
um bom desempenho. Para isso, eles devem ser implementados com o mesmo cuidado e ateno do
cdigo do sistema principal.
A qualidade de um projeto no deve ser responsabilidade apenas de alguns membros da equipe. A
qualidade precisa estar disseminada entre todas as pessoas envolvidas; todas devem ser responsveis por
ajudar no que estiver a seu alcance para a produo de um software de excelente nvel. Dessa forma,
gerentes, desenvolvedores, designers, testadores, analistas, clientes e usurios nais devem contribuir
para a criao de baterias de testes boas e completas.
Os testes devem ter alta prioridade durante o desenvolvimento para que eles sejam implementados o
mais breve possvel, pois quanto o feedback rpido facilita e agiliza a tarefa de melhoria do sistema. Os
testes de correo (unidade e aceitao) devem ser implementados concorrentemente com o cdigo do
sistema, enquanto outros tipos de testes podem ser implementados quando houver necessidade, depen-
dendo dos problemas do software e dos objetivos do projeto.
As baterias de testes devem ser executadas idealmente em ambientes isolados e controlados para
facilitar a escrita e manuteno dos testes. Quando no existe total autonomia do ambiente, os testes
precisam prever diferentes situaes que aumentam a complexidade do cdigo-fonte e podem atrapalhar
a execuo, diminuindo o desempenho ou at mesmo quebrando os casos de teste, impossibilitando
interpretar com delidade os resultados obtidos.
Para facilitar o desenvolvimento do sistema e dos testes, a execuo das baterias de vericaes deve
ser a mais frequente possvel, principalmente no que diz respeito aos testes de unidade e de aceitao,
que so os mais especializados para garantir a correo do sistema. Se a frequncia de execuo das
baterias de testes pequena, os erros se acumulam, o que pode dicultar a compreenso dos relatrios e
tornar o processo de manuteno muito desgastante.
Ainda, tanto o cdigo dos testes quanto os relatrios gerados nas execues so artefatos teis para
documentao do sistema, tanto para desenvolvedores, quanto para clientes e usurios nais. Os testes
so exemplos de uso do sistema, que um tipo prtico e ecaz de documentao.
47
48
Parte II
Prticas, Padres e Tcnicas para Testes
de Correo
49
Captulo 5
Introduo da Parte II
Como foi discutido na Parte I, testes automatizados fazem parte de uma abordagem de controle de qual-
idade simples e que pode ser ecaz e de baixo custo. Por estas caractersticas, ela indicada para com-
plementar o controle de qualidade de qualquer projeto de software, desde simples scripts at sistemas
onde no so tolerveis erros, como sistemas mdicos, pilotos automticos de avies e de controladores
de voo.
No entanto, assim como qualquer trecho de cdigo de computador, os testes automatizados tam-
bm esto sujeitos a erros, desde pequenas imperfeies at falhas graves. O cdigo dos testes pode
ser denido segundo alguma linguagem de programao ou mesmo descrito atravs de linguagens de
marcao, como HTML. Geralmente ele criado por um ser humano, mas h situaes onde o cdigo
gerado por alguma ferramenta, o que tambm suscetvel a erros.
Por isso, a escrita e a manuteno dos testes automatizados requer muitos cuidados, pois testes no
ecazes ou que exigem alta manuteno resultam em desperdcio de tempo e, consequentemente, po-
dem acarretar grandes prejuzos. Nesta parte da dissertao, ser discutido o conceito de qualidade na
automao de testes, destacando boas prticas, padres e tcnicas para criao de bons testes automati-
zados de correo.
Primeiramente, esse captulo discutir o que um bom teste de correo, mostrando as principais
caractersticas que um teste precisa ter para que ele seja considerado de qualidade. Na sequncia, sero
apresentados indcios de problemas, descritos por Meszaros como cheiros (smells) [99]. Para completar,
ser feito um paralelo entre os indcios de problemas e as caractersticas de qualidade. Ainda nesse
captulo, sero denidos os esqueletos dos padres e antipadres que aparecero no decorrer desta parte
da dissertao.
Nos trs captulos seguintes, Captulos 6, 7 e 8, sero apresentados padres e boas prticas de imple-
mentao de Testes de Unidade, Testes com Persistncia de Dados e Testes de Interface de Usurio,
respectivamente. Cada um desses captulos possui uma introduo que discute as principais prticas
que devem ser consideradas para a automao. Posteriormente, sero apresentados padres especcos
para tornarem os testes mais organizados e robustos, alm de favorecer a escrita de sistemas com maior
testabilidade e qualidade. Por ltimo, sero descrito antipadres, com o objetivo de serem evitados.
Para nalizar essa parte, o Captulo 9 ir discutir as Tcnicas de Desenvolvimento de Software
com Testes Automatizados, tais como TFD, TDD, e BDD. Cada tcnica pode inuenciar diretamente
na qualidade dos testes e do sistema.
5.1 Testes de Correo de Qualidade
No decorrer desta parte da dissertao sero apresentadas boas prticas para criao de bons testes
automatizados de correo. Contudo, para um bom entendimento dos captulos a seguir, necessrio
conhecer as principais caractersticas que denem a qualidade desse tipo de testes.
51
Sendo assim, a seguir sero descritas as principais propriedades de um bom conjunto de testes au-
tomatizados de correo. Elas foram reunidas a partir de trabalhos de diferentes autores [71, 99, 97]
referente principalmente a testes de unidade. No entanto, a argumentao a seguir foi generalizada
para qualquer tipo de testes de correo, incluindo testes com persistncia de dados e com interface de
usurio.
Automtico: Deve ser possvel executar as baterias de testes sem qualquer interveno humana. Essa
propriedade fundamental para viabilizar o uso de ferramentas de integrao contnua e de testes
contnuos.
Repetitvel: Mtodos de set up e tear down, ou outras funcionalidades dos arcabouos, devem garantir
que os testes possam ser executados quantas vezes forem necessrias, de tal forma que sempre
produzam os mesmos resultados. Em outras palavras, o nmero de vezes que um teste executado
no deve interferir nos resultados dos testes. Essa caracterstica pode ser difcil de ser assegurada
quando os algoritmos trabalham com datas e horrios ou com persistncia de informaes, tais
como bancos de dados e objetos Singleton.
til: O propsito dos testes deve ser vericar algo de importante no sistema. Testes realizados ir-
responsavelmente apenas para melhoria de mtricas do projeto devem ser rejeitados. Ainda, o
custo-benefcio de um caso de teste deve ser baixo, o que no acontece com testes replicados,
semi-automatizados, frgeis ou que exigem muita manuteno.
nico: Cada caso de teste deve vericar um comportamento especco do sistema ou utilizar uma
partio de domnio de dados de entrada. Testes que no agregam valor ao processo de controle
de qualidade prejudicam as baterias de testes como um todo, pois deixam-nas mais lentas e mais
extensas, o que piora a legibilidade e a manutenibilidade.
Preciso: O resultado do teste no pode ser ambguo, ou seja, no deve haver falso positivo ou falso neg-
ativo (Captulo 3.2). Para assegurar esse aspecto, devem ser evitados testes com lgica condicional
ou com muitos pontos de vericao.
Prossional: A qualidade e a organizao do cdigo-fonte dos testes deve ser a mesma do cdigo-
fonte de produo para prevenir erros e facilitar a manuteno. Refatorao e Padres de Projeto
tambm podem ser aplicado ao cdigo dos testes.
Legvel e Claro: O cdigo dos testes deve ser o mais prximo da linguagem natural quanto possvel,
dessa forma, eles podero ser utilizados como uma boa documentao do sistema. Para isso,
essencial utilizar nomes auto-explicativos de variveis, mtodos e classes.
Simples: A criao e manuteno de um caso de teste deve ser uma tarefa sem grandes diculdades.
Para isso, fundamental o uso de arcabouos e ferramentas de testes adequadas para que o teste se
torne o mais simples possvel. No obstante, essa caracterstica tambm depende da testabilidade
(Seo 10.3) do sistema em teste.
Independente: Os casos de testes devem ser independentes uns dos outros. A ordem de execuo dos
casos de testes no deve interferir no resultado dos testes. Ainda, deve ser possvel executar dois
ou mais testes em paralelo sem qualquer interveno. A execuo em paralelo se torna mais
complicada quando so utilizados recursos compartilhados, tais como gerenciadores de banco de
dados.
Isolado: Cada caso de teste deve vericar apenas um aspecto do sistema, para isso, quanto mais isolado
ele estiver de outros mdulos do sistema e do ambiente, mais fcil ser sua escrita e manuteno.
O ambiente em questo pode ser a infraestrutura de rede, dispositivos de hardware, Internet,
52
servios externos etc. Quando um caso de teste depende do ambiente, a execuo do teste ca
mais suscetvel a erros, pois ele depende de conguraes externas que esto fora de seu controle.
A congurao do ambiente se torna especialmente complexa quando os servios so de respon-
sabilidade de outras equipes de desenvolvimento ou at mesmo de outras empresas. A soluo
simular os servios externos com auxlio de Objetos Dubls (Seo 6.2), dessa forma, se um teste
falhar, o motivo do erro tende a ser facilmente identicado.
Rpido: O desempenho dos testes importante, contudo, no necessrio otimizaes exageradas no
cdigo dos testes. O recomendvel separar os casos de testes que so intrinsicamente lentos em
baterias de testes especcas, dessa forma ca mais fcil organizar quando as baterias de testes
devero ser executadas. Comumente, testes de unidade devem ser executados em poucos milis-
segundos, enquanto testes que envolvem persistncia ou interfaces de usurios so normalmente
mais lentas, podendo durar at alguns poucos segundos.
5.2 Indcios de Problemas
Testes automatizados que no possuem as caractersticas descritas na seo anterior podem trazer
grandes prejuzos para um projeto, como perda de tempo e dinheiro. Em casos extremos, o tempo
gasto para a automatizao dos testes pode no ser recompensada pela melhoria da qualidade do sistema
em teste. Por isso, importante identicar o mais breve possvel os problemas das baterias de testes,
caso existam.
Os tipos de problemas das baterias dos testes so comuns a diferentes projetos, assim como os
problemas rotineiros dos sistemas de software. Da mesma forma que Martin Fowler nomeou e descreveu
alguns dos principais indcios de problemas de software (smells), que podem ser solucionados atravs de
refatoraes [59], Meszaros [99] fez o mesmo relacionado com os problemas da automao dos testes.
Abaixo seguem os indcios de problemas descritos por Meszaros, que os organizou em trs catego-
rias: indcios de problemas de cdigo-fonte, de comportamento e de projeto. Os indcios apenas sero
citados com uma breve descrio, j que o prprio nome dos indcios so intuitivos.
Indcios de Problemas de Cdigo-Fonte (Code Smells)
Teste Obscuro (Obscure Test) Testes muito complexos, pouco legveis ou que vericam muitos aspec-
tos do sistema de uma s vez. Testes obscuros dicultam o entendimento e a manuteno.
Testes com Lgica Condicional (Conditional Test Logic) Testes que possuem comandos condicionais
para conseguirem lidar com diversas situaes do ambiente. Normalmente, isso deve-se incor-
reta utilizao de mtodos de set up e tear down, ou a classe de testes est muito extensa.
Cdigo Difcil de Testar (Hard-to-Test Code) Sistema com baixa testabilidade tornam os testes dif-
ceis de serem automatizados (Seo 10.3), consequentemente, os testes tendem a car obscuros.
Replicao do Cdito dos Testes (Test Code Duplication) Replicao do cdigo dos testes pode sig-
nicar que o cdigo de produo tambm est replicado ou que preciso refatorar o cdigo dos
testes.
Lgica dos Testes em Produo (Test Logic in Production) Ocorre quando parte do cdigo dos testes
incorporada ao cdigo do sistema em teste. O objetivo dos arcabouos de testes justamente
facilitar a escrita dos testes de forma completamente isolada.
53
Indcios de Problemas de Comportamento (Behavior Smells)
Erros no Claros (Assertion Roulette) Ocorre quando necessrio muita depurao para identicar o
motivo da falha de um teste. Isso rotineiro quando um teste faz muitas vericaes ou quando
no so precisos, ou seja, possuem resultado falso positivo ou falso negativo.
Testes Intermitentes (Erratic Test) Quando um teste no completamente independente dos outros
ou de fatores externos, eles podem produzir resultados inesperados, dessa forma no so testes
reprodutveis.
Testes Frgeis (Fragile Test) Testes que param de funcionar por causa de mudanas insignicantes no
sistema em teste, tais como adio de novos casos de testes ou pequenas mudanas no leiaute da
interface de usurio.
Depurao Frequente (Frequent Debugging) Se um desenvolvedor est perdendo muito tempo com
depurao, um sinal de que testes automatizados esto faltando ou ento que os testes no esto
claros.
Interveno Humana (Manual Intervention) Testes que so semi-automatizados, isto , depende de
um ser humano para enviar informaes ao sistema para que ento o teste possa proceder.
Testes Lentos (Slow Tests) Testes que so intrinsicamente lentos ou que no so bem isolados.
Indcios de Problemas de Projeto (Project Smells)
Testes com Erro (Buggy Tests) Assim como o cdigo do sistema em teste, o cdigo dos testes tambm
podem ter erros. Normalmente isso ocorre quando a criao dos testes no uma tarefa trivial.
Desenvolvedores no Escrevem Testes (Developers Not Writing Tests) Quando o prazo de entrega
est curto, o mais natural sacricar o tempo gasto com a escrita dos testes automatizados, con-
sequemente, o tempo gasto com a qualidade do sistema.
Alto-custo de Manuteno (High Test Maintenance Cost) Baterias de testes de baixa qualidade ex-
igem um alto-custo de manuteno.
Erros em Produo (Production Bugs) Erros em produo um indcio de que alguns comportamen-
tos do sistema no foram vericados, portanto, h falta de testes automatizados.
Indcios de Problemas vs. Caractersticas de Qualidade dos Testes
Tendo o conhecimento das principais caractersticas de qualidade dos testes e dos indcios de problemas
mais rotineiros no desenvolvimento com testes automatizados, possvel fazer um paralelo entre eles
para ajudar na manuteno e gerenciamento das baterias de testes.
A Tabela 5.1, criada pelo autor, apresenta quais aspectos de qualidade devem ser primeiramente
questionados quando so encontrados alguns dos indcios de problemas citados. Ainda, a tabela pode
ser usada de maneira inversa, dado que queremos assegurar determinada caracterstica de qualidade dos
testes, podemos vericar prioritariamente os indcios de problemas mais provveis.
5.3 Denio de Padro
Padres descrevem solues comuns para problemas recorrentes no desenvolvimento de sistemas de
software. Esse termo foi aplicado em Cincia da Computao pela primeira vez com os Padres de
Projeto de sistemas orientados a objetos [61], mas, hoje, ele tambm utilizado em inmeros outros
54
h
h
h
h
h
h
h
h
h
h
h
h
h
h
h
h
h
h
h
h
h
h
Indcios de Problema
Aspectos de Qualidade
A
u
t
o
m

t
i
c
o
R
e
p
e
t
i
t

v
e
l

t
i
l

n
i
c
o
P
r
e
c
i
s
o
P
r
o

s
s
i
o
n
a
l
C
l
a
r
o
S
i
m
p
l
e
s
I
n
d
e
p
e
n
d
e
n
t
e
I
s
o
l
a
d
o
R

p
i
d
o
Obscure Test x x x x
Conditional Test Logic x x x x x x
Hard-to-Test Code x x x x x
Test Code Duplication x x x x x
Test Logic in Production x x x x
Assertion Roulette x x x x
Erratic Test x x x x x
Fragile Test x x x x x
Frequent Debugging x x x x x x x x
Manual Intervention x x x x x x
Slow Tests x x x
Buggy Tests x x x x x
Developers Not Writing Tests x x x
High Test Maintenance Cost x x x x x x x x x x x
Production Bugs x x
Tabela 5.1: Indcios de Problemas vs. Aspectos de Qualidade.
contextos, incluindo os testes automatizados [99]. Dessa forma, esses padres ajudam a criar testes de
qualidade tpicos para cenrios rotineiros em sistemas de software.
A organizao de um texto em padres o torna facilmente extensvel, ou seja, novos padres podem
ser adicionados sem a necessidade da reformulao de muitos outros trechos do trabalho. A descrio
de um padro segue uma estrutura enxuta e padronizada de tpicos pr-denidos, o que tende a facilitar
o estudo, principalmente para os leitores que j conhecem parte da teoria, pois os tpicos podem ser
lidos em uma ordem arbitrria.
Alguns dos padres que sero descritos nos prximos captulos j foram identicados por outros au-
tores e nomeados em ingls, mas devido sua grande importncia para a criao de testes automatizados
de qualidade, eles tambm foram includos nessa dissertao. Os nomes desses padres foram traduzi-
dos para o portugus, mas seus nomes originais em ingls foram mantidos para fcil identicao. Alm
disso, para esses casos, haver um tpico com as principais referncias da soluo. Quanto aos outros
padres, eles foram identicados e nomeados pelo autor desta dissertao. No entanto, independente da
autoria, todos sero descritos de acordo com a seguinte estrutura:
Nome: Nome do padro. Caso o nome possua a traduo para o ingls, signica que ele j foi identi-
cado por outros autores.
Tipo: Neste trabalho, um padro poder ser dos tipos Testabilidade, Organizacional, Robustez, Quali-
dade ou Desempenho. Testabilidade indica que o padro ajuda a melhorar essa caracterstica do
sistema em teste; Organizacional aponta que um padro utilizado para ajudar a organizar os
casos de teste; j os padres de Robustez servem para tornar os testes menos frgeis; os de Quali-
dade so teis para fazer anlises interessantes do sistema em teste em busca de erros; por ltimo,
Desempenho para aumentar a velocidade de execuo das baterias de testes.
Quando utilizar: Contm sugestes de situaes tpicas que o padro deve ser utilizado.
55
Inteno: Contm uma breve descrio dos objetivos do padro.
Motivao: Apresenta os problemas que o padro ajuda a resolver.
Soluo: Contm a descrio da soluo proposta pelo padro.
Consequncias: Discute como o padro ajuda a solucionar os problemas descritos no tpico anterior.
Implementao: Contm informaes de como o padro pode ser implementado. Se a implementao
for especca para um nicho de sistemas, o nome do tpico ir indic-lo, por exemplo, Implemen-
tao - WUI. Um mesmo padro poder ter tpicos de implementao para mais de um nicho de
sistemas.
Exemplo: Contm exemplos de cdigo-fonte demonstrando o padro. Os exemplos neste trabalho
utilizaro as linguagens C, Java, Scala ou Python. O nome do tpico ir informar a linguagem e as
tecnologias utilizadas, por exemplo, Exemplo - Python/UnitTest/QAssertions. Um mesmo padro
poder ter exemplos em mais de uma linguagem e as referncias das tecnologias esto nas pginas
iniciais da dissertao.
Padres Relacionados: Outros padres que possuem algum relacionamento importante com o padro
correspondente.
Usos Conhecidos: Sistemas ou ferramentas que utilizaram a soluo proposta e que serviram de
amostra para nomeao do padro. As referncias esto nas pginas iniciais da dissertao.
Referncias: Tpico no obrigatrio. Contm outras referncias para o padro, caso ele j tenha sido
nomeado por outro autor.
5.4 Denio de Antipadro
Antipadres tambm descrevem solues para problemas recorrentes, mas so propostas equivocadas,
pois causam problemas para o desenvolvimento dos sistemas e dos testes. Contudo, a descrio dos
antipadres ser mais simples do que dos padres.
Os antipadres, com raras excees, nunca devem ser utilizados. Em relao Implementao, os
programadores no precisam conhecer todos os detalhes das solues. Quanto aos Usos Conhecidos,
no seria elegante expor negativamente projetos sem uma boa causa. J a Inteno e a Motivao foram
agrupados em um nico item, Contexto, para simplicar e substituir a conotao positiva dos termos.
Os tpicos Consequncias e Padres Relacionados foram substitudos pelo tpico Indcios de Problemas
Relacionados. Sendo assim, a organizao de um antipadro segue a estrutura abaixo:
Nome: Nome do antipadro. Se o nome tiver a traduo para o ingls, signica que ele j foi identi-
cado por outros autores como antipadro ou at mesmo como padro. Em alguns dos casos, o
autor desse trabalho interpretou padres nomeados por outros trabalhos como solues ruins e,
portanto, devem ser entendidas como antipadres.
Tipo: Os antipadres podero ser dos tipos Organizacional, Robustez ou Testabilidade. A explicao
de cada um dos tipos anloga descrita na seo anterior, com a diferena de que as solues
indicadas so prejudiciais.
Contexto: Apresenta, de forma resumida, as situaes tpicas onde aparecem esses antipadres.
Exemplo: Similar ao tpico de um padro.
56
Indcios de Problemas Relacionados: Mostra as ligaes dos indcios de problemas (Seo 5.2) que
podem ser causados pelo antipadro, ou seja, as possveis consequncias causadas pela soluo
equivocada.
Referncias: Similar ao tpico de um padro.
57
58
Captulo 6
Testes de Unidade
Como foi descrito na Seo 3.3.1, um teste de unidade verica a correo dos menores trechos de
cdigo que possuem um comportamento denido e nomeado. Normalmente associamos uma unidade
a um mtodo ou funo do sistema, mas em certas situaes podemos entender unidade como blocos,
classes que geralmente so muito simples, mdulos ou at mesmo constantes (variveis com valores
xos) [99].
Os testes de unidade so, via de regra, os mais importantes dentre os demais tipos de teste, pois
so os mais apropriados para vericao da correo, que a premissa bsica de qualquer sistema de
software de qualidade, alm de ser pr-requisito dos outros aspectos de qualidade. Apesar de existirem
erros de correo insignicantes, que no impedem o bom funcionamento do sistema ou que trazem
pouco prejuzo se comparado com outras irregularidades, falhas na correo do sistema so, geralmente,
crticas e mais intolerveis do que problemas de desempenho, segurana ou usabilidade [70].
Independentemente da gravidade dos erros de correo, sempre desejvel que o sistema esteja
completamente correto, isto porque falhas na correo do sistema podem ocultar outros defeitos do soft-
ware e at mesmo desvalorizar os resultados de outras baterias de testes. Por exemplo, um algoritmo
que no trata todas as situaes esperadas pode ser muito mais rpido do que a verso correta do algo-
ritmo, sendo assim, os testes de desempenho realizados sobre o sistema trazem resultados que podem
ser descartados. Por isso, recomendado que outras baterias de testes s sejam executadas depois que
as baterias de testes de correo estejam completas e sem falhas.
De qualquer maneira, todos os tipos de testes e ferramentas podem ajudar a melhorar a correo dos
sistemas, principalmente em relao a situaes raras e pequenos detalhes que passam despercebidos
durante a implementao. Alm disso, outros tipos de testes submetem o sistema a situaes peculiares
que podem exercitar mdulos e dependncias que no foram previamente testados. Contudo, impor-
tante no atribuir a responsabilidade de encontrar erros de correo a baterias de outros tipos de testes,
principalmente por causa do uso de ferramentas que no so apropriadas e, portanto, induzem ocorrn-
cia de diversos antipadres que tornam os testes difceis de escrever e manter. As ferramentas para testes
de unidade so geralmente bibliotecas de cdigo-fonte que disponibilizam funcionalidades para facilitar
o manuseio e vericao de trechos do sistema, e essas ferramentas j so sucientes para a automao
produtiva dos testes de unidade durante o desenvolvimento.
Ao contrrio de outros tipos de testes que precisam que determinados mdulos do sistema estejam
nalizados para serem executados com xito, os testes de unidade devem ser escritos e executados sobre
pequenas pores de cdigo que no constituem isoladamente uma funcionalidade do sistema do ponto
de vista dos usurios nais. Essa caracterstica fundamental para encontrar erros de correo nos
estgios iniciais de desenvolvimento e para evitar desperdcio de tempo com depurao, pois os testes
de unidade podem ser bem especializados e a falhas nos testes tendem a ser facilmente localizadas [68].
59
6.1 Arcabouos para Testes de Unidade
Executar e testar um sistema so tarefas intrnsecas ao desenvolvimento de sistemas de software. Du-
rante a implementao comum executar o sistema periodicamente, seja para averiguar seu progresso,
encontrar erros ou at mesmo para incentivo pessoal pela visualizao do trabalho que est sendo re-
alizado. No entanto, s possvel executar certas funcionalidades do sistema quando um conjunto de-
terminado de mdulos est pelo menos parcialmente implementado. Por exemplo, pode ser necessrio
que a interface de usurio, assim como o ponto de partida da execuo do sistema (mtodo main), que
obrigatrio para muitas linguagens de programao, estejam implementados para que o usurio possa
fazer a chamada de uma determinada funcionalidade.
Uma soluo trivial para executar pequenos trechos do sistema sem depender de outros mdulos a
criao de mtodos main (geralmente implementados no prprio arquivo de cdigo da funcionalidade)
exclusivos para a execuo do trecho de cdigo desejado juntamente com a utilizao de comandos
print, que so utilizados para imprimir valores de variveis. Esta soluo nada mais que um teste de
unidade manual, ou seja, executado um pequeno trecho do sistema e as vericaes so feitas por um
ser humano que compara o valor impresso com o valor esperado.
Alm de todos os problemas da abordagem manual que j foram discutidos na Parte I, essa soluo
mistura o cdigo dos testes com o do sistema, prejudicando a legibilidade, depurao e manuteno
do cdigo, que pode implicar piora da correo do sistema a mdio e longo prazo. Desses padres e
antipadres de testes manuais de unidade surgiram os arcabouos que deram origem automao de
testes [20].
Por volta de 1994, Kent Beck criou o arcabouo SUnit [13] para fazer testes automatizados em seus
projetos que utilizavam a linguagem SmallTalk. At hoje o SUnit utilizado, alm de servir como
referncia para implementao de arcabouos semelhantes para outras linguagens de programao. Em
1998, por exemplo, Kent Beck e Erich Gamma desenvolveram o arcabouo JUnit para a linguagem Java
com base no SUnit. Kent Beck e colaboradores tambm escreveram na pgina Web ocial do JUnit um
artigo descrevendo passo a passo a sua implementao para referncia
1
.
O conjunto de arcabouos que so inspirados na arquitetura do SUnit so conhecidos como famlia
xUnit. Entre eles esto o PyUnit para Python, CppUnit para C++, JsUnit para JavaScript etc. Todos eles
facilitam a escrita do cdigo dos testes evitando replicao de trabalho e sem prejudicar o cdigo do
sistema principal.
Cada arcabouo da famlia xUnit possui suas particularidades, devido, principalmente, s diferenas
das linguagens, mas todos seguem uma mesma estrutura bsica e extensvel que facilita a escrita e acom-
panhamento dos testes automatizados. Esses arcabouos possuem basicamente trs responsabilidades:
1) possibilitar a criao e organizao de casos de testes com pouco esforo e sem replicao de cdigo;
2) facilitar a comparao dos valores obtidos com os valores esperados e 3) gerar um relatrio claro dos
resultados obtidos.
Um caso de teste representado por um mtodo quando so utilizadas linguagens orientadas a ob-
jetos, ou por uma funo no caso de linguagens estruturadas. Contudo, nem todo mtodo ou funo
do cdigo-fonte um caso de teste, por isso as ferramentas utilizam metadados
2
(Figura 6.2) ou con-
venes
3
(Figura 6.1) para identicar quais deles devem ser interpretados como casos de teste. Quando a
ferramenta xUnit executada, ela processa apenas os mtodos/funes que so denidos como casos de
testes, o que dispensa escrever mtodos main e tambm permite rodar todos casos de teste com apenas
um comando.
Para comparar os valores obtidos com os valores esperados automaticamente, basta substituir os
1
http://junit.sourceforge.net/doc/cookstour/cookstour.htm
2
A verso 4 ou superior do JUnit associa mtodos a casos de teste atravs da anotao Java @Test.
3
Muitas ferramentas seguem a conveno de que se o nome do mtodo comea com a palavra test, ento ele um caso de
teste.
60
1 // Referncias do JUnit
2 import junit.framework.TestCase;
3
4 // Aps a execuo desta classe de teste, ser impresso no console:
5 // Ser invocado pelo JUnit
6 public class JUnit35Exemplo extends TestCase {
7
8 // Conveno: mtodo comea com a palavra "test"
9 public void testUmMetodoDeTeste() {
10 System.out.println("Ser invocado pelo JUnit");
11 }
12
13 public void umMetodoAuxiliar() {
14 System.out.println("No ser invocado pelo JUnit");
15 }
16 }
Figura 6.1: Denindo mtodos de teste com JUnit 3.5.
1 // Referncias do JUnit
2 import org.junit.Test;
3
4 // Aps a execuo desta classe de teste, ser impresso no console:
5 // Ser invocado pelo JUnit
6 public class JUnit4Exemplo {
7
8 @Test // Metadado informando que este um mtodo de teste
9 public void umMetodoDeTeste() {
10 System.out.println("Ser invocado pelo JUnit");
11 }
12
13 public void umMetodoAuxiliar() {
14 System.out.println("No ser invocado pelo JUnit");
15 }
16
17 }
Figura 6.2: Denindo mtodos de teste com JUnit 4 ou superior.
61
comandos print da abordagem manual por comparaes (comandos if). Contudo, os arcabouos
disponibilizam funcionalidades que fazem as vericaes (asseres), substituindo esses comandos com
as vantagens de minimizar a replicao de cdigo de comparao e tambm de armazenar as infor-
maes pertinentes do caso de teste, como o resultado e a causa dos erros. A Figura 6.3 apresenta
exemplos de vericaes comuns utilizando os comandos bsicos de vericao do JUnit e, tambm, a
biblioteca Hamcrest, que torna o cdigo dos testes mais prximo da linguagem natural se ignorarmos os
parenteses, vrgulas e pontos da linguagem Java. Essa biblioteca tem como base o mtodo de vericao
assertThat e Matchers que so objetos que fazem as comparaes de forma conveniente.
Na Figura 6.4 h um exemplo de um teste escrito em Java com JUnit e Hamcrest. J na Figura 3.1
da Parte I podemos ver um exemplo de testes em Python de uma funo que verica se um nmero
primo.
Todas as informaes armazenadas so expostas no relatrio nal da bateria de testes, que so funda-
mentais para identicar os erros e diminuir o tempo perdido com depurao. Os relatrios tambm so
teis para o acompanhamento da automao dos testes e para documentao do sistema. Existem diver-
sas ferramentas que armazenam o histrico de resultados dos testes para gerar grcos e representaes
que ajudam a gerenciar os projetos.
6.1.1 Set up e Tear down
Muitos cenrios de testes (de qualquer tipo) s podem ser realizados segundo conguraes especcas
do ambiente, de dados e de estados de objetos. Por isso, comum a prtica de preparar um ambiente
propcio para um nico ou para um conjunto de casos de testes, sejam eles automatizados ou manuais.
Tendo o ambiente congurado, um caso de teste o manipula indiscriminadamente de acordo com
seus objetivos e faz as vericaes necessrias. Aps o trmino do teste, o ambiente alterado no
mais necessrio, portanto, uma boa prtica da automao de testes descart-lo, seja simplesmente para
liberar memria ou at mesmo para facilitar a criao do ambiente dos prximos cenrios de testes.
Por isso, outra caracterstica comum aos arcabouos da famlia xUnit a chamada implcita a mto-
dos prprios para prepararem e destruirem os ambientes dos testes, com os objetivos de padronizar, sim-
plicar e reduzir o cdigo-fonte dos testes. Como o prprio arcabouo faz a chamada desses mtodos, o
desenvolvedor no precisa fazer as chamadas, apenas saber em que momento eles sero chamados.
Da mesma forma que os mtodos de testes, os mtodos de preparao e destruio do ambiente
so denidos atravs de convenes ou metadados. Geralmente, o mtodo de criao do ambiente
identicado pelo nome set up, enquanto os de limpeza do ambiente de tear down. Quando so
utilizados metadados, possvel dar nomes aos mtodos mais coerentes com o que est sendo realizado.
No obstante, muitos arcabouos fornecem chamadas implcitas para esses mtodos para diversos
escopos: escopo de caso de teste, onde a chamada implcita realizada antes e depois de cada caso de
teste; escopo de grupos de testes, os quais as chamadas so feitas apenas antes e depois da execuo
de todos os casos de testes de um determinado conjunto; e, tambm, escopo da bateria de testes, onde
apenas uma chamada feita antes da execuo da bateria inteira de todos os testes e uma aps o trmino
da execuo dos mesmos.
O arcabouo TestNG, para Java, bastante exvel em relao aos escopos de set up e tear down.
A Figura 6.5 apresenta um esqueleto de teste para demonstrar o uxo das chamadas implcitas do ar-
cabouo.
Como os testes de unidade so isolados, muito comum o uso dos mtodos de set up apenas para
a inicializao dos objetos necessrios. Essa responsabilidade mesma de um construtor de um objeto,
entretanto, deve ser evitado sobrescrever os construtores das classes de testes para evitar interferncia
no uxo de controle dos arcabouos.
J os mtodos de tear down so utilizados principalmente para destruir os objetos, dados e liberar
a memria. No caso das linguagens que possuem coletor de lixo automtico, os mtodos de tear down
62
1 // Referncias Java
2 import java.util.*;
3 // Referncias do JUnit
4 import org.junit.Test;
5 import static org.junit.Assert.*;
6 // Referncias do Hamcrest
7 import static org.hamcrest.Matchers.*;
8
9 // Todos as verificaes dos testes a seguir so vlidas
10 public class ExemploDeVerificacoesTest {
11 @Test public void comparandoInstanciaDosObjetos() {
12 Object o1 = new Object();
13 Object o2 = o1;
14 assertSame(o1, o2);
15 assertThat(o1, is(sameInstance(o2)));
16 o2 = new Object();
17 assertNotSame(o1, o2);
18 assertThat(o1, is(not(sameInstance(o2))));
19 }
20
21 @Test public void comparandoStrings() {
22 assertTrue("a".equalsIgnoreCase("A"));
23 assertThat("a", is(equalToIgnoringCase("A")));
24
25 assertTrue("..zzz!!".contains("zzz"));
26 assertThat("..zzz!!", containsString("zzz"));
27
28 assertTrue("..zzz!!".startsWith(".."));
29 assertThat("..zzz!!", startsWith(".."));
30 }
31
32 @Test public void comparandoNumeros() {
33 assertEquals(10, 10);
34 assertThat(10, is(equalTo(10)));
35
36 assertTrue(11 >= 11);
37 assertThat(11, is(greaterThanOrEqualTo(11)));
38
39 assertTrue(10 < 11);
40 assertThat(10, is(lessThan(11)));
41 }
42
43 @Test public void comparandoPontosFlutuantes() {
44 assertEquals(10.493, 10.5, 0.1); // Preciso: 1 dcimo de diferena
45 assertThat(10.493, is(closeTo(10.5, 0.1)));
46 }
47
48 @Test public void comparandoListas() {
49 List<Integer> list = Arrays.asList(1, 2, 3, 4);
50 assertTrue(list.contains(1));
51 assertThat(list, hasItem(1));
52 }
53 }
Figura 6.3: Exemplos de vericaes com JUnit e Hamcrest.
63
1 // Referncias do JUnit
2 import org.junit.Test;
3 import static org.junit.Assert.*;
4 // Referncias do Hamcrest
5 import static org.hamcrest.Matchers.*;
6
7 public class MathTests {
8 final static double PRECISAO = 0.01;
9
10 @Test
11 public void testaValoresMuitoConhecidosDaFuncaoCosseno() {
12 assertThat(Math.cos(0), is(closeTo(1.0, PRECISAO)));
13 assertThat(Math.cos(90), is(closeTo(0.0, PRECISAO)));
14 assertThat(Math.cos(180), is(closeTo(-1.0, PRECISAO)));
15 assertThat(Math.cos(270), is(closeTo(0.0, PRECISAO)));
16 assertThat(Math.cos(360), is(closeTo(1.0, PRECISAO)));
17 }
18
19 @Test
20 public void testaValoresDeAngulosComunsDaFuncaoCosseno() {
21 assertThat(Math.cos(30), is(closeTo(Math.sqrt(2)/2, PRECISAO)));
22 assertThat(Math.cos(45), is(closeTo(0.5, PRECISAO)));
23 assertThat(Math.cos(60), is(closeTo(Math.sqrt(2)/2, PRECISAO)));
24 }
25
26 }
Figura 6.4: Exemplo de Teste em Java com JUnit e Hamcrest.
so dispensveis nos testes de unidade, pois aps a realizao de todos os testes de uma classe, todas as
variveis de instncia sero coletadas. Nesse caso, o uso dessa funcionalidade uma micro-otimizao
desnecessria, pois o aumento da complexidade do cdigo dos testes por causa do cdigo adicional no
recompensada por milissegundos de velocidade.
Um caso excepcional quando um nico mtodo de teste consome muita memria, ento pode ser
interessante liber-la antes de realizar os outros casos de testes da mesma classe. Ainda, caso sejam
utilizados variveis globais, pode haver a preocupao de vazamento de memria, onde o tear down
tambm ser til. A Figura 6.6 mostra um exemplo de teste de unidade em Java onde interessante
preparar e destruir o ambiente de teste.
Entretanto, os mtodos de set up e tear down so mais importantes para testes de integrao. Os
testes com persistncia de dados e de interface de usurio podem depender de ambientes complexos
e propcios para tornarem os testes frgeis. Por exemplo, comum popular um banco de dados para
realizao de um teste e remover os dados adicionados aps a concluso do mesmo. Assim, dados
criados por um teste no afetam os outros. J para interfaces de usurio, a preparao e destruio do
ambiente refere-se comumente abertura e fechamento dos navegadores, pginas e janelas.
6.2 Objetos Dubls (Test Doubles)
Algumas vezes difcil testar um sistema porque ele pode depender de componentes que so difceis
de serem utilizados em um ambiente de teste [93, 138]. Tais componentes podem ser bancos de dados,
sistemas de arquivos, redes, servios Web, bibliotecas e at mesmo do relgio do computador, no caso
de funcionalidades que envolvem datas e instantes.
Para essas situaes, mais produtivo vericar a correo do sistema atravs de testes de unidade
64
1 // Referncias do TestNG
2 import org.testng.annotations.*;
3
4 // Aps a execuo desta classe de teste, ser impresso no console:
5 // @BeforeSuite => @BeforeTest => @BeforeClass
6 // @BeforeMethod => @Test: teste 1 => @AfterMethod
7 // @BeforeMethod => @Test: teste 2 => @AfterMethod
8 // @AfterClass => @AfterTest => @AfterSuite
9 public class TestNGExemplo {
10 /* Mtodos de set up */
11 @BeforeSuite public void antesDeTodasAsClassesDeTestes() {
12 System.out.print("@BeforeSuite => ");
13 }
14
15 // Ao contrrio do BeforeClass, BeforeTest roda mesmo que no tenha teste
16 @BeforeTest public void antesDessaClasseDeTestes() {
17 System.out.print("@BeforeTest => ");
18 }
19
20 @BeforeClass public void antesDoPrimeiroMetodoDeTesteDessaClasse() {
21 System.out.println("@BeforeClass");
22 }
23
24 @BeforeMethod public void antesDeCadaMetodoDeTesteDessaClasse() {
25 System.out.print("@BeforeMethod => ");
26 }
27
28 /* Mtodos de tear down */
29 @AfterMethod public void depoisDeCadaMetodoDeTesteDessaClasse() {
30 System.out.println("@AfterMethod");
31 }
32
33 @AfterClass public void depoisDoPrimeiroMetodoDeTesteDessaClasse() {
34 System.out.print("@AfterClass => ");
35 }
36
37 @AfterTest public void depoisDessaClasseDeTestes() {
38 System.out.print("@AfterTest => ");
39 }
40
41 @AfterSuite public void depoisDeTodasAsClassesDeTestes() {
42 System.out.print("@AfterSuite");
43 }
44
45 /* Mtodos de teste */
46 @Test public void metodoDeTeste1() {
47 System.out.print("@Test: teste 1 => ");
48 }
49
50 @Test public void metodoDeTeste2() {
51 System.out.print("@Test: teste 2 => ");
52 }
53 }
Figura 6.5: Mtodos de set up e tear down do arcabouo TestNG para Java.
65
1 // Referncias do TestNG
2 import org.testng.annotations.*;
3 // Referncias do sistema em teste ocultas
4
5 public class PilhaComTamanhoLimitadoTests {
6 Pilha pilha; // varivel utilizada em todos os testes
7
8 /* Set up */
9 @Before public void inicializaObjetos() {
10 pilha = new Pilha();
11 }
12
13 /* Tear down */
14 @After public void liberaMemoria() {
15 pilha.esvazia();
16 pilha = null;
17 System.gc(); // Agilizando a execuo do Garbage Collector
18 }
19
20 // Teste que consome bastante memria
21 @Test public void pilhaNaoAceitaMaisElementosDoQueLimiteEstipulado() {
22 pilha.setAlturaMaxima(1000);
23 for(int i = 0; i < 1000; i++)
24 pilha.coloca(i);
25 assertEquals(1000, pilha.altura());
26 pilha.coloca(i);
27 assertEquals(1000, pilha.altura());
28 }
29 }
Figura 6.6: Exemplo tpico de uso dos mtodos set up e tear down.
66
em vez de testes de integrao. Primeiramente, os testes de unidade solucionam os problemas de baixa
testabilidade do sistema em teste. Alm disso, todas as outras caractersticas de qualidade, descritas na
Seo 5.1, so mais facilmente asseguradas quando um cenrio de teste isolado, ou seja, ele tende a
car mais rpido, independente e repetitvel.
O que caracteriza um teste de unidade justamente o isolamento de um trecho de cdigo do resto
do sistema e do ambiente. Isolar um trecho de cdigo signica substituir todas as suas dependncias,
que podem ter implementaes lentas, incompletas ou que prejudicam a testabilidade, por dependncias
controladas. Dessa maneira, o trecho de cdigo em teste trabalha sob situaes ideais, supondo que todas
suas dependncias esto corretas. Inclusive, essa caracterstica ajuda a dispensar a prtica de depurao,
pois, se algum teste falhar, ca explcito o trecho de cdigo que est o problema.
No entanto, isolar um trecho de cdigo pode ser uma tarefa complicada. A diculdade deve-se
principalmente testabilidade do sistema (Seo 10.3). Quanto mais entrelaado estiverem os mdulos
em teste, mais difcil ser para substituir as dependncias por objetos controlados [113].
Dado que um mdulo sucientemente coeso para isolar seu comportamento, possvel que isso
seja feito comumente de duas maneiras: a primeira inserir, errneamente, lgica de teste no cdigo de
produo, que um indcio de problema (Seo 5.2); a segunda, mais elegante, fazer com que os testes
substituam, apenas dentro do seu contexto e durante sua execuo, as dependncias da funcionalidade
em teste por mdulos e objetos que apenas respondam o que o cenrio de teste espera para poder fazer
suas vericaes.
No caso de linguagens orientada a objetos, os testes podem substituir os objetos dependentes por
objetos equivalentes, mas que possuem o comportamento mnimo desejado para realizao do teste.
Por exemplo, atravs de herana, pode-se criar subclasses que sobrescrevem a implementao original
por uma simplicada. Nas linguagens em que at os mtodos so objetos, possvel, simplesmente,
substitu-los por implementaes temporrias durante a execuo do cenrio de teste. Ainda, existem
bibliotecas, tais como Mockito, EasyMock e JMock para Java, que criam objetos que seguem o compor-
tamento desejado, sem a necessidade de implement-los.
Esses objetos que so criados no escopo dos testes para substituir dependncias so chamados gener-
icamente de Objetos Dubls, em analogia aos dubls de cinema [99]. Contudo, h diversos tipos de
Objetos Dubls (Figura 6.7), que so apropriados para situaes especcas. Nas sees 6.4.3 at 6.4.7
h a descrio detalhada dos cinco tipos de Objetos Dubls j descritos por Meszaros: Objeto Tolo,
Stub, Falsicado, Emulado e Espio, respectivamente. Na Seo 6.4.8, descrito um novo tipo que foi
identicado pelo autor, o Objeto Prottipo.
A escolha do tipo de Objeto Dubl a ser utilizado depende prioritariamente do que se est querendo
vericar, pois nem todos eles podem ser utilizados dentro de um contexto. Por exemplo, somente os Ob-
jetos Falsicados e os Espies so capazes de imitar um algoritmo, ou seja, de fornecer dados dinmicos
para a funcionalidade em teste.
A Tabela 6.1 faz uma comparao dos objetos dubls de acordo com quatro caractersticas impor-
tantes: (1) se o dubl exercitado pelo teste, ou seja, se ele inuencia diretamente no resultado do teste;
(2) se o dubl fornece informaes enganosas que inuenciam no resultado gerado pela funcionalidade
em teste, sejam elas dados estticos ou gerados dinamicamente por algoritmos simplicados; (3) a ca-
pacidade do dubl de armazenar informaes sobre o que foi executado, o que permite fazer vericaoes
na forma que um algoritmo executado e (4) caso o objeto dubl precise ou no seguir uma interface
denida, o que pode ser importante para realizar testes de algoritmos reexivos ou com programao a
aspectos.
Depois que se sabe quais padres so viveis de serem utilizados, a escolha deve-se basear na sim-
plicidade, ou seja, qual deles torna a implementao do teste mais enxuta e legvel. Por exemplo, Se o
objeto servir apenas para evitar erros de compilao ou erros indiretos de execuo, ou seja, ele no ser
exercitado diretamente pelo teste, ento Objeto Tolo o que deve ser escolhido porque o mais fcil de
implementar. No entanto, no existe uma regra para isso, pois varia de acordo com as particularidades
67
de cada contexto e das ferramentas disponveis de objetos dubls. Mais detalhes e exemplos so podem
ser encontrados na Seo 6.4.
Figura 6.7: Tipos de Objetos Dubls.
h
h
h
h
h
h
h
h
hh
Objeto Dubl
Caractersticas
Exercitado pelo Teste Fornecimento de Dados para o SUT Armazena Informaes da Execuo Interface Predenida
Objeto Tolo (Dummy Object) No No Fornece No Sim
Objeto Stub (Test Stub) Sim Esttico ou Dinmico No Sim
Objeto Falsicado (Fake Object) Sim Esttico ou Dinmico No Sim
Objeto Emulado (Mock Object) Sim Esttico Sim Sim
Objeto Espio (Spy Object) Sim Esttico ou Dinmico Sim Sim
Objeto Prottipo Sim Esttico No No
Tabela 6.1: Comparao de algumas caractersticas dos Objetos Dubls.
6.3 Boas Prticas de Automao
A automao de testes pode ter diversos problemas de cdigo-fonte, comportamento e projeto, como
foi discutidos na Seo 5.2. Entretanto, muitos desses problemas podem ser facilmente evitados atravs
da utilizao de boas prticas de automao de testes. Algumas das boas prticas mais gerais, teis
para quaisquer tipos de teste, j foram discutidas no Captulo 4. Agora, sero abordadas boas prticas
direcionadas para testes de unidade.
6.3.1 Cdigo-Fonte
Apesar de que o cdigo-fonte dos testes precisa receber a mesma ateno dedicada ao cdigo-fonte do
sistema em teste (Seo 5.1), no necessrio seguir, rigorosamente, todas as boas prticas de progra-
mao conhecidas pela equipe de desenvolvimento. Por exemplo, algumas prticas de otimizaes ou
de modularizao podem trazer muitos benefcios para o sistema, tornando-o mais rpido e exvel, mas
elas podem prejudicar outras caractersticas, como a clareza e simplicidade.
Para os testes, o ideal que seu cdigo seja o mais simples, enxuto e legvel possvel. Deve-se
encontrar o equilbrio entre o uso de todo o poder das linguagens de programao com a clareza e
simplicidade de um texto em linguagem natural. Para encontrar esse equilbrio, algumas boas prticas
podem ajudar, como sero descritas abaixo.
Sem Rigores das Linguagens de Programao: Muitas linguagens permitem atribuir muitas pro-
priedades a uma varivel, mtodo ou classe. Por exemplo, em Java, possvel denir uma varivel
como pblica (public), privada (private), protegida (protected), de classe (static), constante (nal)
etc. Todas essas propriedades podem ser muito importantes para a arquitetura do sistema, mas,
para os testes, elas so dispensveis, pois elas apenas poluem o cdigo-fonte com complexidade
desnecessria. O design do cdigo-fonte dos testes deve ser to simples a ponto de no necessitar
desses rigores de arquitetura. Os casos excepcionais so quando as ferramentas utilizadas neces-
sitarem de alguma propriedade especca. Por exemplo, o JUnit requer que todos os mtodos de
teste sejam pblicos.
68
Ainda, as linguagens podem oferecer diferentes convenes de cdigo-fonte, sendo que algumas
so mais rgidas do que as outras. Por exemplo, em C o padro ANSI mais rgido do que o
POSIX. No caso de Java, possvel congurar ferramentas auxiliares e IDEs para denir quais
so as convenes que devem ser seguidas. Para os testes, deve-se sempre optar pelas convenes
menos controladoras, que possibilitem a criao de cdigo-fonte menos rigoroso.
Nomes Auto-Explicativos: Os nomes das variveis, mtodos e classes podem seguir convenes, desde
que eles sejam claros e auto-explicativos. Deve-se dar preferncia a nomes completos e longos do
que siglas e abreviaes que tornem o signicado no-bvio.
Linguagem Ubqua da Equipe: Alm dos nomes deverem ser auto-explicativos, prefervel que eles
utilizem uma linguagem ubqua entre clientes, programadores, testadores etc. Ainda, deve ser
evitado o uso de sinnimos para diminuir o vocabulrio utilizado pelo projeto.
Sem Variveis Globais Mutveis: Variveis globais, compartilhadas e de classe devem ser evitadas
tanto no sistema como nos testes, mas h situaes em que elas trazem muitos benefcios para as
aplicaes. No entanto, para os testes, elas devem sempre ser evitadas, pois elas no s aumentam
a complexidade dos testes, como tambm favorecem criao de casos de testes dependentes, o
que os tornam mais difceis de serem paralelizados.
Arquitetura Simples: Por mais que um design de arquitetura possa tornar o cdigo-fonte mais exvel
e diminuir a replicao de cdigo, ele tambm pode tornar o cdigo-fonte mais difcil de ser
entendido. Flexibilidade e no-replicao de cdigo tambm so importantes para os testes, mas
deve haver um equilbrio com a simplicidade. Boas tcnicas de orientao a objetos, design e
arquitetura tambm devem ser utilizadas ao escrever os cenrios de testes. Contudo, devido
prpria simplicidade do cdigo dos testes automatizados e do uso de arcabouos, no deve ser
grande o esforo para criar baterias organizadas de testes automatizados. De maneira geral, o
design das classes de testes no deve ser muito mais complexo do que simples relacionamentos
de herana e colaborao.
Sem Otimizaes Desnecessrias: Se at para os sistemas as otimizaes so recomendadas apenas
para as funcionalidades com os gargalos de desempenho, para os testes essa recomendao
ainda mais enftica. De maneira geral, otimizao dos testes deve ser feita apenas por ferramentas
auxiliares e de maneira transparente, ou seja, sem a necessidade de alterar o cdigo-fonte dos
testes. Na prtica, essas ferramentas podem executar os testes paralelamente ou com alguma
estratgia mais elaborada.
6.3.2 Refatoraes Comuns
Como discutido na seo anterior, o cdigo dos testes deve ser organizado, claro, legvel e sem repli-
cao. Quando a implementao no atende a esses requisitos, ainda possvel melhor-la atravs de
refatorao, que deve ser uma tarefa rotineira da automao dos testes.
Existem diversos estudos sobre refatorao de cdigo de teste com o intuito de melhorar a quali-
dade de testes j implementados [53, 143]. Entretanto, mesmo durante a criao de novos cenrios de
testes comum a realizao de refatoraes, principalmente para facilitar a adio de novos cenrios
de vericao. A seguir h breves comentrios das refatoraes que so mais frequentemente utilizadas
durante a automao de testes. Por causa da modelagem simples do cdigo dos testes, as refatoraes
mais usadas esto entre as mais simples [59, 122].
Extrair Mtodo: Muitos mtodos de testes so parecidos, ento comum extrao de fragmentos para
mtodos auxiliares ou at mesmo para os mtodos de set up e tear down.
69
Extrair Classe: Quando uma classe de teste comea a car muito extensa, com muitos mtodos auxil-
iares e de teste, pode ser um sinal que ela precisa ser dividida, ou, at mesmo, que as classes do
sistema que esto sendo testadas possuem muitas responsabilidades. O mesmo raciocnio pode
ser empregado quando os mtodos de set up e tear down esto muito extensos e complexos.
Extrair Superclasse: Quando diversas classes de testes possuem mtodos de set up ou tear down semel-
hantes, pode ser um indcio de que uma classe base para os testes pode ser criada para evitar
replicao de cdigo.
Renomear Classes, Mtodos e Variveis: As refatoraes anteriores de extrao sempre produzem no-
vas variveis e classes, logo, os nomes podem no mais fazer sentido, logo, precisam ser renomea-
dos. No obstante, os nomes do sistema em teste que forem renomeados tambm precisam ser
reetidos nos testes, no entanto, as ferramentas de refatorao no conseguem automatizar essa
tarefa, portanto, necessrio uma preocupao adicional quanto a isso.
Introduzir Varivel Explicativa: Alguns cenrios de testes podem criar cenrios complexos e no intu-
itivos. Para melhorar a legibilidade do cdigo dos testes, pode-se adicionar variveis temporrias
com nomes auto-explicativos para substituir expresses complexas.
6.3.3 Orientao a Objetos
Programas orientados a objetos possuem um bom potencial para alta testabilidade [117, 97, 27], prin-
cipalmente por causa das facilidades de modularizao atravs de classes, heranas e relacionamentos.
Entretanto, vrios detalhes de implementao dos objetos podem inuenciar no modo que os testes so
realizados.
Basicamente, o que precisa ser testado em um objeto sua interface, ou seja, tudo que exposto
para o resto da aplicao. A interface pblica de um objeto pode ser composta por variveis, mtodos e
classes internas, todas sujeitas a erros de implementao. Entretanto, o mais comum testar os mtodos
do objeto e das classes internas. Testes de variveis so apenas interessantes para o caso de constantes
ou para vericar se elas foram inicializadas corretamente.
Quando as funcionalidades pblicas de um objeto esto corretas, h bons indcios que toda a imple-
mentao interna do objeto tambm est. J quando o que est querendo ser testado alguma funcional-
idade interna (privada), preciso car atento, pois isso um indcio de que um conjunto de objetos no
possuem um bom design. Essa situao um exemplo tpico de como os testes automatizados provm
informaes para ajudar com a criao do design do sistema.
Nessa situao, o primeiro passo avaliar se o trecho em teste pode ser movido para algum outro
objeto mais coerente, de modo que a funcionalidade se torne pblica. Dado que o design est de acordo
com as necessidades do sistema, ento basta realizar os testes desejados. O empecilho que, devido s
limitaes das linguagens, pode ser impossvel os testes conseguirem fazer as chamadas das funcionali-
dades privadas. Em alguns casos, o uso de reexo pode ser suciente para chamada da funcionalidade.
Se ainda assim no for possvel, a soluo alterar a visibilidade da funcionalidade ou ento tentar
test-la de forma indireta, atravs de uma funcionalidade pblica que a utilize.
Para classes annimas, o pensamento anlogo ao de mtodos privados. Primeiro deve-se avaliar se
a classe precisa ser nomeada. Caso a classe precise mesmo ser annima, ento a soluo test-la de
forma indireta, ou seja, atravs da funcionalidade que a utiliza.
Ja para as classes abstratas que no podem ser instanciadas, a soluo mais simples, basta criar
uma subclasse concreta que no sobrescreva as funcionalidades da classe em teste. Para no poluir o
cdigo do sistema, essa classe deve ser acessvel apenas aos testes. No entanto, essa abordagem s
coerente se o sistema respeita o Princpio de Substituio de Liskov
4
[89]. Atravs dessa classe concreta
4
Esse princpio diz que uma instncia de uma subclasse deve ser capaz de substituir qualquer instncia da classe pai sem
qualquer dano ao sistema.
70
possvel vericar o cdigo implementado na classe pai, mas no possvel vericar se os mtodos
abstratos esto sendo chamadas corretamente. Para fazer essas vericaes, o recomendado utilizar
Objetos Dubls, tais como Objeto Emulado (Mock Object, Seo 6.4.6) ou Objeto Espio (Spy Object,
Seo 6.4.7).
Quanto aos recursos globais e mutveis, eles devem ser evitados sempre que possvel, assim como
tambm recomendado em programas procedimentais. No caso dos objetos, dois exemplos comuns
de recursos compartilhados so variveis de classe ou objetos Singleton. Todos recursos compartilhados
dicultam a automao dos testes e impedem a execuo paralela dos testes. Quando no possvel refa-
torar o sistema em teste, ento as baterias de testes devem ser executadas sequencialmente e, para evitar
testes intermitentes, cada conjunto de teste deve ser responsvel por atualizar o recurso compartilhado
de acordo com suas necessidades.
No obstante, as implementaes dos Padres de Projetos [61] tambm devem ser testadas, mesmo
que os programadores estejam bem familiarizados com o design dos objetos. Inclusive, tambm pos-
svel pensar em recomendaes para os testes das implementaes dos padres.
Por exemplo, para os padres Singleton e Flyweight recomendado que sejam vericadas que as
instncias dos objetos gerados sejam sempre as mesmas (assertSame), em oposio s instncias obti-
das atravs dos padres Prototype, Builder e Factory Method (assertNotSame). J os padres Chain
of Responsability e Composite lidam com colees de objetos, ento importante realizar testes com
colees vazias e com elementos.
Ainda, podem ser utilizados Objetos Dubls (6.2) para testar alguns Padres de Projeto. Por exem-
plo, Mediator, Interpreter, Adapter e Decorator podem exigir o uso de Objetos Espies para vericarem
que as sadas indiretas de dados esto corretas. No obstante, Template Method e Abstracty Factory po-
dem utilizar Objetos Falsicados para ajudar a testar o trecho concreto das implementaes. Outros
padres podem ser mais simples de serem testados por serem intrinsicamente mais coesos, tais como
Strategy, Command e State.
6.3.4 Orientao a Aspectos
Programao Orientada a Aspectos (POA) um novo paradigma de desenvolvimento que serve de com-
plemento Orientao a Objetos. Os Aspectos fornecem uma nova maneira de encapsular as fun-
cionalidades que so comuns a diversos objetos e difceis de serem isoladas [150]. O cdigo-fonte da
funcionalidade que foi modularizada em um Aspecto inserido em objetos pr-denidos, sendo que esse
processo pode ser feito em tempo de compilao ou execuo, dependendo das ferramentas utilizadas.
A POA uma tcnica poderosa, mas a criao de testes automatizados, tanto para os Aspectos como
para os sistemas que os utilizam, uma tarefa que requer novas abordagens. Um Aspecto no possui
uma identidade independente, pois ele depende de um objeto para existir; ou seja, ele no pode ser
instanciado diretamente. Entretanto, esse novo tipo de estrutura de dado pode conter diversos tipos de
erros, inclusive erros graves como de laos innitos. Por isso, fundamental que eles sejam muito bem
testados.
Existem muitos estudos e estratgias para se testar programas orientados a aspectos, sendo que al-
guns deles sugerem testes de unidade [86, 91] e outros de integrao [102, 83, 24, 106]. O teste de
unidade dene o prprio Aspecto como sendo uma unidade, e com a ajuda de ferramentas apropri-
adas (Jaml-Unit), criado uma maneira de fazer as vericaes diretamente. J os testes de integrao
vericam o comportamento dos objetos que receberam cdigo-fonte de Aspectos [150]. Contudo, o
termo integrao confuso para esse caso, pois possvel realizar testes de unidade para as classes que
possuem cdigo de Aspectos, que ser a estratgia abordada nessa seo.
Essa estratgia nada mais do que testar sistemas orientados a aspectos como se fossem simples-
mente orientado a objetos [152]. Dessa maneira, todas as prticas, padres e tcnicas conhecidas de
testes OO tambm podem ser utilizadas, inclusive o uso do Objeto Prottipo (Seo 6.4.8). Essa estrat-
71
gia coerente, pois um bom teste automatizado no testa como uma funcionalidade foi implementada,
mas sim o que ela deve fazer.
Um Aspecto composto de Pontos de Atuao (Pointcuts) e Adendos (Advices), sendo que ambos
precisam ser testados. As duas subsees seguintes discutiro as estratgias de cada um deles.
Pontos de Atuao (Pointcuts)
Os Pontos de Atuao so expresses que mapeiam os locais do sistema onde sero inseridos os trechos
de cdigo-fonte do aspecto (Adendos). Essas expresses so anlogas s expresses regulares, que pos-
suem padres de caracteres que devem ser encontrados em strings. Um padro denido de forma errada
pode adicionar ou remover pontos de atuao importantes [85]. Por isso, por mais que existam IDEs que
ajudam na criao dos Pontos de Atuao, fundamental ter uma bateria de testes automatizados para
evitar erros de distrao e de regresso.
Para testar esses pontos, pode ser utilizado Objetos Prottipo (Seo 6.4.8) que contenhamtrechos de
cdigo que devem e que no devem ser encontrados pelas expresses do Ponto de Atuao, justamente
para vericar os cenrios positivos e negativos. Para fazer as vericaes, pode ser utilizado Objetos
Espies ou Emulados, que possibilitam vericar se eles foram ou no exercitados. Consequentemente,
deve ser possvel injetar os Objetos Dubls para que os testes possam ser realizados.
Outra soluo a utilizao de arcabouos que ajudam a testar os Pontos de Atuao, como o APTE
(Automated Pointcut Testing for AspectJ Programs) [5]. Ele recebe um conjunto de aspectos e classes e
devolve duas listas: uma dos Pontos de Juno que satisfazemos Pontos de Atuao dos aspectos; e outra
contendo os Pontos de Juno que quase satisfazem os Pontos de Atuao, que so casos interessantes
de serem analisados em busca de erros. Dessa forma, basta criar um teste automatizado que mande
executar essa ferramenta e que verique se as listas contm ou no os mtodos esperados. Essa soluo
dispensa o uso de Objetos Dubls, mas ao mesmo tempo requer o uso de uma ferramenta externa a dos
testes.
Adendos (Advices)
J os Adendos so os trechos de cdigo que sero acrescentados em todos os Pontos de Juno (Join
points) do sistema, que so os locais que satisfazem os Ponto de Atuao do Aspecto. Isso implica
que erros de implementao em seu cdigo so espalhados em diversos pontos da aplicao. Conse-
quentemente, Aspectos mal implementados podem causar danos catastrcos ao sistema. Por isso,
fundamental a criao de uma bateria de testes automatizados muito cuidadosa.
A primeira recomendao para criao desses testes a utilizao do padro Objeto Humilde (Seo
6.4.2) para separar a lgica principal de outros detalhes de implementao no testveis. Por exem-
plo, em Java com AspectJ, parte do cdigo do Adendo pode estar escrito em Java (testvel) e parte na
linguagem do AspectJ (no testvel de forma direta sem a ajuda de arcabouos prprios).
O cdigo em Java pode ser encapsulado em um objeto comum e testado como qualquer outro.
Quanto ao restante da implementao, recomendvel que os testes sejam realizados, novamente,
atravs de Objetos Prottipo que receberam o cdigo do Adendo. A princpio, pode parecer que os
testes esto vericando o Objeto Dubl e no o sistema em teste, o que seria um erro, mas essa estrat-
gia coerente, pois o cdigo adicionado ao Objeto Dubl idntico ao cdigo adicionado ao sistema
em teste. Um exemplo de teste com Aspectos que engloba todos essas recomendaes pode ser visto na
Seo 6.4.8.
Ainda, caso o sistema possua diversos Aspectos que sero aplicados em um mesmo Ponto de Juno,
pode-se criar situaes de teste para vericar se existe incompatibilidade entre eles [119]. Para isso, basta
criar um Objeto Prottipo que satisfaz os Pontos de Atuao correspondentes.
Tambm importante notar que existem diversos tipos de Aspectos. Alguns apenas coletam in-
formaes do sistema e no inuenciam o resto da implementao do objeto, enquanto outros podem
72
alterar o uxo de controle ou at mesmo alterar os valores de variveis dos objetos [121]. Contudo, essa
estratgia permite criar testes para quaisquer dessas situaes, pois pensando no objeto como uma caixa
preta, ele no diferente. Apenas importante ressaltar que o cdigo dos Adendos deve permitir que os
objetos colaboradores possam ser injetados.
6.3.5 Reexo
Reexo a capacidade de um programa observar ou alterar sua prpria estrutura ou comportamento
[58]. A tcnica de programar utilizando essa capacidade tem sido vastamente utilizada, principalmente
por bibliotecas, APIs e engines. Bons exemplos so os arcabouos para programas Web, tais como os
populares Django (Python), Rails (Ruby), Grails (Groovy), Spring e Hibernate (Java).
No entanto, assim como a programao orientada a aspectos, as funcionalidades que utilizam re-
exo processam parte do prprio cdigo do sistema, por exemplo, por meio de bytecodes. Em alguns
casos, as regras de uma funcionalidade se baseiam em algumas caractersticas do cdigo, enquanto, em
outras situaes, novas funcionalidades so adicionadas a objetos em tempo de execuo. Para ambos os
casos podem haver diversos problemas, no s de correo, como tambm de segurana e desempenho.
Ainda, devem ser consideradas as inmeras possibilidades de se implementar um mesma soluo
computacional, portanto, mesmo os algoritmos reexivos mais simples devem se preocupar com muitos
detalhes. No obstante, o cdigo-fonte de sistemas pode estar em constante evoluo, seja atravs de
refatoraes, correes ou da adio de novas funcionalidades. Cada mudana do cdigo-fonte pode
quebrar os algoritmos reexivos, o que os tornam funcionalidades muito suscetveis a erros de regresso.
Por causa desses fatores, a automao de testes uma boa soluo para garantir a qualidade dessas
funcionalidades.
As recomendaes para criao de bons testes automatizados para os algoritmos reexivos so pare-
cidas aos de programao orientada a aspectos. Primeiramente, por mais que esses algoritmos no
tenham uma estrutura denida, uma boa prtica de programao separar as responsabilidades de re-
conhecimento de um padro de cdigo-fonte (anlogo aos Pontos de Atuao dos Aspectos) das tarefas
que sero realizadas no momento oportuno (anlogo aos Adendos dos Aspectos).
Para os testes das funcionalidades que reconhecem padres de cdigo-fonte, podem ser utilizados
Objetos Falsicados (Seo 6.2) ou Objetos Prottipo (Seo 6.4.8). J para as tarefas que sero execu-
tadas, pode-se utilizar os padres Objeto Humilde (Seo 6.4.2).
6.3.6 Mdulos Assncronos
Hoje, a importncia de sistemas assncronos muito grande devido Internet, grande modulariza-
o dos sistemas e ao uso de servios. Alm disso, a tendncia tornar os sistemas cada vez mais
independentes e velozes, devido criao e popularizao dos processadores com vrios ncleos e das
linguagens de programao que facilitam a escrita de sistemas altamente escalveis, tais como Erlang,
Haskell e Scala.
Trechos de cdigo que envolvem programao paralela ou distribuda so complexos e, por isso,
muito suscetveis a erros. H muitos pontos que precisam ser vericados quando um sistema utiliza
outros processos, threads ou atores, tais como a sincronizao e a comunicao atravs do compartil-
hamento de memria ou da troca de mensagens. Erros tpicos de programao concorrente como os
de sincronizao, deadlocks, livelocks, starvation e race conditions podem quebrar regras de negcio,
tornar dados inconsistentes e at mesmo deixar o sistema inteiro inutilizvel.
No entanto, os testes de unidade tem como premissa bsica a execuo sncrona do sistema em
teste. Apesar da grande importncia dos mdulos assncronos em sistemas de software, a maioria das
ferramentas e arcabouos de testes automatizados no possuem funcionalidades que facilitam a imple-
mentao de casos de teste de qualidade.
73
Contudo, criar testes automatizados para esses sistemas possvel, apesar de ser muito mais com-
plexo. Ao contrrio de uma bateria de testes sequenciais, a bateria de testes de mdulos assncronos
executada em uma thread diferente da do sistema em teste. Como a execuo do sistema testado depende
do sistema operacional e do escalonador de processos, no possvel prever, com exatido, quando o
sistema ser executado. Dessa forma, os testes no recebem automaticamente os efeitos colaterais do
sistema, logo, preciso que eles sejam sincronizados, ou ento, que observem quando o sistema foi
alterado, para ento fazer as vericaes no seu tempo.
Para sincronizar os testes necessrio o mesmo conhecimento e cautela da sincronizao do sistema
em teste. J para observar o sistema, os testes podem obter informaes de seu estado em um momento
oportuno, ou ento, eles podem capturar os eventos emitidos pelo sistema. Todas essas alternativas so
muito propcias a criarem testes com muitos antipadres, que geram os problemas de testes difceis de
manter e escrever, falsos positivos e negativos, testes pouco legveis, intermitentes e lentos.
A primeira boa prtica para criar bons testes de mdulos assncronos utilizar o padro Objeto
Humilde (Seo 6.4.2) para isolar a lgica de negcios da lgica computacional que gerencia a linha
de execuo da funcionalidade. A lgica de negcios deve ser testada como qualquer outra parte do
sistema. Quanto ao restante da funcionalidade, deve ser utilizado o padro Assert Eventually [60], que
verica periodicamente se a funcionalidade assncrona terminou de ser executada. Quando o padro
identica que o teste est pronto para ser testado, ento so feitas as vericaes da correo. Caso o
sistema demore muito para ser executado, ento o padro devolve um erro de tempo esgotado.
74
6.4 Padres
A seguir sero descritas solues de testes automatizados de unidade que podem ser aplicadas em difer-
entes contextos. Entretanto, algumas das recomendaes podem ser generalizadas para outros tipos de
teste. Vale ressaltar que todos os padres sero denidos segundo o esqueleto exibido na Seo 5.3.
6.4.1 Injeo de Dependncia (Dependency Injection)
Tipo: Testabilidade
Quando utilizar: Em sistemas orientado a objetos. Idealmente, em todos objetos do sistema.
Inteno: Desacoplar os objetos e facilitar a insero e substituio das suas dependncias.
Motivao: Sistemas muito acoplados so mais difceis de serem testados [142]. Mais especicamente,
objetos que no permitem a substituio de seus objetos colaboradores inviabilizam o uso de
Objetos Dubls para criao de testes isolados.
Soluo: Um objeto deve estar desacoplado de suas dependncias, de modo que haja mecanismos para
que todas elas possam ser substitudas por outros objetos do mesmo tipo. Consequentemente,
possvel testar o objeto isoladamente com o auxlio de Objetos Dubls.
Consequncias: Todos as dependncias podem ser inseridas atravs dos contrutores ou de mtodos per-
tinentes. Ainda, a responsabilidade de instanciar os objetos colaboradores passada para outros
objetos do sistema, ou at mesmo para novos objetos que so criados especicamente para isolar
esta responsabilidade, como ocorre quando utilizamos Padres de Projeto de Criao, tais como
Builder, Factory e Prototype [61].
Implementao: Para variveis privadas de instncia, a injeo das dependncias pode ser feita mais
comumente atravs do construtor, ou de mtodos set. Se a varivel for pblica, dentro de um
contexto, basta atualiz-la diretamente. Ainda, pode ser utilizado arcabouos que so responsveis
por vasculhar e inicializar as variveis desejadas, como o Spring para Java. J as dependncias no
associadas ao objeto em teste podem ser passadas como argumentos para os mtodos necessrios.
Exemplo - Java/JUnit/Hamcrest: A Figura 6.8 mostra um trecho de cdigo do objeto Compra de uma
loja que est acoplado s regras de desconto. Nesse exemplo, queremos testar apenas que o valor
do subtotal com desconto o valor do desconto subtrado do subtotal. Entretanto, da maneira que
est implementada, no conseguimos realizar esse teste sem conhecer toda a regra de descontos
aplicada na compra, isso porque a classe Compra e o mtodo que faz o clculo do subtotal com
desconto possuem mais de uma responsabilidade.
Testar funcionalidades que possuem mais de uma responsabilidade trabalhoso, alm de resultar
em diversos outros antipadres de testes automatizados. Isso porque os testes se tornam presos
implementao e no ao comportamento do sistema. A Figura 6.9 mostra um exemplo de teste
automatizado para o mtodo subTotalComDesconto.
O primeiro passo para melhorar a implementao do objeto Compra isolar as regras de desconto
em um objeto prpio para isso, como mostra a Figura 6.10. Contudo, essa melhoria no inuencia
em como os testes do objeto Compra sero implementados, isso porque o objeto colaborador
RegraDesconto ainda no pode ser injetado, dessa maneira, ainda necessrio conhecer as regras
de desconto para poder testar o mtodo subTotalComDesconto.
Para nalizar a refatorao, necessrio remover a responsabilidade do objeto Compra de instan-
ciar as regras de desconto (Figura 6.11), consequentemente, ser possvel injet-la tanto atravs
dos testes quanto pelo prprio sistema.
75
1 public class Compra {
2 Cliente cliente;
3 Produtos produtos;
4 FormaPagamento formaPagamento;
5 Promocao promocao;
6
7 public Compra(Cliente c, Produtos l, FormaPagamento f, Promocao p) {
8 this.cliente = c;
9 this.produtos = l;
10 this.pagamento = f;
11 this.promocao = p;
12 }
13
14 public Dinheiro subTotal() {
15 return produtos.subTotal();
16 }
17
18 // Objeto Desconto e as regras esto acoplados ao objeto Compra.
19 // No possvel testar o objeto Compra independente das regras de desconto.
20 public Dinheiro subTotalComDesconto() {
21 Dinheiro valor = new Dinheiro(0);
22
23 if(cliente.isVIP()) {
24 Desconto d = new DescontoVIP();
25 valor.add(d.valor(this));
26 }
27 else {
28 Desconto d = new DescontoPelaFormaDePagamento();
29 valor.add(d.valor(this));
30 valor.add(promocao.desconto().valor(this));
31 }
32
33 return subTotal().subtract(valor);
34 }
35 }
Figura 6.8: Objeto Compra com implementao acoplada ao objeto Desconto.
76
1 //Dependncias do JUnit + Hamcrest
2 import org.junit.Before;
3 import org.junit.Test;
4 import static org.junit.Assert.*;
5 import static org.hamcrest.Matchers.equalTo;
6
7 public class CompraTests {
8 // Objetos pertinentes ao teste
9 Produtos produtos;
10 Cliente cliente;
11 FormaPagamento pagamento;
12 Promocao promocao;
13 Compra compra;
14
15 @Before
16 public void setUp() {
17 produtos = new Produtos();
18 }
19
20 // Para realizar este teste preciso conhecer as regras de desconto.
21 // Um teste simples fica extenso e difcil de entender.
22 @Test public void totalComDescontoDeveSubtrairDescontoDoSubTotal() {
23 // Detalhes de implementao das regras de desconto.
24 boolean vip = true;
25 cliente = new Cliente(vip);
26 Dinheiro preco = new Dinheiro(100);
27 produtos.add(new Produto(preco));
28 pagamento = new BoletoFormaPagamento(); // 3% de desconto
29 promocao = new PromocaoDeNatal(); // 10% de desconto
30
31 compra = new Compra(cliente, produtos, pagamento, promocao);
32
33 // 100 - (3 + 10 + 15) = 72
34 assertThat(compra.subTotalComDesconto(), equalTo(new Dinheiro(72)));
35 }
36
37 // As regras de desconto devero ser testadas a partir do objeto Compra.
38 // Devero ser feitos testes para cliente no-VIP, com pagamento por carto etc.
39 }
Figura 6.9: Teste complicado do objeto Compra.
77
1 public class Compra {
2 Cliente cliente;
3 Produtos produtos;
4 FormaPagamento formaPagamento;
5
6 public Compra(Cliente c, Produtos l, FormaPagamento f) {
7 this.cliente = c;
8 this.produtos = l;
9 this.formaPagamento = f;
10 }
11
12 public Dinheiro subTotal() {
13 return produtos.subTotal();
14 }
15
16 // As regras de desconto esto isoladas no objeto RegraDeDescontoPadrao,
17 // mas ainda assim as regras esto implicitamente acopladas ao objeto Compra.
18 public Dinheiro subTotalComDesconto() {
19 RegraDesconto regraDesconto = RegraDescontoPadrao();
20 Dinheiro valorDesconto = regraDesconto.calcula(this);
21
22 return subTotal().subtract(valor);
23 }
24 }
Figura 6.10: Objeto Compra com implementao mais organizada, mas ainda acoplada ao objeto
Desconto.
A testabilidade est relacionada com a exibilidade do sistema, portanto, se est complicado de
testar, um indcio de que o sistema precisa ser refatorado. Com essa nova modelagem, o sistema
poder trabalhar com diversas regras de desconto simultneamente e os testes cam legveis e
fceis de implementar (Figura 6.12).
Padres Relacionados: O padro Objeto Humilde (Seo 6.4.2), que tambm utilizado para separar
as responsabilidades de um objeto, pode ser utilizado para desacoplar os objetos e facilitar a
injeo de dependncia. Ainda, esse padro pr-requisito para os padres Objeto Emulado
(Mock Object, Seo 6.4.6), Objeto Falsicado (Fake Object, Seo 6.4.5) e Objeto Espio (Test
Spy, Seo 6.4.7).
Usos Conhecidos: O arcabouo Spring para Java uma das ferramentas mais populares de injeo de
dependncia. Outro uso conhecido que merece destaque a API EJB para Java. Na Seo 10.3 h
outros exemplos relacionados.
Referncias: Existem livros especcos sobre injeo de dependncia [113] e outros de catlogo de
padres que tambm o descrevem [99].
78
1 public class Compra {
2 Cliente cliente;
3 Produtos produtos;
4 FormaPagamento formaPagamento;
5 RegraDesconto regraDesconto;
6
7 // possvel injetar as dependncias.
8 // Objeto Compra e Desconto no esto mais acoplados.
9 public Compra(Cliente c, Produtos p, FormaPagamento f, RegraDeDesconto r) {
10 this.cliente = c;
11 this.produtos = p;
12 this.formaPagamento = f;
13 this.regraDesconto = r;
14 }
15
16 public Dinheiro subTotal() {
17 return produtos.subTotal();
18 }
19
20 public Dinheiro subTotalComDesconto() {
21 Dinheiro valor = regraDesconto.calcula(compra);
22 return subTotal().subtract(valor);
23 }
24 }
Figura 6.11: Objeto Compra desacoplado de suas dependncias.
79
1 // Dependncias do JUnit + Hamcrest
2 import org.junit.Before;
3 import org.junit.Test;
4 import static org.junit.Assert.*;
5 import static org.hamcrest.Matchers.*;
6
7 public class CompraTests {
8 // Objetos Tolos
9 Cliente cliente = new Cliente();
10 FormaPagamento pagamento = new BoletoFormaPagamento();
11
12 // Objetos pertinentes ao teste
13 Produtos produtos;
14 Compra compra;
15 // Objeto Dubl: Objeto Falsificado
16 RegraDesconto regraDesconto = new RegraDesconto() {
17 public Dinheiro calcula(Compra compra) {
18 return new Dinheiro(15);
19 }
20 }
21
22 @Before
23 public void setUp() {
24 produtos = new Produtos();
25 }
26
27 // Valor total com desconto depende somente do valor dos produtos e
28 // do valor total do desconto.
29 @Test public void totalComDescontoDeveSubtrairDescontoDoSubTotal() {
30 Dinheiro preco = new Dinheiro(100);
31 produtos.add(new Produto(preco));
32
33 compra = new Compra(cliente, produtos, pagamento, regraDesconto);
34
35 // 100 - 15 = 85
36 assertThat(compra.subTotalComDesconto(), equalTo(new Dinheiro(85)));
37 }
38
39 // ... As regras de desconto tambm devem ser testadas, mas isoladamente e
40 // em outra classe de teste.
41 }
Figura 6.12: Teste do objeto Compra refatorado.
80
6.4.2 Objeto Humilde (Humble Object)
Tipo: Testabilidade
Quando utilizar: Sempre que o objeto em teste possui mais de uma responsabilidade, mas, princi-
palmente, quando difcil test-lo devido ao seu acoplamento com arcabouos ou at mesmo a
objetos complexos. So exemplos comuns os objetos que possuem processos assncronos, ou que
interagem com requisies Web e gerenciadores de bancos de dados.
Inteno: Uma boa prtica de orientao a objetos que cada objeto tenha apenas uma responsabil-
idade. A inteno desse padro justamente partir um objeto complexo em objetos simples e
coesos (objetos humildes).
Motivao: Objetos com muitas responsabilidades so difceis de serem testados. Primeiramente,
porque a inicializao do objeto pode car mais complexa, assim como os mtodos de preparao
do teste (set up). Alm disso, os prprios mtodos de testes tendem a car mais extensos e dif-
ceis de implementar, pois quanto mais acoplado um objeto est do resto do sistema, maior ser
o trabalho para executar um cenrio de teste de modo isolado. No obstante, quanto mais re-
sponsabilidades um objeto possui, mais vericaes so necessrias para avaliar a correo da
implementao.
Soluo: Refatorar objetos para que eles tenham apenas uma responsabilidade. Em particular,
necessrio separar a lgica testvel de um objeto dos aspectos tcnicos e complexos de arcabouos
e do ambiente.
Consequncias: Aps a refatorao, os objetos cam mais simples e coesos, pois possuem apenas uma
responsabilidade. Alm disso, a lgica de negcios ca desacoplada da lgica de infraestrutura,
tal como lgica de programao assncrona, persistncia de dados etc. Isso resulta em um sistema
mais exvel, com objetos coesos, desacoplados e com alta testabilidade.
Implementao: Esse padro descreve simplesmente uma boa prtica de orientao a objetos, indepen-
dentemente do sistema ter ou no testes automatizados. Sendo assim, no h uma implementao
sistematizada para esse padro. Qualquer padro arquitetural ou de projeto pode descrever a
soluo apropriada para melhorar a testabilidade dos objetos, assim como todas as tcnicas de
refatorao podem ser teis. No entanto, como as responsabilidades de um objeto sero divididas
entre objetos menores, natural a utilizao de refatoraes de extrao, tais como Extract Class
e Extract Method.
Exemplo - Python/Django: A Figura 6.13 possui um trecho de cdigo de uma aplicao Web com o
arcabouo Django para buscar pessoas por parte do nome. Essa funcionalidade recebe uma req-
uisio Web e devolve a resposta apropriada. No entanto, esse mtodo tambm possui a respons-
abilidade de gerar a query que ser executada no banco de dados para encontrar os resultados, ou
seja, alm do mtodo ter mais de uma responsabilidade, ele no segue a arquitetura MVC proposta
pelo arcabouo.
Essa falha de modelagem reete na qualidade dos testes automatizados. Para testar a busca re-
alizada no banco de dados necessrio lidar com objetos de requisio e de resposta Web. Para
testar apenas a query gerada, pode-se separar as responsabilidades em objetos distintos, como
mostrado na Figura 6.14. Nesse caso, o objeto PessoaManager o Objeto Humilde.
Padres Relacionados: Caso sejam feitos alguns testes nos objetos que contm os detalhes complexos
de arcabouos, o padro Injeo de Dependncia (Seo 6.4.1) pode ser utilizado para substituir
o Objeto Humilde por dubls.
81
1 # Funcionalidade para buscar pessoas por parte do nome.
2 def busca_pessoa_pelo_nome(request):
3 if request.method == POST:
4 pessoas = Pessoa.objects.filter(nome__icontains=request.POST[texto_busca
])
5 else:
6 pessoas = []
7 return HttpResponse(/pessoas-encontradas, {pessoas: pessoas})
Figura 6.13: Exemplo de funcionalidade com muitas responsabilidades.
1 # Objeto Humilde: Para testar, basta chamar o mtodo
2 # Pessoa.objects.com_parte_do_nome com uma string desejada.
3 # Os testes no precisam mais lidar com objetos de Request e Response.
4 class PessoaManager(models.Manager):
5 def com_parte_do_nome(texto_busca):
6 return self.filter(nome__icontains=texto_busca)
7
8
9 # Mtodo refatorado
10 def busca_pessoa_pelo_nome(request):
11 if request.method == POST:
12 pessoas = Pessoa.objects.com_parte_do_nome(request.POST[texto_busca])
13 else:
14 pessoas = []
15 return HttpResponse(/pessoas-encontradas, {pessoas: pessoas})
Figura 6.14: Funcionalidade de busca de pessoas refatorada, utilizando um Objeto Humilde.
82
Referncias: Esse padro foi identicado por Meszaros [99].
83
6.4.3 Objeto Tolo (Dummy Object)
Tipo: Testabilidade
Quando utilizar: Quando for necessrio lidar com objetos que no so utilizados pelo cenrio de teste,
mas que so fundamentais para sua execuo. Por exemplo, para evitar erros de compilao.
Inteno: Apenas viabilizar a execuo de um teste.
Motivao: Para realizao de um caso de teste, pode ser necessrio a instanciao de vrios obje-
tos, mas nem sempre todos eles so utilizados diretamente pela funcionalidade em teste. Alguns
desses objetos so necessrios apenas para evitar erros de compilao ou de execuo de outras
funcionalidades que no esto sob vericao.
Soluo: Substituir os objetos colaboradores que so necessrios para a execuo de um teste mas que
no so processados por objetos nulos ou implementados da maneira mais simples possvel.
Consequncias: Torna vivel a execuo dos cenrios de teste.
Implementao: Basta substituir os objetos colaboradores dispensveis por valores nulos ou instncias
implementadas da maneira mais simples e legvel possvel.
Exemplo - Java/JUnit/Mockito: mais comum que os Objetos Tolos sejam objetos de tipos primi-
tivos das bibliotecas provenientes da linguagem de programao utilizada (strings, nmeros etc),
entretanto, tambm pode acontecer de serem de tipos denidos pelo prprio sistema em teste.
A Figura 6.15 mostra trs maneiras comentadas de substituir objetos colaboradores por Objetos
Tolos.
Padres Relacionados: Quando no for possvel passar valores nulos e a inicializao do Objeto Tolo
se torna complexa, ento recomendado o uso de Objetos Emulados (Mock Objects, Seo 6.4.6).
Usos Conhecidos: O uso desse padro natural durante a implementao de um caso de teste.
84
1 class Pessoa {
2 public Pessoa(String nome, Date nascimento) { /* ... */ }
3 public int idade() { /* mtodo em teste */ }
4 }
5
6 import java.util.Date;
7
8 // Dependncias do JUnit + Hamcrest
9 import org.junit.Test;
10 import static org.junit.Assert.*;
11
12 // Dependncias do Mockito
13 import static org.mockito.Mockito.*;
14
15 public class PessoaTests {
16
17 @Test public void idadeDeUmaPessoaQueNasceuHojeRetornaZero_versao1() {
18 // A String nome recebe um valor nulo.
19 // Se o nome receber algum processamento, como validao de dados,
20 // essa abordagem se torna invivel.
21 Pessoa pessoa = new Pessoa(null, new Date());
22 assertEquals(0, pessoa.idade());
23 }
24
25 @Test public void idadeDeUmaPessoaQueNasceuHojeRetornaZero_versao2() {
26 // A String "Um nome qualquer" um Objeto Tolo.
27 // O clculo da idade no deve depender do nome da pessoa.
28 Pessoa pessoa = new Pessoa("Um nome qualquer", new Date());
29 assertEquals(0, pessoa.idade());
30 }
31
32 @Test public void idadeDeUmaPessoaQueNasceuHojeRetornaZero_versao3() {
33 // interessante deixar claro quando um objeto no deve
34 // interferir no teste.
35 // A biblioteca Mockito fornece alguns mtodos com esse propsito,
36 // tais como o anyString, anyObject, anyInt...
37 Pessoa pessoa = new Pessoa(anyString(), new Date());
38 assertEquals(0, pessoa.idade());
39 }
40 }
Figura 6.15: Exemplo de Objeto Tolo.
85
6.4.4 Objeto Stub (Test Stub)
Tipo: Testabilidade
Quando utilizar: Quando os dados obtidos de objetos colaboradores inuenciam e dicultam a criao
de testes automatizados para uma funcionalidade.
Inteno: Substituir objetos colaboradores que so difceis de serem manipulados por verses que
possam ser controladas. Dessa maneira, o objeto pode ser congurado para construir diferentes
cenrios de teste.
Motivao: Muitos objetos colaboradores so difceis de serem manipulados, consequentemente, os
testes se tornam difceis de serem realizados. Por exemplo, os que envolvem o relgio do com-
putador, datas etc.
Soluo: Criar objetos que so fceis de serem manipulados para substituir o comportamento que prej-
udica a testabilidade.
Consequncias: A testabilidade do sistema melhorada, o que possibilita a simulao de diversos
cenrios de teste.
Implementao: Deve-se criar uma variao do objeto colaborador, seguindo a mesma interface, mas
de modo que ele seja capaz de retornar dados controlados para a funcionalidade em teste. Ento
esse objeto deve ser injetado no objeto em teste.
Padres Relacionados: O padro Injeo de Dependncia (Dependency Injection, Seo 6.4.1)
necessrio para injetar o Objeto Stub no objeto em teste. J o Objeto Emulado (Mock Object,
Seo 6.4.6) tambm atua como esse padro fornecendo dados estticos para o objeto em teste,
no entanto, o Objeto Emulado tambm possui funcionalidades que permitem vericar chamadas
indiretas da funcionalidade em teste.
Usos Conhecidos: A soluo proposta por esse padro surgiu antes da soluo proposta pelos Objetos
Emulados [28, 93].
86
6.4.5 Objeto Falsicado (Fake Object)
Tipo: Testabilidade
Quando utilizar: O Objeto Falsicado uma soluo elegante para realizao de testes difceis de
serem simulados. Por exemplo, quando queremos vericar o comportamento do sistema quando
ocorre problemas de hardware, rede, sistemas de arquivos etc. Esse padro tambm til para re-
solver problemas de testes de partes do sistema que dependem de mdulos intrinsicamente lentos.
Entretanto, os Objetos Emulados (Seo 6.4.6) tambm servem para solucionar esses problemas,
com a vantagem de que so mais fceis de serem utilizados do que a soluo proposta por este
padro. Sendo assim, esse padro s deveria ser utilizado quando no existir uma biblioteca de
Objetos Emulados apropriada para as tecnologias utilizadas pelo sistema em teste.
No entanto, os Objetos Falsicados so capazes de fornecer dados gerados dinamicamente, en-
quanto os Objetos Emulados no so apropriados para isso. Por isso, os Objetos Falsicados so
mais interessantes para testes que precisam de uma grande quantidade de dados, tais como testes
de sanidade.
Outra situao que requer gerao de dados dinmica ocorre quando o teste de correo feito
atravs da comparao dos resultados de algoritmos similares (Seo 6.4.9). Essa abordagem
especialmente til quando est sendo feito uma otimizao: os resultados gerados por um algo-
ritmo que sabemos que est correto so utilizados como valores esperados do algoritmo que est
sendo testado.
Inteno: Fornecer uma implementao simplicada e isolada de uma dependncia da funcionalidade
em teste (objeto colaborador) para que um cenrio de teste se torne vivel de ser realizado.
Motivao: Alguns cenrios de testes so difceis de serem criados ou executados, principalmente os
que dependem de regras de negcio complexas, servios externos ao sistema em teste etc.
Soluo: A ideia fornecer uma implementao auxiliar e exclusiva para os testes de uma funcional-
idade do sistema, de modo que facilite a realizao dos cenrios de testes que utilizam indireta-
mente essa funcionalidade. A proposta a mesma do Antipadro Gancho para os Testes (Test
Hook, Seo 6.5.1), mas a implementao deve ser feita de modo elegante, ou seja, sem poluir e
aumentar a complexidade do sistema em teste. O cdigo auxiliar deve ser visvel apenas dentro
do escopo dos testes automatizados.
Consequncias: Os cenrios de testes difceis de serem realizados de forma isolada se tornam simples
como quaisquer outros.
Implementao: Os Objetos Falsicados devem possuir a mesma interface do objeto colaborador a
ser substitudo, mas com uma implementao simplicada do comportamento esperado. A im-
plementao pode ser desde uma verso limitada de um algoritmo at mesmo um conjunto de
informaes hard-coded que so simplesmente retornadas. Para a simulao de erros, a imple-
mentao pode simplesmente lanar a exceo adequada.
Exemplo - Python/UnitTest: A classe Compra, citada no exemplo do padro Injeo de Dependncia
(Dependency Injection, Seo 6.4.1) possui um exemplo de Objeto Falsicado de uma implemen-
tao com dados estticos (Figura 6.12), o que bem simples de implementar.
Padres Relacionados: Esse padro a soluo elegante do Antipadro Gancho para os Testes (Test
Hook, Seo 6.5.1). Tambm pode-se utilizar Objetos Falsicados para implementar o padro
Teste por Comparao de Algoritmos (Seo 6.4.9). J o padro Objeto Emulado (Mock Object,
87
Seo 6.4.6) prope um outra soluo para resolver parte dos problemas que esse padro tam-
bm se prope a resolver. Por m, como todo Objeto Dubl, o padro Injeo de Dependncia
(Dependency Injection, Seo 6.4.1) fundamental.
88
6.4.6 Objeto Emulado (Mock Object)
Tipo: Testabilidade
Quando utilizar: Objetos Emulados tambm atuam como Objetos Stub, fornecendo dados para o ob-
jeto em teste atravs dos objetos colaboradores. Por isso, eles tambm podem ser utilizados
rotineiramente durante a criao dos cenrios de teste. Quando a criao e congurao dos ob-
jetos colaboradores uma tarefa complexa, ento deve-se utilizar preferencialmente esse padro,
que facilita essas tarefas. Esse padro tambm possui similaridades com o Objeto Espio. Am-
bos armazenam informaes do que foi executado, o que permite que sejam feitas vericaes no
comportamente interno da funcionalidade em teste.
Inteno: Possibilitar e facilitar a criao de testes para um objeto de forma isolada. Esse padro
tambm permite vericar as chamadas indiretas da funcionalidade em teste.
Motivao: Testar um cdigo no trivial de maneira isolada difcil. Alm disso, criar e congurar
objetos Objetos Stub e Espio pode ser uma tarefa complexa.
Soluo: O Objeto Emulado cria uma implementao vazia do objeto colaborador e permite que o
comportamento de cada mtodo do objeto possa ser descrito de forma dinmica.
Consequncias: As funcionalidades so testadas isoladamente. Alm disso, os Objetos Emulados so
muito rpidos, o que melhora a performance dos testes.
Implementao: Criar um Objeto Emulado no uma tarefa trivial, pois ele feito de maneira
dinmica por meio de reexo. Por isso, s vivel sua utilizao se existir uma biblioteca
de Objetos Emulados para a linguagem do sistema em teste.
Padres Relacionados: Esse padro atua como o Objeto Stub (Test Stub, Seo 6.4.4), fornecendo
dados para o objeto em teste. Tambm permite vericar chamdas indiretas, como o Objeto Es-
pio (Test Spy, Seo 6.4.7). Os Objetos Emulados tambm precisam ser injetados no objeto em
teste, por isso o padro Injeo de Dependncia (Dependency Injection, Seo 6.4.1) tambm
importante.
Usos Conhecidos: Essa soluo foi identicada no ano 2000 [93] e desde ento temsido muito estudada
[138, 80].
89
6.4.7 Objeto Espio (Test Spy)
Tipo: Testabilidade
Quando utilizar: Quando o que se est querendo vericar algum comportamento interno da fun-
cionalidade em teste, que no se reete diretamente nos resultados obtidos. Em outras palavras,
o efeito colateral produzido pela funcionalidade em teste no pode ser vericado atravs de um
valor de retorno ou de uma exceo lanada. Exemplos tpicos so testes de classes abstratas
(especialmente comum em APIs) e de sistemas de registros (log).
Inteno: Permitir que um teste consiga vericar se uma chamada indireta de uma funcionalidade est
sendo executada corretamente.
Motivao: importante vericar a correo de chamadas indiretas. Elas podem conter no apenas
detalhes fundamentais para o funcionamento do sistema, como tambm podem interferir na cor-
reo do comportamento explcito de uma funcionalidade. Contudo, no possvel vericar esse
tipo de funcionalidade do modo convencional, atravs dos efeitos colaterais diretos causados.
Soluo: Criar um objeto que coleta informaes das chamadas indiretas da funcionalidade em teste
para que possam ser utilizadas posteriormente para vericao.
Consequncias: Comobjetos espies se torna possvel vericar a correo das sadas indiretas de dados
de uma funcionalidade, incluindo chamadas de mtodos abstratos.
Implementao: As chamadas indiretas podem ser do prprio objeto em teste ou de algum objeto
colaborador. Para o primeiro caso, deve-se herdar a classe em teste acrescentando um sistema
de registro dos mtodos executados. J para o segundo caso, deve-se fazer o mesmo mas com o
objeto colaborador, com o trabalho adicional de que o objeto espio dever ser injetado no objeto
em teste. Contudo, existem bibliotecas que facilitam o trabalho de gerar objetos espies, alm de
fornecerem funes padronizadas para vericao dos dados coletados.
Exemplo - Python/Unittest: A Figura 6.16 mostra uma classe abstrata com um algoritmo de sin-
cronizao que percorre duas listas simultaneamente enquanto vai comparando seus itens
(SincronizadorDeListas). Os tipos que herdarem dessa classe devem denir qual o comporta-
mento desejado quando os tens forem comuns a ambas as listas ou exclusivo em alguma delas.
importante notar que no possvel testar o comportamento dessa classe do modo convencional,
comparando as sadas diretas de dados (valores retornados ou excees lanadas) com valores es-
perados. Uma soluo criar uma classe espi que adicionar um comportamento para capturar
informaes das chamadas indiretas de modo que essas informaes possam ser vericadas poste-
riormente. A Figura 6.17 contm uma implementao de classe espi e realiza os testes usando-a
como base.
Exemplo - Python/Unittest/Python-Mockito: A principal vantagem de utilizar ferramentas de objetos
espies que o trabalho de criar um novo objeto com um sistema de registro dispensado. Outra
vantagem que os testes cam padronizados e, consequentemente, mais fceis de serem interpre-
tados. A Figura 6.18 mostra um outro exemplo de teste para o cdigo da Figura 6.16, mas dessa
vez utilizando a ferramenta Python-Mockito para gerar os objetos espies.
Padres Relacionados: O padro Injeo de Dependncia (Dependency Injection, Seo 6.4.1) fun-
damental para que o Objeto Espio seja inserido no objeto em teste. O Objeto Emulado (Mock
Object, Seo 6.4.6) tambm armazena informaes da sua execuo, no entanto, ele no capaz
de fornecer dados dinmicos para o sistema em teste.
90
1 class SincronizadorDeListas(object):
2
3 def __init__(self, lista1, lista2):
4 self.lista1 = lista1
5 self.lista2 = lista2
6 self.lista1.sort()
7 self.lista2.sort()
8
9 def executa(self):
10 self.__executa_recusivamente(0, 0)
11
12 def __executa_recusivamente(self, indice1, indice2):
13 sem_mais_elementos_na_lista1 = indice1 >= len(self.lista1)
14 sem_mais_elementos_na_lista2 = indice2 >= len(self.lista2)
15
16 if sem_mais_elementos_na_lista1 and sem_mais_elementos_na_lista2:
17 return
18
19 if sem_mais_elementos_na_lista2:
20 elemento1 = self.lista1[indice1]
21 self.processa_elemento_exclusivo_lista1(elemento1)
22 return self.__executa_recusivamente(indice1 + 1, indice2)
23
24 if sem_mais_elementos_na_lista1:
25 elemento2 = self.lista2[indice2]
26 self.processa_elemento_exclusivo_lista2(elemento2)
27 return self.__executa_recusivamente(indice1, indice2 + 1)
28
29 elemento1 = self.lista1[indice1]
30 elemento2 = self.lista2[indice2]
31
32 if elemento1 == elemento2:
33 self.processa_elementos_iguais(elemento1, elemento2)
34 return self.__executa_recusivamente(indice1 + 1, indice2 + 1)
35 elif elemento1 > elemento2:
36 self.processa_elemento_exclusivo_lista2(elemento2)
37 return self.__executa_recusivamente(indice1, indice2 + 1)
38 else: # elemento1 < elemento2
39 self.processa_elemento_exclusivo_lista1(elemento1)
40 return self.__executa_recusivamente(indice1 + 1, indice2)
41
42 # mtodos abstratos:
43 def processa_elementos_iguais(self, elemento1, elemento2): pass
44 def processa_elemento_exclusivo_lista1(self, elemento1): pass
45 def processa_elemento_exclusivo_lista2(self, elemento2): pass
Figura 6.16: Uma classe python com mtodos abstratos.
91
1 import unittest
2
3 from sincronizador import SincronizadorDeListas
4
5 # Herda a classe em teste e adiciona comportamento para espion-la.
6 class SincronizadorDeListasEspiao(SincronizadorDeListas):
7
8 def __init__(self, lista1, lista2):
9 super(SincronizadorDeListasEspiao, self).__init__(lista1, lista2)
10 self.processa_elementos_iguais_contador = 0
11 self.processa_elemento_exclusivo_lista1_contador = 0
12 self.processa_elemento_exclusivo_lista2_contador = 0
13
14 def processa_elementos_iguais(self, element1, element2):
15 self.processa_elementos_iguais_contador += 1
16
17 def processa_elemento_exclusivo_lista1(self, element1):
18 self.processa_elemento_exclusivo_lista1_contador += 1
19
20 def processa_elemento_exclusivo_lista2(self, element2):
21 self.processa_elemento_exclusivo_lista2_contador += 1
22
23
24 class SincronizadorDeListasEspiaoTests(unittest.TestCase):
25
26 def verificar_chamadas(self, espiao, a, b, c):
27 self.assertEquals(a, espiao.processa_elementos_iguais_contador)
28 self.assertEquals(b, espiao.processa_elemento_exclusivo_lista1_contador)
29 self.assertEquals(c, espiao.processa_elemento_exclusivo_lista2_contador)
30
31 def test_nao_deve_executar_nada_se_recebe_duas_listas_vazias(self):
32 espiao = SincronizadorDeListasEspiao([], [])
33 espiao.executa()
34 self.verificar_chamadas(espiao, 0, 0, 0)
35
36 def test_deve_processar_elemento_exclusivo_lista1(self):
37 espiao = SincronizadorDeListasEspiao([1], [])
38 espiao.executa()
39 self.verificar_chamadas(espiao, 0, 1, 0)
40
41 def test_deve_processar_elemento_exclusivo_lista2(self):
42 espiao = SincronizadorDeListasEspiao([], [1])
43 espiao.executa()
44 self.verificar_chamadas(espiao, 0, 0, 1)
45
46 def test_deve_processar_elemento_comum_em_ambas_as_listas(self):
47 espiao = SincronizadorDeListasEspiao([1], [1])
48 espiao.executa()
49 self.verificar_chamadas(espiao, 1, 0, 0)
50
51 def test_ambas_as_listas_com_elementos_distintos(self):
52 espiao = SincronizadorDeListasEspiao([1], [2])
53 espiao.executa()
54 self.verificar_chamadas(espiao, 0, 1, 1)
Figura 6.17: Exemplo de teste com Objeto Espio.
92
1 import unittest
2 from mockito import *
3
4 from sincronizador import SincronizadorDeListas
5
6 class SincronizadorDeListasTests(unittest.TestCase):
7
8 def test_nao_deve_executar_nada_se_recebe_duas_listas_vazias(self):
9 espiao = spy(SincronizadorDeListas([], []))
10 espiao.executa()
11
12 verify(espiao).executa()
13 verify(espiao).__executa(0, 0)
14 verifyNoMoreInteractions(espiao) # No executou nenhum outro mtodo
15
16 def test_deve_processar_elemento_exclusivo_lista1(self):
17 espiao = spy(SincronizadorDeListas([1], []))
18 espiao.executa()
19
20 # No executou o mtodo processa_elementos_iguais com parmetro 1
21 verify(espiao, times=0).processa_elementos_iguais(1)
22 # Executou uma vez o mtodo processa_elemento_exclusivo_lista1 com
parmetro 1
23 verify(espiao, times=1).processa_elemento_exclusivo_lista1(1)
24 verify(espiao, times=0).processa_elemento_exclusivo_lista2(1)
25
26 def test_deve_processar_elemento_exclusivo_lista2(self):
27 espiao = spy(SincronizadorDeListas([], [1]))
28 espiao.executa()
29
30 verify(espiao, times=0).processa_elementos_iguais(1)
31 verify(espiao, times=0).processa_elemento_exclusivo_lista1(1)
32 verify(espiao, times=1).processa_elemento_exclusivo_lista2(1)
33
34 def test_deve_processar_elemento_comum_em_ambas_as_listas(self):
35 espiao = spy(SincronizadorDeListas([1], [1]))
36 espiao.executa()
37
38 verify(espiao, times=1).processa_elementos_iguais(1)
39 verify(espiao, times=0).processa_elemento_exclusivo_lista1(1)
40 verify(espiao, times=0).processa_elemento_exclusivo_lista2(1)
41
42 def test_ambas_as_listas_com_elementos_distintos(self):
43 espiao = spy(SincronizadorDeListas([1], [2]))
44 espiao.executa()
45
46 verify(espiao, times=0).processa_elementos_iguais(1)
47 verify(espiao, times=0).processa_elementos_iguais(2)
48 verify(espiao, times=1).processa_elemento_exclusivo_lista1(1)
49 verify(espiao, times=0).processa_elemento_exclusivo_lista1(2)
50 verify(espiao, times=0).processa_elemento_exclusivo_lista2(1)
51 verify(espiao, times=1).processa_elemento_exclusivo_lista2(2)
Figura 6.18: Exemplo de teste de Objeto Espio com Python-Mockito.
93
Usos Conhecidos: As ferramenta Mockito para Java e Python-Mockito para Python so ferramentas
que disponibilizam objetos espies.
94
6.4.8 Objeto Prottipo
Tipo: Organizacional, Robustez e Testabilidade
Quando utilizar: Quando uma funcionalidade processa trechos arbitrrios de cdigo-fonte, como
ocorre quando utilizado Reexo ou Programao Orientada a Aspectos.
Inteno: Agrupar em um ou poucos objetos de uso exclusivo dos testes, diferentes prottipos de im-
plementao que sejam pertinentes para realizao dos cenrios de teste de uma funcionalidade
que trabalha com informaes do cdigo-fonte.
Motivao: Pode ser necessrio o uso de muitos objetos distintos e no relacionados para testar fun-
cionalidades que processam cdigo-fonte, principalmente quando elas so muito abrangentes. Por
exemplo, um aspecto pode ser denido para adicionar cdigo a todas as classes do sistema. Isso
pode causar diferentes tipos de problema para os testes, como set ups complexos, testes comlgica
condicional, entre outros problemas organizacionais.
Alm disso, testes que envolvem muitos mdulos de um sistema no so robustos. Alteraes de
cdigo-fonte em diversos pontos do sistema podem quebrar os testes, mesmo que a funcionalidade
que est sendo testada no tenha sido alterada.
Ainda h os casos emque os testes no podemser realizados devido indisponibilidade de objetos.
Por exemplo, comum que as APIs forneam objetos abstratos e incompletos, contendo apenas
um esqueleto de implementao (classes abstratas e Template Methods). Para esses casos, pode
ser utilizado Prottipos de Objetos em Teste ou outros Objetos Dubls.
Soluo: Os testes podem criar um ou mais objetos, visveis apenas no escopo dos testes (Objetos
Dubls), que contm prottipos de diferentes tipos de implementao, de modo que diferentes
cenrios de testes possam ser realizados.
Diferentemente dos Objetos Falsicados (Seo 6.2), o Objeto Prottipo no precisa respeitar
uma API denida rigidamente pelo sistema, a no ser que seja pertinente ao teste. De maneira
geral, ele apenas deve fornecer recursos que imitem as caractersticas de cdigo-fonte dos objetos
do sistema. Ainda, o prottipo no fornece dados ao sistema, o prprio cdigo-fonte compe as
informaes necessrias para realizao dos testes.
Outra grande diferena entre o Objeto Prottipo e outros Objetos Dubls o processo de instalao
do objeto no sistema em teste. No caso de orientao a aspectos, uma forma de instalao se d
atravs da compilao do cdigo dos testes utilizando o compilador de aspectos. Isso adicionar
o comportamento a ser testado no prottipo. J para reexo, a instalao ainda pode ser feita do
modo convencional, atravs de injeo de dependncia.
importante ressaltar que o que deve ser testado so funcionalidades do sistema, nunca os Objetos
Dubls. Sendo assim, no a implementao do prottipo que deve ser utilizada para os testes,
mas sim as informaes do seu cdigo-fonte ou trechos de cdigo que foram embutidos.
Consequncias: Todos os tipos de cdigo-fonte necessrios para os testes cam encapsulados em um
ou poucos objetos no escopo dos testes. Isso deixa os testes mais organizados, simples e robustos.
Implementao: No caso de orientao a aspectos, o prottipo deve ser um objeto simples, mas que
seja identicado pelos Pontos de Atuao (Pointcuts, Seo 6.3.4) para que os testes consigam ex-
ercitar o cdigo dos Adendos (Advices) que sero adicionados ao prottipo. Entretanto, tambm
interessante criar prottipos que no sejam identicados pelos Pontos de Atuao, justamente
para testar que eles realmente no so encontrados pelos aspectos. Para reexo, a implementao
similar, mas o objeto deve satisfazer alguma API para que as funcionalidades reexivas recon-
heam o objeto. Da mesma maneira, prottipos incompatveis com as funcionalidades tambm
95
so recomendados para realizao dos testes de casos de erros. Valor notar que, dependendo da
funcionalidade, os nomes das classes e mtodos podem descrever o que eles representam para os
testes.
Exemplo - Java: A Figura 6.19 mostra um Objeto Prottipo que pode ser utilizado para testes de difer-
entes aspectos. Se um Ponto de Atuao representa apenas os mtodos protegidos (protected),
ento o cdigo do Adendo deve ser inserido apenas no mtodo umMetodoProtegidoParaTeste.
Se o comportamento desse mtodo corresponder ao cdigo do Adendo, ento a expresso
de mapeamento do Ponto de Atuao est encontrando o trecho de cdigo desejado. No
entanto, tambm necessrio vericar que o Adendo no inserido nos outros mtodos.
Ainda, os testes do prprio Adendo pode ser vericado atravs do comportamento do mtodo
umMetodoProtegidoParaTeste.
1
2 public class PrototipoDeObjetoEmTeste {
3 public void umMetodoPublicoParaTeste() {}
4
5 protected void umMetodoProtegidoParaTeste() {}
6
7 private void umMetodoPrivadoParaTeste() {}
8
9 public void umMetodoQueLancaExcecao() throws Exception {
10 throw new Exception();
11 }
12 // ...
13 }
Figura 6.19: Objeto Prottipo.
Exemplo - Python/Unittest/Django-Dynamic-Fixture: A biblioteca Django-Dynamic-Fixture utiliza
reexo para identicar os tipos de dados esperados para cada varivel de um objeto de dados do
arcabouo Django. Depois que os tipos so identicados, a biblioteca preenche as variveis com
informaes apropriadas e do tipo esperado. A Figura 6.20 mostra alguns testes dessa ferramenta
utilizando esse padro.
Padres Relacionados: O padro Objeto Humilde 6.4.2 deve ser sempre utilizado como pr-requisito,
justamente para simplicar os casos de testes e, consequentemente, o Objeto Prottipo.
Ainda, como o objeto criado um Objeto Dubl (Seo 6.2), existem similaridades entre ele
e Objetos Stub, Mock, Falsicado e Tolo. Por exemplo, a implementao visvel apenas ao
escopo dos testes, assim como a implementao deve ser simples, fcil e rpida.
Usos Conhecidos: A ferramenta Util4Selenium, que usa aspectos (AspectJ com Java) para gerar fo-
tograas das interfaces Web, usa esse padro para testar a funcionalidade. J a biblioteca de
testes Python-QAssertions e a engine de jogos de cartas Card Game Engine tambm utilizam essa
soluo para testar os trechos de cdigo que envolvem reexo.
96
1 from django.test import TestCase
2 from django.db import models
3
4 # O mtodo new preenche as variveis do objeto com valores vlidos
5 from django_dynamic_fixture import new
6
7 class MetodoNewPreencheInstanciaComDadosTest(TestCase):
8
9 def test_preenche_integer_fields_com_inteiros(self):
10 # Objeto Prottipo
11 class UmModelo(models.Model):
12 integer_field = models.IntegerField()
13 instancia = new(UmModelo)
14 # O mtodo new identificou que a varivel esperava receber um nmero
inteiro
15 self.assertTrue(isinstance(instancia.integer_field, int))
16
17 def test_preenche_char_fields_com_strings(self):
18 # Objeto Prottipo
19 class UmModelo(models.Model):
20 char_field = models.CharField(max_length=10)
21 instancia = new(UmModelo)
22 # O mtodo new identificou que a varivel esperava receber uma string
23 self.assertTrue(isinstance(instancia.char_field, str))
Figura 6.20: Exemplo em Python de testes da biblioteca Django-Dynamic-Fixture utilizando o padro
Objeto Prottipo.
97
6.4.9 Teste por Comparao de Algoritmos
Tipo: Qualidade
Quando utilizar: Quando a funcionalidade em teste um algoritmo de alta complexidade com muitas
combinaes de dados de entrada e sada, enquanto existem algoritmos mais simples que resolvem
o mesmo problema, mas que so inviveis de serem utilizados em ambiente de produo. Por
exemplo, quando alguns algoritmos triviais para problemas complexos so extremamente lentos.
Esse padro especialmente til para vericar algoritmos de clculo de propriedades matemticas,
anlise combinatria, programao musical, computao grca etc.
Inteno: Vericar a correo de um algoritmo otimizado com base nos valores gerados por um outro
algoritmo reconhecidamente correto.
Motivao: Muitos problemas computacionais so difceis de serem resolvidos, ainda mais se o de-
sempenho e a exibilidade da soluo for imprescindvel. Alm do mais, algoritmos complexos
podem conter muitas parties de domnios, dicultando ou mesmo inviabilizando a criao de
uma bateria de testes automatizados que traga segurana quanto correo da implementao.
Soluo: Testar o algoritmo com uma grande quantidade de dados de entrada com o intuito de encontrar
algum cenrio de teste que ainda no foi vericado. Para isso, deve ser implementado um algo-
ritmo, que seja correto e fcil de implementar, para gerar os resultados esperados de um caso de
teste que sero posteriormente utilizados para comparar com os resultados obtidos pelo algoritmo
em teste.
Consequncias: O algoritmo testado com uma grande quantidade de dados, o que traz mais segurana
quanto sua correo, j que aumenta as chances de vericar alguma partio de domnio que o
desenvolvedor pode ter esquecido de testar.
Implementao: O primeiro passo implementar um algoritmo reconhecidamente correto dentro do
escopo dos testes. A prxima etapa programar para que tanto o algoritmo de controle, quanto o
algoritmo em teste sejam executados diversas vezes com os mesmos dados de entrada, para que
ento seja comparado os resultados obtidos pelos dois.
Exemplo: Na Figura 6.21 temos um algoritmo eciente para clculo do Mximo Dividor Comum
(M.D.C.) de dois nmeros inteiros. Os primeiros cenrios de testes a serem realizados devem
ser os casos mais simples, tais como combinaes de nmeros pares, mpares, nmeros primos e
nmeros primos entre si. Caso haja insegurana quanto correo do algoritmo, podemos imple-
mentar um teste de comparao de algoritmos para tentar encontrar um cenrio de teste que ainda
no foi pensado. Para esse caso, podemos utilizar um algoritmo lento, mas reconhecidamente
correto, para servir de modelo para os testes (Figura 6.22).
98
1 class MathHelper(object):
2 # Algoritmo de Euclides: mdc(a, b) = mdc(b, r) onde r: a = q * b + r
3 def mdc(self, a, b):
4 valor = max([a, b])
5 divisor = min([a, b])
6 resto = valor % divisor
7 while resto != 0:
8 valor = divisor
9 divisor = resto
10 resto = valor % divisor
11 return divisor
Figura 6.21: Algoritmo eciente para clculo do M.D.C. entre dois nmeros inteiros.
1 import random
2 import unittest
3
4 class MathHelperFake(object):
5 # Algoritmo ingenuamente lento, mas simples de implementar.
6 def mdc(self, a, b):
7 maior_divisor_possivel = min((a, b))
8 divisor_comum = 1
9 for i in range(1, maior_divisor_possivel+1):
10 if a % i == 0 and b % i == 0:
11 divisor_comum = i
12 return divisor_comum
13
14 class MathHelperTest(unittest.TestCase):
15 def setUp(self):
16 self.fake = MathHelperFake()
17 self.math_helper = MathHelper()
18
19 def test_aleatorio_por_comparacao_de_algoritmo_do_calculo_de_mdc(self):
20 for i in range(1, 10):
21 a = random.randint(1, 1000000)
22 b = random.randint(1, 1000000)
23 expected_value = self.fake.mdc(a, b)
24 value = self.math_helper.mdc(a, b)
25 self.assertEquals(expected_value, value)
Figura 6.22: Exemplo de Teste por Comparao de Algoritmos.
99
6.4.10 Teste por Probabilidade
Tipo: Robustez e Qualidade
Quando utilizar: Quando o que est sendo testado possui comportamento aleatrio. Esta situao
tpica em jogos e algoritmos de segurana, tais como gerao de senhas aleatrias e algoritmos de
criptograa que utilizam, em alguma etapa, nmeros pseudo-aleatrios.
Inteno: Denir o resultado nal de um teste baseado nos resultado de diversas execues de um teste
intermitente.
Motivao: Funcionalidades que produzem resultados aleatrios so difceis de serem testadas, pois os
resultados esperados no so previsveis. Tentar prever os resultados leva ao indcio de antipadro
Testes Intermitentes (Seo 5.2).
Soluo: Executar um mesmo caso de teste diversas vezes e denir se o teste aceito de acordo com a
porcentagem de sucesso.
Consequncias: denido, de forma vivel, o resultado de um caso de teste baseado na probabilidade
de sucesso de uma vericao. Os testes continuaro sendo teoricamente intermitentes, mas, na
prtica, robusto como outro qualquer.
Implementao: Antes de utilizar este padro, importante refatorar o sistema ou tentar utilizar o
padro Objeto Humilde (Seo 6.4.2) para isolar o comportamento aleatrio de uma funcionali-
dade. Isso poder facilitar a escrita dos Testes por Probabilidade ou at mesmo evit-los.
Dado que necessrio utilizar esse padro, ento necessrio executar o teste uma quantidade
determinada de vezes (um lao simples) e armazenar os resultados de todas as execues (uma
lista com os resultados), para no nal, calcular a razo de sucesso sobre fracasso e comparar com a
probabilidade desejada (uma conta e comparao simples). Idealmente, esse algoritmo deve estar
integrado ao arcabouo de teste para seguir as convenes e enriquecer o relatrio da bateria dos
testes, embora seja possvel implement-lo de maneira independente, como mostrado na Figura
6.23.
Exemplo - Java/JUnit/TestNG: Aimplementao no complexa, mas pode tornar o cdigo dos testes
obscuro, outro indcio de antipadro. Por isso, importante abstrair o conceito do Teste por
Probabilidade de forma que que transparente para os testes que o utilizam. Contudo, existem
arcabouos que j fornecem essa implementao e facilitam a utilizao deste padro. A Figura
6.24 mostra um exemplo de teste de uma funcionalidade tpica em jogos de cartas, embaralhar
uma pilha de cartas. O exemplo escrito em Java e utiliza o arcabouo TestNG, que permite criar
facilmente testes por probabilidade atravs de metadados.
Padres Relacionados: O padro Objeto Humilde (Seo 6.4.2) til para separar o que for possvel
da lgica aleatria do resto da lgica de uma funcionalidade. Tambm, Testes por Probabilidade
podem ser usados em conjunto com Testes de Sanidade (Seo 3.4.3) para possibilitar fazer ver-
icaes mais rgidas, assim, o padro tambm pode ser utilizado com o intuito de garantir a
qualidade do sistema.
Usos Conhecidos: O arcabouo de testes TestNG fornece uma maneira simples de congurar testes
baseados na probabilidade de sucesso.
100
1 public class TestePorProbabilidadeImplTests {
2
3 public void testePorProbabilidade() {
4 // Implementao do teste
5 }
6
7 // Teste ser executado 20 vezes.
8 // Se 8 ou mais vezes (>= 80%) passar, resultado encarado como sucesso.
9 // Caso contrrio, encarado como falha.
10 @Test
11 public void testePorProbabilidadeDecorator() {
12 int QTDE_EXECUCOES = 20;
13 int PORCENTAGEM_DE_SUCESSO_ESPERADA = 80;
14
15 int quantidadeDeSucessos = 0;
16 for(int i = 0; i < 20; i++) {
17 try {
18 testePorProbabilidade();
19 quantidadeDeSucessos++;
20 } catch(Exception e) {
21 }
22 }
23 int porcentagemDeSucesso = 100 * quantidadeDeSucessos / QTDE_EXECUCOES;
24 if(porcentagemDeSucesso < PORCENTAGEM_DE_SUCESSO_ESPERADA)
25 throw new RuntimeException(
26 "Falhou mais do que o esperado: " +
27 porcentagemDeSucesso + "%");
28 }
29 }
Figura 6.23: Exemplo de teste que verica a correo de um teste pela probabilidade.
101
1 //Referncias do TestNG
2 import org.testng.annotations.Test;
3 //Referncias do JUnit + Hamcrest
4 import static org.junit.Assert.*;
5 // Custom Matcher: isNotSorted
6 import static QAMatchers.*;
7
8 public class PilhaDeCartasTests {
9
10 // Teste ser executado 20 vezes.
11 // Se 8 ou mais vezes (>= 80%) passar, resultado encarado como sucesso.
12 // Caso contrrio, encarado como falha.
13 @Test(invocationCount = 20, successPercentage = 80)
14 public void embaralharDeveMisturarAsCartasEmUmaOrdemAleatoria() {
15 PilhaDeCartas pilhaDeCartas = new PilhaDeCartas();
16 pilhaDeCartas.adiciona(new Carta(1, 1));
17 pilhaDeCartas.adiciona(new Carta(2, 2));
18 pilhaDeCartas.adiciona(new Carta(3, 3));
19 pilhaDeCartas.embaralha();
20 // Verifica que NO est ordenado.
21 // Intermitente: A funo embaralha pode deixar o baralho organizado
22 assertThat(pilhaDeCartas.getCartas(), isNotSorted(Carta.comparadorPorNaipeValor
()));
23 }
24 }
Figura 6.24: Exemplo de teste que verica a correo de um teste pela probabilidade.
102
6.4.11 Vericar Inversibilidade
Tipo: Qualidade
Quando utilizar: Ao testar duas funes do sistema que precisam ser exatamente uma inversa da outra.
Tipicamente em testes de funes matemticas bijetoras, funcionalidades de importao e expor-
tao de dados, voltar e refazer aes, alm de efeitos de imagem e som que so inversveis.
Inteno: Vericar a existncia de erros de incompatibilidade entre uma funo bijetora e sua inversa.
Motivao: Duas funcionalidades podem ser individualmente corretas, mas ao trabalharem como inver-
sas so incompatveis. Vrios erros podem ser cometidos, especialmente em pequenos detalhes
que passam despercebidos, tais como caracteres invisveis em strings, diferenas de arredonda-
mento em pontos utuantes e at mesmo a ordem de elementos idnticos em listas ordenadas, que
podem ser diferentes quando so utilizados algoritmos de ordenao instveis.
Soluo: Criar cenrios de testes que comparem os resultados produzidos por duas funes que so
inversas entre si, sendo que os dados de entrada de uma das funes so os dados de sada da
outra.
Consequncias: vericado se as implementaes de duas funes teoricamente inversas entre si po-
dem ser utilizadas na prtica, sem incompatibilidade.
Implementao: A ideia do teste executar as duas funcionalidades supostamente inversas entre si
f e f
1
, sendo que uma processar um dado qualquer x e a outra receber como dados de entrada
os dados de sada produzida pela primeira, f (x). Assim, temos: y = f
1
( f (x)). Se x = y, ento o
teste tido como sucesso, caso contrrio, uma falha.
Exemplo - Java/JUnit/Hamcrest: A Figura 6.25 mostra um algoritmo simples de criptograa e de-
scriptograa, que so duas funcionalidades necessariamente inversas. Caso contrrio, o usurio
poder perder dados criptogrados importantes porque no conseguir recuper-los. Note que,
propositalmente, um detalhe da implementao do mtodo de descriptograa foi comentado para
enfatizar o caso de teste de inversibilidade (Figura 6.26).
Exemplo - Python/UnitTest/QAssertions: A implementao do teste de inversibilidade simples de
ser feito e no suja o cdigo-fonte. No entanto, possvel criar mtodos de assero que abstraem
o objetivo do teste, o que til para enfatizar o que est sendo testado e tambm para lembrar e
incentivar a realizao deste tipo de teste. A Figura 6.27 mostra um exemplo com a ferramenta
Python-QAssertions. O mtodo de assero recebe os dois mtodos que teoricamente so funes
inversas entre si e os argumentos que sero passados para as funes em si. A ferramenta executa
os dois mtodos apropriadamente e faz as comparaes apropriadas.
Padres Relacionados: Se a quantidade de argumentos que podem ser passados para as funes in-
nita, ento impossvel provar com testes automatizados, que duas funcionalidades so inversas
entre si. Por isso, interessante que sejam feitas vericaes com diversos argumentos. Para isso,
pode-se utilizar os padres Teste de Sanidade (Seo 3.4.3) e Testes Aleatrios (Seo 3.4.1) para
gerar argumentos para vericao de inversibilidade.
Usos Conhecidos: A ferramenta Python-QAssertions implementa um mtodo de assero
(assertFunctionsAreInversible) que realiza este tipo de vericao.
103
1 import java.util.Random;
2
3 public class Criptografador {
4 private static final int _RANDOM_NUMBER = 10;
5
6 public String criptografar(String senha, String texto) {
7 Random random = new Random(senha.hashCode());
8 byte[] bytes = texto.getBytes();
9 for(int i = 0; i < bytes.length; i++) {
10 bytes[i] = (byte) (bytes[i] + random.nextInt(_RANDOM_NUMBER));
11 }
12 return "!!" + new String(bytes) + "!!";
13 }
14
15 public String descriptografar(String senha, String texto) {
16 // Precisa descomentar a linha abaixo para que
17 // as funes criptografar e decriptografar sejam inversas entre si.
18 // texto = texto.replaceFirst("^!!", "").replaceFirst("!!$", "");
19 Random random = new Random(senha.hashCode());
20 byte[] bytes = texto.getBytes();
21 for(int i = 0; i < bytes.length; i++) {
22 bytes[i] = (byte) (bytes[i] - random.nextInt(_RANDOM_NUMBER));
23 }
24 return new String(bytes);
25 }
26 }
Figura 6.25: Algoritmo ingnuo de criptografar and descriptografar textos.
104
1 //Referncias do JUnit + Hamcrest
2 import org.junit.*;
3 import static org.junit.Assert.*;
4 import static org.hamcrest.Matchers.*;
5
6 public class CriptografiaSimplesTests {
7 Criptografador c;
8
9 @Before
10 public void inicializaVariaveis() {
11 c = new CriptografadorSimples();
12 }
13
14 @Test // Sucesso.
15 public void testeCriptografar() {
16 String texto = "abcdefghijk";
17 String criptografado = c.criptografar("senha123", texto);
18 assertThat(criptografado, equalTo("!!jddhfgkplmk!!"));
19 }
20
21 @Test // Sucesso.
22 // Dependendo do requisito do cliente, pode ser um falso positivo.
23 public void testeDescriptografar() {
24 String criptografado = "jddhfgkplmk";
25 String decriptografado = c.decriptografar("senha123", criptografado);
26 assertThat("abcdefghijk", equalTo(decriptografado));
27 }
28
29 @Test // Falha.
30 // As funes criptografar e descriptografar no so inversas entre si.
31 public void criptografarInversaDeDescriptografar() {
32 String texto = "abc";
33 String criptografado = c.criptografar("senha123", texto);
34 String descriptografado = c.descriptografar("senha123", criptografado);
35 assertThat(texto, equalTo(descriptografado));
36 }
37 }
Figura 6.26: Teste de inversibilidade dos algoritmos de criptograa e descriptograa.
1 # Referncia do UnitTest
2 import unittest
3 # Referncia do Python-QAssertions
4 import qassertions as qa
5
6 class InversibilidadeTests(unittest.TestCase):
7
8 def testFuncaoCriptInversaDeDecript(self):
9 c = Criptador("senha123")
10 # qa.assertFunctionsAreInversible(mtodo1, mtodo2, argumento)
11 qa.assertFunctionsAreInversible(c.cript, c.decript, "texto")
Figura 6.27: Assero de Inversibilidade da ferramenta Python-QAssertions.
105
6.4.12 Vericar Valores Limites
Tipo: Qualidade
Quando utilizar: Emtestes de algoritmos que trabalhamcomintervalos de valores de dados de entrada,
sada ou, at mesmo, de variveis locais. O uso tpico em algoritmos com clculos puramente
matemticos, laos complexos, vetores e matrizes, conjuntos de dados ordenaveis, pontos utu-
antes etc.
Inteno: Vericar erros de programao causados pelos valores limites dos intervalos de dados que o
algoritmo trabalha.
Motivao: Estudos mostram que erros em valores limites so frequentes [95]. Erros de validao de
dados, falhas de segmentao, laos innitos, diviso por zero etc. Alm disso, erros de valores
limites podem ser acarretados devido interpretao incorreta de requisitos denidos de forma
ambgua ou no clara pelos clientes.
Soluo: Testar as funcionalidades de acordo com os dados extremos de entrada e sada.
Consequncias: feito a preveno contra erros causados por valores extremos.
Implementao: A implementao dos testes de valores limites no necessitam de solues especi-
ais, apenas os valores de entrada e sada so escolhidos cuidadosamente para forar clculos e
comparaes especcos.
Exemplo - C/CUnit: A Figura 6.28 mostra uma funcionalidade escrita em C que faz a multiplicao
de matrizes de inteiros. A implementao, apesar de curta, possui muitos detalhes sutis, o que
aumenta as chances do programador cometer erros conceituais ou por distrao, tais como trocas
de variveis e erros de precedncia de operadores. Alm do mais, essa uma funo que aceita
uma combinao innita de dados de entrada, o que torna impossvel provar sua correo atravs
de testes automatizados, embora possvel criar uma boa bateria de testes que d segurana na
funcionalidade.
1 /*
2 Matrizes de inteiros A, B e C
3 C(m x o) = A(m x n) * B(n x o)
4 Retorna 0 se sucesso, negativo caso contrrio
5 */
6 int matrizXmatriz(int **A, int m, int n, int **B, int o, int **C){
7 int i, j, k;
8 if(m < 1 || n < 1 || o < 1) return -1;
9 for(i = 0; i < m; i++) {
10 for(j = 0; j < o; j++) {
11 C[i][j] = 0;
12 for(k = 0; k < n; k++)
13 C[i][j] = C[i][j] + (A[i][k] * B[k][j]);
14 }
15 }
16 }
Figura 6.28: Funo escrita em C que calcula a multiplicao de matrizes.
Para essa funcionalidade, problemas de valores limites podem ocorrer tanto com os dados de
entrada como os de sada. A Figura 6.29 mostra alguns dos testes que podem ser feitos para
106
vericar esse tipo de erro. O exemplo utiliza a ferramenta CUnit, mas mostra apenas os cenrios
de teste. No Apndice B h mais informaes sobre a ferramenta, em particular, como executar
os testes com o arcabouo.
1 /* Referncias do CUnit, outras referncias foram ocultas */
2 #include <CUnit/CUnit.h>
3
4 /* Funes auxiliares: Implementao oculta para simplificar o exemplo */
5 /* A = B = C|0 ... 0|
6 |0 ... 0| ... */
7 void inicializaMatrizesZeradas(int** A, int m, int n, int** B, int o, int** C) {}
8
9 /* A|a b| B|e f| C|0 0|
10 |c d| |g h| |0 0| */
11 void inicializaMatrizesDoisPorDoisComValores(int** A, int a, int b, int c, int d,
int** B, int e, int f, int g, int h, int** C) {}
12
13 void verificaMatrizDoisPorDois(A, a, b, c, d) {
14 CU_ASSERT_EQUAL(A[0][0], a);
15 CU_ASSERT_EQUAL(A[0][1], b);
16 CU_ASSERT_EQUAL(A[1][0], c);
17 CU_ASSERT_EQUAL(A[1][1], d);
18 }
19
20 /* TESTES */
21
22 /* Funo se comporta bem com zeros? */
23 void test_ValoresLimitesDosCalculos(void) {
24 int **A, **B, **C;
25 inicializaMatrizesDoisPorDois(A, 0, 1, 0, 1, B, 1, 0, 1, 0, C);
26 int conseguiuCalcular = matrizXmatriz(A, 2, 2, B, 2, C);
27 CU_ASSERT_TRUE(conseguiuCalcular == 0);
28 verificaMatrizDoisPorDois(C, 1, 1, 1, 1);
29 }
30
31 /* E com nmeros negativos? */
32 void test_ValoresLimitesDosCalculos(void) {
33 int **A, **B, **C;
34 inicializaMatrizesDoisPorDois(A, 1, -1, 1, -1, B, -1, 1, -1, 1, C);
35 int conseguiuCalcular = matrizXmatriz(A, 2, 2, B, 2, C);
36 CU_ASSERT_TRUE(conseguiuCalcular == 0);
37 verificaMatrizDoisPorDois(C, 1, 1, 1, 1);
38 }
39
40 /* Resultados (dados de sada) devem pertencer ao intervalo dos inteiros */
41 void test_ValoresLimitesDosResultados(void) {
42 int **A, **B, **C;
43 inicializaMatrizesDoisPorDois(A, INT_MAX, INT_MAX, INT_MAX, INT_MAX, B, 2, 2, 2,
2, C);
44 int conseguiuCalcular = matrizXmatriz(A, 2, 2, B, 2, C);
45 CU_ASSERT_TRUE(conseguiuCalcular < 0);
46 }
Figura 6.29: Teste da multiplicao de matrizes usando a biblioteca CUnit.
Exemplo - Scala/JUnit/TestNG: Contudo, esses tipos de erros podem acontecer at com algoritmos
mais simples e que utilizam linguagens de programao de mais alto nvel. A Figura 6.30 mostra
107
um exemplo de testes escritos em Scala com JUnit e TestNG para o jogo de carta Poker. As regras
do jogo denem uma hierarquia simples de combinaes de cartas, mas que programaticamente
pode conter erros nos valores limites das regras.
1 // Referncias do TestNG e JUnit
2 import org.testng.annotations._
3 import org.junit.Assert._
4 // Imports das classes do sistema foram ocultos
5
6 // Exemplos de testes de valores limites para o jogo de cartas Poker
7 // Obs: Nomes dos mtodos de testes definem parte das regras do jogo
8 class ComparacaoEntreCombinacoesLimitesTests {
9
10 @Test def menorParGanhaDeMaiorCartaMaisAlta() {
11 assertTrue(menorPar() > maiorCartaMaisAlta())
12 assertTrue(maiorCartaMaisAlta() < menorPar())
13 }
14
15 @Test def menorDoisParesGanhaDeMaiorPar() {
16 assertTrue(menorDoisPares() > maiorPar())
17 assertTrue(maiorPar() < menorDoisPares())
18 }
19
20 @Test def menorTrincaGanhaDeDeMaiorDoisPares() {
21 assertTrue(menorTrinca() > maiorDoisPares())
22 assertTrue(maiorDoisPares() < menorTrinca())
23 }
24
25 @Test def menorSequenciaGanhaDeDeMaiorTrinca() {
26 assertTrue(menorSequencia() > maiorTrinca())
27 assertTrue(maiorTrinca() < menorSequencia())
28 }
29
30 @Test def menorTodasMesmoNaipeGanhaDeDeMaiorSequencia() {
31 assertTrue(menorTodasMesmoNaipe() > maiorSequencia())
32 assertTrue(maiorSequencia() < menorTodasMesmoNaipe())
33 }
34
35 @Test def menorFullHouseGanhaDeDeMaiorTodasMesmoNaipe() {
36 assertTrue(menorFullHouse() > maiorTodasMesmoNaipe())
37 assertTrue(maiorTodasMesmoNaipe() < menorFullHouse())
38 }
39
40 @Test def menorQuadraGanhaDeDeMaiorFullHouse() {
41 assertTrue(menorQuadra() > maiorFullHouse())
42 assertTrue(maiorFullHouse() < menorQuadra())
43 }
44
45 @Test def menorSequenciaTodasMesmoNaipeGanhaDeDeMaiorQuadra() {
46 assertTrue(menorSequenciaTodasMesmoNaipe() > maiorQuadra())
47 assertTrue(maiorQuadra() < menorSequenciaTodasMesmoNaipe())
48 }
49 }
Figura 6.30: Teste escrito em Scala dos valores limites das regras do Poker.
Exemplo - Python/UnitTest/QAssertions: Ainda, existem ferramentas que geram testes automatiza-
dos para vericar valores limites em regras de validao de dados de entrada. o caso da
108
Python-QAssertions, que fornece o mtodo de vericaao assertValidation. Esse mtodo
recebe como argumentos o prprio mtodo em teste e os parmetros que sero utilizados para
sua execuo. Se os parmetros forem objetos herdados da classe ValidationTest (Min, Max,
Positive, Negative, Range, InList, NotInList, Blank e NonBlank), ento o algoritmo iden-
tica que necessrio vericar valores limites para determinado parmetro, de acordo com o tipo
de validao.
Por exemplo, se um parmetro for Range(56, 790) (Figura 6.31), sero gerados os testes para
valores os 56 e 790, onde esperado sucesso, ou seja, nenhuma exceo lanada. Tambm so
feito testes para os valores 55 e 791, para os quais so esperadas excees. No obstante, ainda
so feitos testes com outros valores menos signicativos, tais como 423 (esperado sucesso), 46 e
800 (esperado falha).
1 # Referncias do UnitTest
2 import unittest
3 # Referncias do Python-QAssertions
4 import qassertions as qa
5 from qassertions import Range
6
7 class UmaClasseDoSistemaTests(unittest.TestCase):
8
9 def setUp(self):
10 self.sistema = UmaClasseDoSistema()
11
12 def testValorTemQueSerMaiorOuIgualQue56MenorOuIgualQue790(self):
13 qa.assertValidation(self.sistema.metodoEmTeste, Range(56, 790))
Figura 6.31: Exemplo de vericao de validao com casos limites com gerao de casos de teste.
AFigura 6.32 mostra como poderiamcar a implementao dos testes semusar a gerao de casos
de teste de validao. Mesmo para os testes de validao de apenas umparmetro a implementao
ca mais extensa. Consequentemente, quanto mais parmetros precisam ser validados, maior a
vantagem do uso da ferramenta. A Figura 6.33 mostra um exemplo de um teste de validao de
vrios argumentos. imporante notar que os valores limites so denidos subtraindo e somando 1
dos limites do intervalo, mas tambm pode-se alterar a preciso para outros valores, como mostra
a validao Max no exemplo da gura.
Usos Conhecidos: A teoria de testes de software incentiva o uso desse padro [95]. A ferramenta
Python-QAssertions que fornece um mtodo de assero que gera testes de valores limites. API
para criao de jogos de cartas Card Game Engine, que realiza esses testes para vericar erros de
implementao.
109
1 # Referncias do UnitTest
2 import unittest
3 # Referncias do Python-QAssertions
4 import qassertions as qa
5
6 class UmaClasseDoSistemaTests(unittest.TestCase):
7
8 def setUp(self):
9 self.sistema = UmaClasseDoSistema()
10
11 def testValorTemQueSerMaiorOuIgualQue56MenorOuIgualQue790(self):
12 self.assertRaises(Exception, self.sistema.metodoEmTeste, 46)
13 qa.assertDontRaiseAnException(self.sistema.metodoEmTeste, 56)
14 self.assertRaises(Exception, self.sistema.metodoEmTeste, 55)
15 qa.assertDontRaiseAnException(self.sistema.metodoEmTeste, 423)
16 qa.assertDontRaiseAnException(self.sistema.metodoEmTeste, 790)
17 self.assertRaises(Exception, self.sistema.metodoEmTeste, 791)
18 self.assertRaises(Exception, self.sistema.metodoEmTeste, 800)
Figura 6.32: Exemplo de vericao de validao com casos limites sem gerao dos casos de teste.
1 # Referncias do UnitTest
2 import unittest
3 # Referncias do Python-QAssertions
4 import qassertions as qa
5 # Tipos de validao:
6 # Nmeros: Min, Max, Positive, Negative, Range
7 # Listas: InList, NotInList
8 # Strings: Blank, NonBlank
9 from qassertions import Min, Max, Range, InList, NotInList, Blank, NonBlank
10
11 class UmaClasseDoSistemaTests(unittest.TestCase):
12
13 def setUp(self):
14 self.sistema = UmaClasseDoSistema()
15
16 def testValidacaoDeVariosDadosDeEntrada(self):
17 qa.assertValidation(self.sistema.metodoEmTeste2,
18 Min(5), Max(7, 0.1), valor sem regra de validao,
19 Range(5, 10), InList([1, 5, 7]))
Figura 6.33: Exemplo de vericao de validao com casos limites para diversos parmetros.
110
6.5 Antipadres
A seguir sero descritos antipadres de automao para testes de unidade, de acordo com o esqueleto
denido na Seo 5.4. Os indcios de problemas citados nos padres possuem mais informaes na
Seo 5.2.
6.5.1 Gancho para os Testes (Test Hook)
Tipo: Testabilidade
Contexto: Testar um sistema pode ser muito complexo, principalmente quando os mdulos e objetos
esto muito acoplados entre si, como discutido na Seo 10.3. Quando no possvel substituir
nem parte do comportamento do sistema atravs de Objetos Dubls, os testes podem se tornar
inviveis de serem realizados. Uma soluo simples modicar o prprio comportamento do
sistema apenas para a execuo dos testes, ou seja, feito um gancho no sistema para torn-lo
testvel.
Apesar de simples, essa soluo ruim porque ela polui o cdigo do sistema, tornando-o mais ex-
tenso e complexo. Isso aumenta as chances do sistema conter erros, que vai completamente contra
o objetivo dos testes automatizados. No obstante, essa soluo ainda pode inibir refatoraes para
melhorar o design do sistema.
Exemplo: A implementao tpica a criao de uma ag para indicar que so os testes que esto
executando o sistema. Se forem os testes, ento executado o trecho de cdigo substituto e
testvel do sistema, como exibido na Figura 6.34.
1 // Antipadro: Gancho para os Testes (Test Hook)
2 public class UmaClasseDoSistema {
3 public boolean TESTANDO = false;
4 // ...
5 public void umaFuncionalidadeComBaixaTestabilidade() {
6 if(TESTANDO) {
7 // Simule algo de forma isolada e controlada para os testes ...
8 }
9 else {
10 // Faa o que deve ser feito ...
11 }
12 }
13 // ...
14 }
Figura 6.34: Antipadro Gancho para os Testes.
Indcios de Problemas Relacionados: Hard-to-Test Code, Test Logic in Production e Production Bugs
(vide Seo 5.2).
Referncias: Esse antipadro foi identicado por Meszaros como um padro [99]. No entanto, ele
explica que essa abordagem deve ser utilizada apenas em casos excepcionais, quando invivel
refatorar o sistema para aumentar a testabilidade.
111
6.5.2 Testes Encadeados (Chained Tests)
Tipo: Organizacional
Contexto: normal que alguns casos de testes sejam parecidos e possuam trechos de cdigo auxiliares
em comum. Por isso, refatoraes para diminuir a replicao de cdigo-fonte deve ser uma tarefa
rotineira durante a criao dos testes automatizados.
Uma situao comum, que umcaso de teste seja muito parecido como mtodo de set up de outro,
isso porque os testes podem ser complementares. Uma possvel soluo para evitar replicao de
cdigo para este caso, fazer com que ambos os testes compartilhem as mesmas variveis e sejam
executados em sequncia, de forma encadeada.
Entretanto, essa soluo incentiva o uso de informaes compartilhadas entre os testes e, conse-
quentemente, dependentes entre si, frgeis, difceis de serem entendidos e mantidos. Alm disso,
essa abordagem pode at inviabilizar o uso de ferramentas que otimizam a bateria de testes como
um todo, por meio de ferramentas que paralelizam a execuo dos testes. Se uma funcionalidade
dependente de outra, pode-se utilizar Objetos Dubls para tornar os testes independentes.
Exemplo/Java/TestNG: A Figura 6.35 mostra um exemplo de teste com a ferramenta TestNG que
possui funcionalidades para criar testes encadeados.
1 //Referncias do TestNG
2 import org.testng.annotations.Test ;
3
4 public class UmaClasseDeTest {
5
6 @Test
7 public void teste1() {
8 }
9
10 // Antipadro: Testes Encadeados (Chained Tests)
11 // Esse teste s ser executado depois do que o teste1 tenha sido executado.
12 @Test(dependsOnMethods="teste1")
13 public void teste2() {
14 }
15 }
Figura 6.35: Um exemplo de esqueleto de cdigo Java do antipadro Testes Encadeados.
Indcios de Problemas Relacionados: Obscure Test, Assertion Roulette, Erratic Test, Fragile Test,
Frequent Debugging, Slow Tests, Buggy Tests, High Test Maintenance Cost (vide Seo 5.2).
Referncias: Esse antipadro foi identicado por Meszaros como um padro [99]. Em casos excep-
cionais, esse antipadro pode ser til em testes de integrao, mas desde que ele seja utilizado
com cautela.
112
Captulo 7
Testes com Persistncia de Dados
Controlar e garantir a qualidade da camada de persistncia de dados fundamental, no apenas devido
ao valor da informao, mas tambm porque dados inconsistentes podem afetar a correo das outras
camadas do sistema [64].
Falhas com os dados podem desencadear uma innidade de situaes indeterminadas de erros no
sistema que gerencia a camada de persistncia. As camadas superiores ao mdulo de dados so imple-
mentadas para trabalhar com dados corretos, ou seja, no esto preparadas para lidar com situaes onde
os dados no seguem os formatos e as convenes denidas.
Quando esses erros so identicados antes da causa principal do problema, o processo de identi-
cao e correo das falhas se torna um trabalho ainda mais complexo e demorado. O prprio sistema,
ou at mesmo o usurio nal, pode ser induzido a criar novos dados problemticos, o que, talvez, resulte
em um ciclo automtico de adio de erros e na perda da credibilidade dos dados armazenados.
Por causa da gravidade que os problemas nos dados podem ter, muitas empresas possuem depar-
tamentos exclusivos de especialistas para implementar e gerenciar a camada de persistncia de dados.
Contudo, mesmo os especialistas na rea e as ferramentas de persistncia de dados no garantem que
todas as situaes propcias a erros sejam vericadas a cada alterao do sistema.
A camada de persistncia pode possuir muitos pontos suscetveis a falhas. Basicamente, a camada
composta por funcionalidades de escrita e leitura dos dados, que, geralmente, so implementadas com a
ajuda de APIs e arcabouos, mas o uso destas ferramentas e a criao da lgica de leitura e escrita nem
sempre so tarefas triviais.
Este captulo ir descrever alguns padres e tcnicas de automao de testes para aumentar a produ-
tividade e tornar os testes mais rpidos e robustos. Alm disso, sero discutidos as situaes tpicas de
cenrios de testes tanto para sistema de arquivos quanto para bancos de dados.
7.1 Banco de Dados
Para vericar a correo da camada de persistncia com banco de dados pode ser necessrio tanto testes
de unidade como de integrao. Basicamente, a escolha do tipo de teste depende do que se est querendo
vericar, mas a regra geral utilizar os testes de unidade sempre que possvel e fazer testes de integrao
para completar a bateria de vericaes.
Entretanto, antes de denir os tipos de testes, necessrio entender o que interessante de ser veri-
cado. A camada de persistncia de dados pode ter diversos trechos de cdigo suscetveis a erros, alm
de que os tipos de erros podem variar de acordo com os arcabouos utilizados. Por exemplo, sistemas
que possuem queries hardcoded no cdigo-fonte so muito suscetveis a erros sintticos. J para os
sistemas que utilizam arcabouos de ORM
1
, so comuns problemas de desempenho, inconsistncia de
1
Arcabouos de ORM (Object-Relational Mapping) mapeiam objetos para estrutura de banco de dados relacionais.
113
dados causados por refatoraes etc.
No caso de sistemas integrados com arcabouos ORM, algumas funcionalidades podem ser veri-
cadas com testes de unidade. Tanto as vericaes de sintaxe quanto as de lgica da aplicao podem
ser isoladas. Alm disso, alguns arcabouos disponibilizam bibliotecas especcas com Objetos Dubls
e mtodos de vericao para facilitar a criao de testes automatizados de unidade para testar o mapea-
mento dos objetos para a camada de persistncia.
J para vericar a semntica de queries, imprescindvel que os testes sejam integrados, pois elas
precisam ser interpretadas pelos gerenciadores de banco de dados. Alm disso, para testar uma query
preciso observar os efeitos colaterais causados na base de dados, ou seja, o teste verica justamente a
integrao das funcionalidades camada de persistncia.
Contudo, importante notar que existem diversos arcabouos que geram algumas queries auto-
maticamente. Estas no precisam ser vericadas, pois responsabilidade da equipe que desenvolveu o
arcabouo avaliar se elas esto sendo geradas corretamente. Assim como para todos os tipos de testes de
todas as camadas, deve-se testar apenas o sistema de interesse, dispensando as suas dependncias. Uma
situao excepcional quando h interesse em vericar o comportamento do sistema sob a ao de erros
conhecidos dos arcabouos.
No obstante, a camada de persistncia possui diversas particularidades que podem trazer dicul-
dades para automao de testes. Entre elas esto o compartilhamento de dados, sistema de conexes
de usurios, nveis e permisses de acesso, replicao da bases de dados e auditoria. No decorrer desta
seo sero discutidas algumas prticas e padres para criar testes automatizados robustos para camadas
de persistncia com banco de dados.
7.1.1 Congurao do Ambiente de Teste
Os testes de unidade da camada de persistncia so semelhantes aos de outras camadas. Sendo assim, as
dependncias devem ser substitudas sempre que possvel por Objetos Dubls para que os testes sejam
isolados. J os testes de integrao dependem da congurao e execuo correta dos ambientes e dos
gerenciadores de banco de dados necessrios. Todavia, a forma de organizao do ambiente reete
diretamente na eccia e na produtividade dos testes automatizados, por isso importante conhecer as
abordagens de congurao do ambiente.
Bancos de Dados Compartilhados
comum que empresas possuam um ou mais ambientes prprios para realizao de testes (geralmente
manuais), que so normalmente conhecidos como ambientes de desenvolvimento, de homologao ou
de garantia de qualidade. Estes ambientes so idealmente semelhantes ao de produo e teis para
a realizao de testes que integram todos os mdulos do sistema e suas dependncias. Como estes
ambientes geralmente so de alto custo, vrios departamentos e projetos acabam compartilhando os
recursos e as bases de dados.
Uma das principais vantagens desse ambiente para realizao de testes que ele prximo do
real, o que d maior credibilidade s vericaes e possibilita a criao de cenrios de testes is aos
comportamentos de usurios reais. Os testes realizados nesse ambiente tambm so teis para evitar
e identicar problemas de instalao, congurao e de portabilidade, que so aqueles que podem ser
associados frase: Mas no meu ambiente funcionava!.
Outra vantagem que a base de dados normalmente importada do ambiente real de produo, o
que permite que os testes sejam feitos com dados reais de usurios. Alm disso, o uso dos dados j
existentes pode facilitar a criao dos testes, pois dispensa parte da tarefa de preparar os dados para
execuo dos testes. A criao do set up dos testes que envolvem banco de dados exigem, via de regra,
um trabalho rduo de implementao, principalmente quando a modelagem do banco muito complexa.
114
No entanto, necessrio um esforo para pesquisa e avaliao dos dados antes que eles sejam utiliza-
dos para os testes, o que pode ser mais custoso do que a criao de novos dados. Alm disso, dicilmente
os dados pesquisados podero ser reutilizados no futuro, j que tanto os prprios testes quanto outras
pessoas podem modicar os dados.
No obstante, mesmo com as outras vantagens citadas, esse tipo de ambiente deve ser evitado para
grandes baterias de testes, sejam eles automatizados ou manuais. Ambientes compartilhados trazem in-
meras diculdades ao processo de criao, manuteno e execuo dos testes, tornando a produtividade
muito baixa.
Uma das diculdades deve-se preocupao aos dados j existentes e aos criados pelos casos de
teste. necessrio um esforo adicional para organizar e controlar os ambientes e as equipes para que
a base de dados no seja degradada com a utilizao. Mesmo assim, muito difcil manter o ambiente
estvel por muito tempo, pois muitos testes precisam criar cenrios crticos. Por exemplo, podem exigir
mudanas de congurao, gerao de dados invlidos para testes, base de dados vazia, entre outras.
Outro problema difcil de resolver a execuo concorrente de testes em um ambiente compartil-
hado, sejam eles testes de um mesmo projeto ou de projetos diferentes. Os testes no possuem o conceito
de transao, dessa forma, os comandos so executados no gerenciador de banco de dados de forma in-
determinada. Isso resulta em testes intermitentes e erros difceis de depurar. Para ilustrar, enquanto
um teste pode estar inserindo dados para vericao, outro pode estar limpando a base para preparar o
ambiente.
Ainda, a produtividade da vericao do sistema em teste tambm prejudicada devido reduo
do desempenho dos testes. A memria e o poder de processamento do ambiente so compartilhados
entre diversos usurios que podem estar realizando operaes demoradas e que exigem muitos recursos.
Alm disso, medida que os testes vo deixando resduos de dados na base, as queries de busca vo se
tornando cada vez mais lentas.
Por estas caractersticas, a relao custo/benefcio de se automatizar os testes nesse tipo de ambiente
no vantajoso. O cdigo dos testes tende a car mais extenso e complexo para que eles quem mais
robustos. Ainda assim, os testes so mais sucestveis a serem frgeis, lentos e intermitentes do que se
forem executados em outros tipos de ambientes, como veremos nas prximas subsees.
De qualquer maneira, esses ambientes so teis para garantir a qualidade dos sistemas de software.
Eles podem ser utilizados para buscar apenas erros mais especcos, a partir de testes de fumaa, de
sanidade, de instalao e de congurao. Dessa forma, apenas uma pequena parcela de todas as veri-
caes so feitas nesse ambiente, o que facilita a organizao e a manuteno dos testes e do ambiente.
Dependendo do tamanho da bateria dos testes e de outras caractersticas, pode at ser mais vantajoso
no os automatizar.
Bancos de Dados Locais
Banco de Dados Local a congurao em que os gerenciadores de banco de dados para testes so
instalados nas mquinas de cada membro da equipe de desenvolvimento. Dessa forma, cada bateria de
testes de cada membro da equipe pode ser executada paralelamente, sem grandes preocupaes, pois
os recursos do ambiente e os dados no so compartilhados. Vale notar que a base de dados ainda
compartilhada para mesma bateria de casos de testes, por isso os testes de uma mesma bateria no de-
vem ser executados paralelamente, a no ser que sejam implementados de uma maneira completamente
independente dos demais.
As vantagens e desvantagens desse tipo de congurao so praticamente opostas s de ambientes
compartilhados, o que torna as duas opes complementares para vericao da qualidade dos sistemas
de software. As conguraes de hardware e software das mquinas de desenvolvimento podem apre-
sentar grandes diferenas em relao ao ambiente de produo, no entanto, cada desenvolvedor tem total
autonomia para criao de diferentes cenrios de teste.
115
A preparao dos dados para os testes feita em mtodos de set up ou nos prprios mtodos de teste,
ou seja, h maior autonomia, controle e exibilidade sobre os dados criados. Alm disso, os registros nas
tabelas da base de dados podem ser criados de forma abstrata, com a ajuda das prprias funcionalidades
do sistema, o que facilita a criao dos cenrios de teste.
O desempenho das baterias de testes tambm pode ser signicativamente melhor com bancos de
dados locais do que com ambientes compartilhados. Apesar de as mquinas de desenvolvimento no
terem todo o potencial de processamento daquelas de servidores, elas so normalmente utilizadas por
apenas um usurio. Outro aspecto importante do desempenho deve-se menor quantidade de dados, j
que apenas umusurio de umprojeto insere dados na base. Por ltimo, bancos de dados locais dispensam
a comunicao entre mquinas, que pode at ser o principal gargalo de desempenho de muitos ambientes.
Contudo, o sucesso deste tipo de ambiente depende da congurao e organizao dos repositrios
de cdigo-fonte. Como os bancos de dados so locais, cada desenvolvedor ou testador pode possuir con-
guraes que so especcas de sua mquina, como o diretrio de instalao do banco de dados. Para
isso, existem duas solues simples: ou selecionar alguns arquivos que sero ignorados durante a sin-
cronizao com o repositrio, ou, ento, utilizar endereos de arquivos relativos e outras conguraes
dinmicas, ou seja, que no estejam hard coded.
Para nalizar, esse tipo de congurao de ambiente de teste tambm pode ser de alto custo se for
necessrio comprar licenas do gerenciador de banco de dados para cada mquina de desenvolvimento.
Contudo, este problema pode ser facilmente resolvido se as mquinas de desenvolvimento utilizarem
bancos de dados livres para realizao dos testes. Entretanto, fundamental que, em algum momento,
as baterias de testes sejam executadas sobre o gerenciadores de banco de dados utilizados em ambiente
de produo, o que pode ser feito idealmente no ambiente de integrao contnua.
Bancos de Dados em Memria
Bancos de Dados em Memria utilizam, a priori, a memria principal do computador em vez dos discos
de armazenamento. Por isso, este tipo de banco de dados intrinsecamente mais rpido para pequenas
quantidade de dados do que os tradicinais, que utilizam principalmente os discos de armazenamento.
Dessa forma, eles podem ser utilizados como banco de dados locais para o ambiente de testes.
Alm de todas as vantagens j descritas na subseo anterior, as baterias de testes podem tornar-se
signicativamente mais rpidas.
O principal obstculo para utilizar este tipo de ambiente de testes so as grandes diferenas em
relao aos bancos de dados de produo, que geralmente utilizam bancos de dados tradicionais. Por
exemplo, nem todos os bancos de dados em memria oferecem triggers e stored procedures, o que pode
impossibilitar os testes de vrios mdulos do sistema.
Mesmo assim, o recomendado utilizar os bancos de dados em memria sempre que eles permitirem
a realizao de uma grande parcela dos cenrios de testes necessrios. No entanto, fundamental que
em algum momento seja executada a bateria de testes no ambiente real de produo para evitar erros de
incompatibilidade. O mais indicado congurar o ambiente de integrao contnua [52] o mais prximo
do real, para conrmar que os resultados dos testes realizados durante o desenvolvimento so conveis.
importante observar que mesmo com banco de dados em memria ainda necessrio cuidados
para executar os testes em paralelo. Se for necessrio paralelizar os testes, uma possvel soluo criar
uma instncia distinta de banco de dados para cada caso de teste (Padro Uma Instncia de Banco de
Dados por Linha de Execuo, Seo 7.2.1).
116
7.2 Padres
Para que os testes com persistncia de dados sejam de qualidade, fundamental que a bateria como
um todo esteja muito bem organizada. Para isso, pode-se utilizar uma combinao de diversos padres
organizacionais de testes de unidade, tais como Testcase Superclass, Test Helper, Parametrized Test e
Test Utility Method [99]. Todos esses padres so teis para reutilizao de cdigo e dos dados.
No entanto, independente de como ser a organizao, fundamental que o estado do banco de dados
no incio de cada teste seja sempre o mesmo: sem dados ou apenas com um conjunto de dados essenciais
para o funcionamento do sistema. Para isso, pode-se utilizar qualquer padro que seja responsvel por
limpar todos os dados gerados por um teste, por exemplo, o Table Truncation Tear down [99]. Apenas
importante notar que invivel controlar quais foram os dados gerados por cada cenrio de teste. Por
isso, a soluo mais simples e fcil remover absolutamente todos os dados da base e recriar novamente
os essenciais. Tendo esse padro aplicado, novos padres podem ser integrados bateria de testes, como
alguns que sero descritos a seguir.
117
7.2.1 Uma Instncia de Banco de Dados por Linha de Execuo
Tipo: Desempenho
Quando utilizar: Quando uma bateria de testes se torna lenta devido grande quantidade de casos
de testes. O que deve ser levado em conta se o tempo de execuo da bateria de testes est
impactando na produtividade do desenvolvimento. O pr-requisito para que esse padro seja uti-
lizado que os testes possam ser executados em paralelo, ou seja, eles no manipulem infor-
maes compartilhadas, tais como variveis globais. Alm disso, tambm deve ser avaliado se a
infraestrutura adequada para paralelizar os testes.
Inteno: Utilizar diferentes instncias de bancos de dados para possiblitar a execuo dos testes em
paralelo, visando melhor desempenho.
Motivao: Os testes que envolvem bancos de dados tendem a possuir um desempenho inferior aos
testes de unidade devido preparao do comando a ser executado (queries) e comunicao
entre o aplicativo e o gerenciador de banco de dados. Em alguns casos, at aceitvel um teste
demorar alguns segundos para ser realizado. Por isso, o desempenho de uma grande bateria desses
testes integrados pode ser insatisfatria.
Uma boa soluo de otimizao paralelizar a execuo dos testes, no entanto, historicamente os
arcabouos de testes foram implementados para executarem os testes sequencialmente, inclusive
os que dependem de gerenciadores de banco de dados. Por isso, preciso adapt-los para que seja
possvel executar diversos testes em paralelo.
Executar testes integrados com bancos de dados paralelamente difcil porque a prpria base de
dados se torna um recurso compartilhado entre os testes, o que torna os testes dependentes entre
si. As alteraes feitas por um cenrio de teste no esquema (schema) do banco, ou mesmo nos
prprios dados, podem quebrar os demais.
Soluo: Executar a bateria de testes paralelamente em uma certa quantidade de linhas de execuo,
sendo que cada uma delas utilizar sua prpria e independente instncia do banco de dados.
Consequncias: A bateria dos testes otimizada de maneira global, o que pode dispensar micro-
otimizaes em cada cenrio de teste.
Implementao: O aplicativo que executar os testes deve ter uma linha principal de execuo que
responsvel por criar e gerenciar uma la de cenrios de testes a serem executados. Alm disso,
preciso que ela tambm inicialize e gerencie as demais linhas de execuo que iro ser executadas
em paralelo para rodar os testes automatizados. Opcionalmente, o comando para execuo da
bateria de testes pode ser parametrizado para receber a quantidade de linhas de execuo que
devero ser criadas.
Cada linha de execuo deve ser responsvel por instanciar e congurar sua prpria instncia
de banco de dados. Dado que o ambiente est congurado, a linha de execuo desempilha um
cenrio de teste para ser executado sempre que ela estiver ociosa. Quando todas as linhas de
execues estiverem ociosas e a pilha estiver vazia, a bateria de testes terminou de ser executada.
118
7.2.2 Gerao Dinmica de Dados
Tipo: Robustez
Quando utilizar: recomendado o uso em praticamente todos os testes que envolvem dados persis-
tentes em gerenciadores de bancos de dados, especialmente aqueles que precisam de muitos dados
pr-populados, tais como testes de buscas, de gerao de relatrios ou de modelos que possuem
um grande nmero de dependncias.
Inteno: Gerar automaticamente objetos tolos para facilitar a criao dos testes, assim como torn-los
mais robustos e legveis.
Motivao: Os testes que envolvem a camada de persitncia so os responsveis por criar todos os
dados necessrios para sua execuo. Esses dados podem ser classicados em duas categorias: os
principais, que caracterizam o cenrio de teste, e os tolos ((Seo 6.4.3)), que so criados apenas
para evitar erros de compilao ou de execuco, causados comumente por validaes realizadas
pelo prprio gerenciador do banco de dados.
Um problema comum ocorre quando so necessrios muitos dados tolos para realizao de um
cenrio de teste. Alm de ser uma tarefa repetitiva e tediosa, a inicializao dessas informaes
polui o cdigo de teste. Ainda, esse problema pode ser multiplicado quando um cenrio de teste
precisar de dados j existentes na base.
Para amenizar o problema de legibilidade, os dados tolos podem ser denidos de forma esttica,
geralmente em arquivos externos que sero carregados durante a preparao dos testes (Figura
7.1). Entretanto, essa no uma boa soluo. Um dos principais problemas dessa abordagem
que a quantidade de dados para os testes cresce rapidamente medida que novos casos de testes
so adicionados, o que torna a manuteno dos testes muito complicada, pois qualquer mudana
na modelagem pode implicar que todos os arquivos de testes precisem ser adaptados.
1 - model: Pessoa
2 id: 1
3 nome: Sharon Janny den Adel
4 sexo: F
5 data_nascimento: 1974/07/12
6 nacionalidade: Holandesa
7
8 - model: Pessoa
9 id: 2
10 nome: Mark Knopfler
11 sexo: M
12 data_nascimento: 1949/08/12
13 nacionalidade: Escocesa
Figura 7.1: Exemplo de dados estticos em um arquivo no formato YAML.
Uma possvel soluo para esse problema tentar reaproveitar os dados para diferentes cenrios
de teste, o que diminui a replicao de informaes e facilita a manuteno em caso de mudanas
na modelagem dos dados. Entretanto, essa abordagem possui problemas ainda maiores. Com-
partilhar informaes entre testes os tornam frgeis, de modo que qualquer pequena alterao na
bateria de testes ou no prprio sistema pode quebrar um grande conjunto de testes, o que diculta
a identicao do erro e, consequentemente, torna a manuteno muito complicada (Seo 7.1.1).
Para dicultar ainda mais, essa abordagem prejudica a clareza dos testes, pois no ca expltico
quais os dados que so realmente pertinentes para cada caso de teste.
119
Soluo: Criar mtodos que geram dinamicamente objetos de dados populados com dados tolos e vli-
dos. Tendo esse objeto instanciado, basta atualizar as informaes principais com valores perti-
nentes para simular o cenrio de teste desejado.
Consequncias: Primeiramente, no mais necessrio a criao e manuteno de arquivos estticos de
dados, muito menos o gerenciamento de dados compartilhados. Alm disso, os testes so mais
facilmente adaptados s mudanas da modelagem dos dados. Por m, a clareza e a legibilidade
dos testes so melhoradas, no s porque os testes tendem a car mais enxutos e coesos, como
tambm porque os dados tolos de um objeto podem ser escondidos.
Implementao: No escopo dos testes, deve-se criar uma biblioteca de funcionalidades que so re-
sponsveis por instanciar e persistir objetos de dados populados com objetos tolos. Contudo, os
objetos tolos precisam ser nicos, para evitar problemas de integridade de dados, e no aleatrios,
para facilitar a depurao de testes incorretos e para no tornar os testes intermitentes. Tambm
importante notar que, como um objeto de dado pode depender de outros, essa biblioteca pode
fazer chamadas internas para reaproveitamento de cdigo.
J para tornar essa biblioteca mais exvel, pode-se permitir que um cenrio de teste consiga per-
sonalizar as informaes que forem pertinentes para seu contexto, ou seja, os mtodos de gerao
de objetos devem ser parametrizveis. Entretanto, o trabalho de implementao dessa biblioteca
de objetos de dados semelhante para todos os objetos de dados, logo, altamente recomendvel
que seja utilizado reexo para criao de bibliotecas genricas, ou seja, que consigam criar di-
namicamente qualquer tipo de objeto de dados.
Exemplo Python/Unittest: Para testar uma funcionalidade de busca de pessoas, muitos objetos de da-
dos Pessoa precisaro ser criados para poder simular todos os cenrios desejados. Por isso, antes
mesmo da criao dos testes, importante criar classes para gerar dinamicamente os objetos de
dados desejados. Esse objeto ter a responsabilidade de criar um objeto vlido, com pelo menos os
atributos obrigatrios do objeto preenchidos, mas de modo que possa ser customizado de acordo
com a necessidade dos testes. A Figura 7.2 mostra um exemplo de implementao desse objeto
(GeradorDePessoas) e de um teste que o utiliza.
Exemplo Python/Unittest/Django Dynamic Fixture: Como foi citado nos tpicos anteriores, a im-
plementao dessa classe de gerao de dados um trabalho rduo e repetitivo . Por isso, pref-
erencialmente, recomendado utilizar bibliotecas genricas de gerao dinmica de dados, como
o caso da Django Dynamic Fixture, para sistemas Web que utilizam o arcabouo Django para
Python. A Figura 7.3 mostra alguns exemplos de teste para a mesma funcionalidade de busca de
pessoas.
Usos Conhecidos: A ferramenta Django Dynamic Fixture implementa esse padro para aplicaes que
utilizam o arcabouo Django para Python.
120
1 from cadastro.models import Pessoa
2
3 import unittest
4
5 class GeradorDePessoas(object):
6 def cria(nome=X, sexo=F, nascimento=2000/01/01):
7 p = Pessoa(nome=nome, sexo=sexo, nascimento=nascimento)
8 p.save()
9 return p
10
11 gerador = GeradorDePessoas()
12
13 class BuscaDePessoasPeloNomeTest(unittest.TestCase):
14 def test_deve_encontrar_pessoas_que_possuem_parte_do_nome_buscado(self):
15 pessoa_que_deve_ser_encontrada = gerador.cria(nome=Sharon Janny den Adel)
16 pessoa_que_nao_deve_ser_encontrada = gerador.cria(nome=Mark Knopfler)
17
18 pessoas_encontradas = Pessoa.objects.com_parte_do_nome(Jan)
19
20 self.assertTrue(pessoa_que_deve_ser_encontrada in pessoas_encontradas)
21 self.assertTrue(pessoa_que_nao_deve_ser_encontrada not in
pessoas_encontradas)
Figura 7.2: Exemplo em Python de classe de gerao dinmica de um objeto de dados especco.
121
1 from django_dynamic_fixture import get
2 from cadastro.models import Pessoa
3
4 import unittest
5
6 class BuscaDePessoasPeloNomeTest(unittest.TestCase):
7 def test_deve_encontrar_pessoas_que_possuem_parte_do_nome_buscado(self):
8 # Apenas o atributo nome pertinente para esse caso de teste.
9 # Portanto, os outros atributos do objeto Pessoa devem ficar ocultos.
10
11 # cria e salva na base de dados uma pessoa com um nome especfico.
12 pessoa_que_deve_ser_encontrada = get(Pessoa, nome=Sharon Janny den Adel)
13 pessoa_que_nao_deve_ser_encontrada = get(Pessoa, nome=Mark Knopfler)
14
15 pessoas_encontradas = Pessoa.objects.com_parte_do_nome(Jan)
16
17 self.assertTrue(pessoa_que_deve_ser_encontrada in pessoas_encontradas)
18 self.assertTrue(pessoa_que_nao_deve_ser_encontrada not in
pessoas_encontradas)
19
20 def test_deve_ignorar_se_texto_buscado_esta_em_minuscula_ou_maiuscula(self):
21 pessoa_que_deve_ser_encontrada = get(Pessoa, nome=Kyra Gracie Guimares)
22 pessoa_que_nao_deve_ser_encontrada = get(Pessoa, nome=Roger Gracie Gomes)
23
24 pessoas_encontradas = Pessoa.objects.com_parte_do_nome(guiMARes)
25
26 self.assertTrue(pessoa_que_deve_ser_encontrada in pessoas_encontradas)
27 self.assertTrue(pessoa_que_nao_deve_ser_encontrada not in
pessoas_encontradas)
28
29 class BuscaDePessoasPorSexoTest(unittest.TestCase):
30 def test_deve_encontrar_apenas_pessoas_do_sexo_buscado(self):
31 # Dessa vez, o nome no importante, pode-se utilizar um nome tolo
qualquer,
32 # que criado pela biblioteca automaticamente.
33 pessoa_que_deve_ser_encontrada = get(Pessoa, sexo=F)
34 pessoa_que_nao_deve_ser_encontrada = get(Pessoa, sexo=M)
35
36 pessoas_encontradas = Pessoa.objects.de_sexo(F)
37
38 self.assertTrue(pessoa_que_deve_ser_encontrada in pessoas_encontradas)
39 self.assertTrue(pessoa_que_nao_deve_ser_encontrada not in
pessoas_encontradas)
Figura 7.3: Exemplo do padro de Gerao Dinmica de Dados com a biblioteca genrica de objetos de
dados Django Dynamic Fixture.
122
Captulo 8
Testes de Interface de Usurio
Interface de usurio (IU) a camada que cria a ligao entre o usurio e as camadas internas do sistema.
Os tipos mais comuns de IUs so as interfaces grcas (GUI, de Graphic User Interface) e as interfaces
Web (WUI, de Web User Interface). Os componentes das IUs observam eventos originrios de dispos-
itivos de hardware, identicam os eventos e fazem chamadas a outros mdulos do sistema por meio de
troca de mensagens ou de chamada de mtodos.
As IUs so fundamentais para muitos projetos e podem ser a camada determinante para o sucesso
de um sistema. Elas podem tornar o uso do sistema intuitivo, o que possibilita que mesmo pessoas
inexperientes consigam aprender a utiliz-lo sem a necessidade de um estudo rduo de documentos.
Atrativos que tornem o uso da interface mais fcil e interessante so diferenciais que valorizam muito o
sistema como um todo, vide as interfaces multi touch que tm atrado a ateno de milhes de usurios
em todo o mundo [103].
Devido importncia das IUs, interessante que seja dedicada uma parcela considervel de esforo
para que ela seja bem implementada. A qualidade das IUs pode ser interpretada pelas caractersticas
de correo, usabilidade, acessibilidade, portabilidade e beleza. Alm disso, estes fatores so, muitas
vezes, determinantes para a aceitao do sistema por parte do cliente [139].
No entanto, controlar e garantir a qualidade dessa camada do sistema uma tarefa delicada. A
interface de usurio ca exposta ao manuseio dos seres humanos, que possuem comportamentos inde-
terminados. Portanto, esta camada est sujeita a lidar com uma innidade de combinaes inusitadas de
eventos. Alm disso, muitos sistemas esto sujeitos a alteraes frequentes da interface, principalmente
os sistemas Web que evoluem constantemente seu leiaute [73].
Essas particularidades das IUs requerem que o controle de qualidade seja gil (de fcil adaptao),
ecaz e seguro contra erros de regresso. Mtodos formais so geralmente inviveis devido s mu-
danas constantes que a interface est sujeita e tambm por causa do pouco embasamento matemtico
do cdigo-fonte, com exceo de componentes multi touch que precisam interpretar traos e guras
geomtricas. J os testes manuais so ecazes para certos aspectos de qualidade, como beleza e usabili-
dade, mas no so seguros contra erros de regresso, principalmente por causa da innidade de maneiras
que uma interface pode ser manipulada.
A automao de testes uma alternativa satisfatria para o controle de qualidade das IUs, por todos
os motivos que j foram discutidos na Parte I. Contudo, para que os testes automatizados para esta
camada sejam de qualidade, necessrio o uso de ferramentas especializadas, que permitam a escrita de
testes legveis com alta produtividade.
No decorrer deste captulo sero discutidos alguns aspectos de ferramentas que so teis para criao
de testes automatizados de interface com qualidade. Tambm sero apresentadas abordagens prprias
para criao de testes de interface, assim como padres e antipadres que so especcos para este tipo
de teste.
123
8.1 Princpios Bsicos
Como muitas das responsabilidades de um sistema so associadas interface de usurio, mais difcil
test-la do que mdulos isolados que so responsveis por apenas uma tarefa. Por mais que o sistema e a
interface sejam bem modularizados, os problemas de outras partes do sistema podem acabar interferindo
na interface grca.
Por isso, fazer testes automatizados de interface de qualidade requer no s conhecimento de padres
e antipadres de testes, como tambm muita disciplina. Para organizar bem os testes necessrio con-
hecer primeiramente as responsabilidades da interface de usurio, assim como modularizar o sistema
corretamente para facilitar a escrita dos mesmos.
Um projeto mal arquitetado no separa as regras de negcio e de dados do cdigo da interface de
usurio. Por exemplo, comandos SQL integrados comcdigo-fonte responsvel por desenhar a interface.
Este problema de arquitetura comum, por isso, hoje em dia, muitos arcabouos possuem uma estrutura
denida para evitar que isso acontea, principalmente os arcabouos para desenvolvimento de sistemas
Web.
Os arcabouos para criao de interfaces grcas seguem, em geral, a arquitetura baseada no padro
MVC (Model-View-Controller) [32]. Alguns seguem variaes deste padro, mas sempre incentivando
a separao do sistema em mdulos bem denidos, o que torna o software mais fcil de implementar e
testar. O padro MVC sugere uma arquitetura na qual o sistema dividido em trs partes: (1) Modelo
responsvel por encapsular as regras e os dados do sistema; (2) Viso, que exibe os dados e (3) Contro-
lador, que recebe informaes do usurio e as envia para camada de Modelo. O Controlador recebe da
Viso as aes do usurio e as mapeia para as funcionalidades pertinentes ao Modelo. A partir dos resul-
tados, o Controlador manuseia a Viso apropriadamente. A Figura 8.1 possui um diagrama simplicado
mostrando as associaes entre as camadas.
Figura 8.1: Diagrama simplicado do padro MVC. As linhas slidas indicam associaes diretas en-
quanto as tracejadas representam associaes indiretas.
Dado que a aplicao segue a arquitetura MVC, pode-se dizer que a interface grca est associada
Viso, apesar de nem toda Viso ser uma interface grca. O termo Viso mais amplo, pois abrange
tudo que tenha o propsito de exibir os dados. Por exemplo, Viso pode ser imagens, grcos, tabelas,
sons etc. Entretanto, os testes de interface tambm envolvem, comumente, a camada Controlador, pois
ela interfere diretamente nas informaes que sero exibidas, alm de que o cdigo-fonte do controlador
pode estar entrelaado com o cdigo dos arcabouos que facilitam a criao da Viso.
Controlador
A responsabilidade do Controlador basicamente conectar duas outras partes do sistema, pois ela recebe
os dados do usurio a partir da Viso e as envia apropriadamente para camada Modelo. Por isso a sua
lgica no deve ter grande complexidade. Entretanto, erros do controlador podem ser to desastrosos
124
quanto erros em mdulos mais complexos. Portanto, automatizar os testes dos controladores tambm
importante.
Os controladores podem ser avaliados por meio de efeitos colaterais causados pelo manuseio da
interface de usurio. Como sua execuo possivelmente altera o estado da interface, possvel seguir
essa estratgia. Essa forma de testar especialmente til nas situaes em que o cdigo do controlador
difcil de ser isolado e testado. Sistemas legados mal implementados ou os que usam arcabouos
complexos tornam invivel a criao de testes de unidade de qualidade. Estes testes integrados com a
camada de interface do usurio se tornam uma alternativa produtiva e segura, at que os controladores
sejam refatorados.
Contudo, sempre que possvel e vivel, prefervel testar isoladamente os controladores com testes
de unidade, assim como qualquer outro componente do sistema. Testes de unidade so mais fceis e
rpidos de serem escritos e mantidos do que testes que integram diversos mdulos do sistema.
Os controladores da interface no possuem tantas particularidades quanto Viso, j que ela no
acessvel ao usurio nal. Entretanto, ela possui duas caractersticas expressivas que podem afetar
sua testabilidade: (1) comum que a lgica da camada que entrelaada com trechos de cdigo para
satisfazer as necessidades de arcabouos e (2) ela comumente possui referncias para diversos outros
mdulos do sistema.
No caso de aplicaes Web, o controlador est sujeito a lidar com detalhes do protocolo HTTP.
Ao ser chamado, ele pode ter de processar as informaes que vieram por meio de requisies GET
ou POST. Para o retorno, ele pode lanar os erros 403 (funciolidade proibida) e 404 (pgina no en-
contrada) ou, at mesmo, trechos de cdigo HTML, JavaScript, JSON e XML para serem exibidos
apropriadamente na Viso.
O mesmo ocorre para o caso dos controladores de interfaces grcas, os quais so mais fceis de
ser implementados com a ajuda de arcabouos. O controlador obtm as informaes vindas do usurio
atravs de objetos ou estruturas de dados prprias. Sua execuo tambm pode ter de seguir a forma
que os arcabouos so organizados para que a interface seja implementada corretamente. Por exemplo,
programas escritos com o arcabouo Swing para linguagem Java precisam se preocupar com o modo que
iro fazer as chamadas para as camadas base do sistema, pois a execuo lenta das tarefas pode impedir
que o processo de renderizao da interface seja executado, bloqueando a interface.
A primeira recomendao para realizao de bons testes de unidade dos controladores utilizar
o padro Humble Object (Seo 6.4) sempre que for pertinente. Dessa forma, o teste ca direcionado
totalmente lgica do sistema enquanto a lgica do arcabouo de apoio ignorada. Erros dos arcabouos
podem afetar o sistema, mas sempre supomos que ele funciona como o esperado. Se o arcabouo
possuir um erro j conhecido, ento pode ser implementado um teste para vericar se o sistema consegue
administr-lo apropriadamente.
Atualmente, diversos arcabouos fornecem no apenas seus arquivos compilados como, tambm,
bibliotecas para facilitar a escrita de testes automatizados dos mdulos que utilizem suas funcional-
idades. Isso facilita e aumenta a produtividade da criao de testes. o caso dos arcabouos Web
Django e Ruby on Rails que fornecem bibliotecas que permitem simular requisies de usurios e que
possuem mtodos de vericaes que tornam os testes mais legveis e fceis de serem escritos.
Outra recomendao implementar os controladores de um modo que seja possvel injetar as de-
pendncias [113], isto , que o teste consiga substituir os objetos da camada de negcios por Objetos
Dubls. Dessa forma, a persistncia de dados e a comunicao entre servidores podem ser facilmente
isoladas.
Viso
Teste de interface verica a correo da interface do usurio. Outros tipos de testes tambm avaliam a
interface, mas utilizando outros critrios, como, por exemplo, os testes de usabilidade, acessibilidade,
125
leiaute e aceitao. Portanto, as ferramentas de testes de interface podem ser utilizadas para a realizao
desses outros tipos de testes. No entanto, como foi discutido no Captulo 4, importante focar no que se
est querendo vericar, assim como imprescindvel no misturar baterias de testes com objetivos dis-
tintos. possvel separar as baterias de testes que envolvem a interface sem a necessidade de replicao
de cdigo-fonte, como ser discutido na seo de padres deste captulo.
Existem duas abordagens para realizao dos testes que envolvem a interface de usurio: (1) testar a
implementao da interface, vericando o uso das bibliotecas e arcabouos de MVC e de renderizao;
ou (2) fazer os testes diretamente na interface a partir da simulao de um usurio nal. Essas duas abor-
dagens podem ser simplicadamente ditas como testes de caixa-branca e caixa-preta, respectivamente.
Na prtica, as duas abordagens podem ser implementadas com um certo conhecimento do cdigo-fonte,
ou seja, o termo mais apropriado seria caixa-cinza em vez de caixa-preta.
A abordagem de caixa-branca nada mais do que fazer testes de unidade para a Viso. Para isso,
necessrio a criao dos eventos que representam as aes dos usurios e importante isolar a interface
dos controladores. A interface tambm pode ter mtodos auxiliares que encapsulam parte de sua lgica.
Esses mtodos tambm devem ser testados, como qualquer outra regra do sistema. Para esse tipo de
teste, podem ser utilizadas as ferramentas normais de testes de unidade, como as da famlia xUnit, assim
como as ferramentas de criao de Objetos Dubls (vide Seo 6.2).
No caso das interfaces Web, mais complexo fazer os testes de unidade. A interface implementada
usando linguagem de marcao (HTML) e outras que so interpretadas pelo navegador Web, como
JavaScript. O arcabouo JsUnit, que a verso JavaScript da famlia xUnit, utiliza o prprio navegador
para executar os testes e fornece um servidor Web leve para tornar possvel a execuo automtica, por
exemplo, em servidores de integrao contnua, como descrito na Seo 4.5.
Alm disso, as aplicaes Web so distribudas: a interface do usurio ca localizada no lado do
cliente, enquanto os controladores e o modelo cam no lado do servidor. Isso impossibilita que os
controladores ou outros mdulos do sistema sejam facilmente substitudos por Objetos Dubls. Essa
diculdade um tpico interessante para pesquisas futuras. Outra diculdade ainda no solucionada
medir a cobertura dos testes em relao ao cdigo (vide Captulo 10) de interfaces Web.
Existem ferramentas que fazem chamadas ao sistema pela interface simulando um usurio, mas o
teste passa a ser integrado, pois envolve tambm o lado do servidor. o caso das ferramentas HtmlU-
nit
1
, JWebUnit
2
e Selenium
3
. Elas simulam os usurios nais e coletam informaes da interface para
vericao. Alguns detalhes da implementao so utilizados, tais como propriedades de componentes,
como, por exemplo, nomes dos componentes, identicadores etc. No entanto, grande parte dos detalhes
de implementao da interface e do controlador so abstrados pelas ferramentas.
Tambm existem ferramentas anlogas para fazer testes em interfaces Desktop. Assim como as
ferramentas para testes Web podem depender do navegador, as de interfaces Desktop podem depender do
gerenciador de janelas do sistema operacional, da linguagem de programao e das bibliotecas utilizadas
para implementar a interface do sistema. Por exemplo, as ferramentas Fest e Jemmy so especcas para
testes de interfaces grcas implementadas em Java Swing.
Essas ferramentas so as mesmas utilizadas em um teste caixa-preta. Entretanto, mais importante
do que o conhecimento dos testes em relao ao cdigo-fonte, se os testes iro substituir mdulos
do sistemas por Objetos Dubls para tornar o teste menos acoplado. Essa deciso depender dos tipos
de erros que sero vericados, assim como da facilidade de implementao dos testes e do uso das
ferramentas.
1
Apesar de o nome sugerir que a ferramenta da famlia xUnit, HtmlUnit um navegador leve escrito em Java que no
renderiza as pginas, mas consegue processar o cdigo HTML e interpretar o cdigo JavaScript. Ele utilizado para testes de
integrao e serve como base para muitas ferramentas, tanto para testes em Java quanto para outras linguagens, como Python
e Ruby.
2
JWebUnit um Wrapper do HtmlUnit para facilitar a escrita dos testes e torn-los mais claros.
3
Selenium uma ferramenta escrita em JavaScript que executada internamente em navegadores reais. Atualmente, est
sendo unicada com a ferramenta WebDriver, que possui o mesmo propsito da JWebUnit.
126
8.2 Testes que Simulam Usurios
Os testes que simulam aes dos usurios possuem peculiaridades importantes. O modo pelo qual o
sistema exercitado no por intermdio de chamadas diretas a objetos e mdulos do sistema, mas,
sim, por arcabouos que manipulam a prpria interface de forma transparente, sem a necessidade de
conhecer a fundo o cdigo-fonte. J a forma de vericao pode variar dependendo do que se est
querendo vericar. Podem ser feitas vericaes diretamente no estado da interface, ou, ainda, em
outras camadas do sistema, como na camada de persistncia de dados.
A lgica dos testes de interface segue sempre uma estrutura denida, que ilustrada pelo exemplo
de uso da ferramenta HtmlUnit na Figura 8.2. Primeiro preciso localizar um componente da pgina
(linhas 17, 19 e 23) para, em seguida, simular algum evento do usurio nal (linhas 21 e 26) ou capturar
propriedades para fazer as vericaes (linha 28). Os eventos mais comuns so cliques do mouse e teclas
digitadas. Entretanto, existem ferramentas que tambm disponibilizam mtodos para simular eventos de
arrastar e soltar (drag and drop), apertar e segurar teclas etc.
1 // referncias do JUnit
2 import org.junit.Test;
3 import static org.junit.Assert.assertEquals;
4 // referncias do HTMLUnit
5 import com.gargoylesoftware.htmlunit.WebClient;
6 import com.gargoylesoftware.htmlunit.html.*;
7
8 public class BuscaTests {
9
10 @Test
11 public void buscaComSucessoDeveRedirecionarParaPaginaDeResultados() {
12 // Cria um cliente (navegador)
13 WebClient cliente = new WebClient();
14 // Abre uma pgina armazenada em um servidor local
15 HtmlPage pagina = cliente.getPage("http://localhost:8000");
16 // Localiza o form de busca
17 HtmlForm formulario = pagina.getFormByName("busca_form");
18 // Localiza o campo de texto para busca do formulrio
19 HtmlTextInput texto_busca = formulario.getInputByName("texto_busca");
20 // Digita o texto para busca
21 texto_busca.setValueAttribute("tdd");
22 // Localiza o componente para submeter o form
23 HtmlSubmitInput botao_busca = formulario.getInputByName("busca");
24 // Simula um clique no boto de envio de dados para o servidor
25 // Abre a pgina de resultados
26 HtmlPage pagina_resultados = botao_busca.click();
27 // Verifica se a ao foi executada corretamente
28 assertEquals("Resultados da Busca - tdd", page.getTitleText());
29 }
30 }
Figura 8.2: Exemplo de teste de interface Web com HtmlUnit.
As vericaes deste exemplo so feitas com auxlio da ferramenta JUnit. Como a HtmlUnit ape-
nas cria um navegador para execuo dos testes, interessante a utilizao de outras ferramentas que
facilitem as vericaes. Outras ferramentas tambm fornecem mtodos de vericaes que so mais
pertinentes para testes de interface do que as da famlia xUnit, como o caso da JWebUnit e da Sele-
nium. Esses mtodos podem ser desde aucares sintticos que melhoram a legibilidade dos testes at
mtodos fundamentais, por aumentar consideravelmente a produtividade da automao. Alm disso,
127
algumas ferramentas possuem gravadores de interao, discutidos a seguir.
8.2.1 Gravadores de Interao
Gravadores de Interao so ferramentas que detectam aes executadas por usurios reais sobre um
programa e geram cdigo-fonte ou metadados que podem ser interpretados e reproduzidos para simular
um usurio. Alm disso, elas permitem adicionar pontos de vericao manualmente durante ou depois
da gravao por meio da edio do cdigo-fonte gerado. Exemplos de ferramentas so Marathon
4
, para
testes de GUIs geradas com Java/Swing, e Selenium-IDE
5
, para WUIs.
A principal vantagem da gravao de testes a facilidade de sua escrita, j que no necessrio con-
hecimento de programao. Assim, qualquer pessoa pode criar casos de testes automatizados, mesmo
clientes e usurios nais. A produtividade tambm pode ser alta, j que o trabalho de localizao dos
componentes da tela transparente para o usurio.
Contudo, o cdigo gerado pode no ser muito legvel e modularizado, o que resulta na replicao
de cdigo e difcil manuteno. Qualquer alterao na interface de usurio pode afetar diversos casos
de testes. Se muitos testes precisarem ser arrumados ou at mesmo refeitos ou regravados do zero, a
produtividade dessa abordagem pode diminuir.
A qualidade dos testes automatizados de interface depende das ferramentas utilizadas, por isso tam-
bm interessante conhecer as limitaes das ferramentas. Existem casos onde nem todos os eventos de
usurios podem ser gravados, sendo necessria a edio do cdigo-fonte para complementar o teste.
Por essas complicaes, a abordagem recomendada para evitar esses problemas refatorar o cdigo-
fonte gerado aps a gravao da simulao de forma a organizar o cdigo-fonte gerado. Utilizar a
gravao pode aumentar a produtividade durante a criao dos testes, assim como mais produtivo dar
manuteno em cdigo-fonte organizado e modularizado.
No entanto, a gravao da simulao s faz sentido aps a implementao da interface, portanto
esta abordagem conitante com as tcnicas de escrever os testes antes mesmo da implementao
(vide Captulo 9). Entretanto, nada impede que as duas abordagens sejam mescladas, dependendo das
situaes.
J para os sistemas legados, em que o cdigo-fonte est muito embaralhado ou incompreensvel, a
gravao de testes uma tcnica rpida e interessante para trazer segurana nas futuras manutenes do
sistema
6
. Alm disso, ela pode ser til para criao de outros tipos de testes, como os de usabilidade,
acessibilidade e aceitao.
Outro uso interessante dos gravadores a criao de testes de fumaa bem simples e sem a neces-
sidade de refatorao do cdigo-fonte gerado. Como a criao dos testes rpida e os cenrios so
simples, o custo de refaz-los do princpio tende a ser menor do que o custo de refatorar o cdigo ger-
ado. Testes de fumaa so, muitas vezes, utilizados em ambientes de produo, desde que no sejam
realizadas aes crticas que possam comprometer o sistema e os dados em caso de erro.
8.3 Desempenho dos Testes
Os testes de interface so intrinsecamente mais lentos do que aqueles das outras camadas do sistema. Por
mais que eles sejam isolados, podem envolver processos de renderizao e de manuseio de dispositivos
de hardware para criao dos eventos de usurio. Para os sistemas Web, a situao ainda mais delicada,
4
Marathon uma ferramenta implementada em Python que permite gravar testes para aplicaes escritas em Java/Swing.
5
Selenium-IDE uma extenso para o navegador Firefox que permite gravar, editar e executar testes escritos com a ferra-
menta Selenium
6
O autor deste trabalho aplicou esta recomendao em um sistema Web durante seu estgio na Assembleia Legislativa do
Estado de So Paulo.
128
pois pode ser necessrio o apoio de navegadores Web e de servidores para integrar o lado do cliente e o
do servidor.
No caso dos testes de integrao, o desempenho pode baixar a nveis crticos. A persistncia de
dados no sistema de arquivos, ou em banco de dados, tambm uma operao lenta, podendo at ser um
dos gargalos de desempenho, assim como a comunicao lenta entre redes e servidores
7
.
O ideal da automao de testes que todos os cenrios possam ser executados a todo momento e
praticamente instantaneamente. No caso dos testes de interface, pode haver uma certa tolerncia quanto
ao desempenho, desde que eles no sejam to lentos a ponto de atrasar o desenvolvimento do projeto.
O mesmo ocorre com outros tipos de testes intrinsecamente demorados, tais como os de aceitao. No
caso de grandes baterias de testes de WUI, elas podem demorar at horas para serem executadas.
Existem algumas ferramentas que podem acelerar a execuo dos testes ou recomendaes para
tornar o uso da automao mais prtica. A ferramenta Selenium Grid, por exemplo, cria uma grade
computacional para possibilitar que os testes escritos com a ferramenta Selenium sejam executados par-
alelamente em diversos ambientes. Essa ferramenta especialmente til quando uma mesma bateria
de testes executada em vrios navegadores Web para testar a portabilidade da aplicao. Contudo,
para que ela seja utilizada com xito, fundamental que os casos de testes sejam completamente in-
dependentes uns dos outros e da ordem em que so executados. Como mais de um caso de teste pode
ser executado ao mesmo tempo, um poder inuenciar o sucesso de outro, caso haja algum recurso
compartilhado.
Os erros causados pela dependncia dos testes inviabilizam a execuo paralela da bateria de testes.
A quantidade de erros que podem surgir indeterminada alm de que os erros possivelmente sero
intermitentes. Mesmo os relatrios dos resultados dos testes no sero mais teis porque a bateria de
testes perde a sua propriedade de reprodutibilidade.
Outra recomendao utilizar as ferramentas com melhor desempenho durante o perodo de desen-
volvimento e deixar as mais lentas para serem executadas em ambientes de integrao contnua, pelo
menos uma vez ao dia. Para interfaces Web, existem ferramentas que permitem executar a mesma bate-
ria de testes em diferentes navegadores. Dessa forma, durante o dia a dia de desenvolvimento, os testes
podem ser executados no navegador do HtmlUnit, que leve e tem melhor desempenho porque no
renderiza a interface. J no ambiente de integrao contnua, os testes podem ser executados de forma
assncrona nos navegadores reais, como Firefox e Google Chrome.
7
O autor teve essa experincia enquanto trabalhava com o sistema Janus, da Pr-Reitoria de Ps-Graduao da USP. O
sistema possuia uma bateria de testes de integrao e uma de testes de fumaa para a sua interface Web. Os testes de integrao
eram executados em um ambiente de integrao contnua, que era um servidor Linux com uma sesso grca virtual
129
8.4 Padres
A seguir sero descritos padres de automao para testes que envolvem a interface de usurio. Estes
padres foram identicados pelo autor em projetos prprios e com o estudo de certas ferramentas de
testes que j implementam algumas das solues propostas. Os padres sero descritos segundo o es-
queleto exibido na Seo 5.3. Quando houver diferena signicativa na implementao do padro para
interfaces GUI e WUI, haver subtpicos prprios para descrever cada caso.
8.4.1 Tela como Unidade
Tipo: Organizacional
Quando utilizar: Idealmente, em todos os testes de interface de usurio.
Inteno: Facilitar a implementao dos mtodos de set up, tornar os testes menos sensveis a mudanas
do sistema e melhorar o desempenho deles.
Motivao: Para o teste chegar at a tela a ser testada pode ser necessria a navegao por meio de
diversas outras telas do sistema, o que acaba adicionando responsabilidades adicionais ao teste
desnecessariamente. Esta navegao normalmente deve car armazenada no mtodo de set up,
pois uma preparao do ambiente para realizao dos testes.
A navegao torna a criao do teste mais complexa e gera uma dependncia de outras telas do
sistema. Alm disso, o carregamento de outras telas pode armazenar na memria informaes que
no esto explcitas na descrio do teste, o que, se ocorrer, diculta o entendimento dos casos de
teste. Por ltimo, este processo exige que outras telas que no so pertinentes para os testes sejam
carregadas e renderizadas, o que demanda tempo.
Soluo: Abrir a tela diretamente, dispensando a necessidade de navegar por outras telas do sistema.
Consequncias: A navegao entre telas evitada, o que torna o caso de teste mais rpido e indepen-
dente de outras partes do sistema, assim como esperado com os testes de unidade.
Implementao - GUI: Deve-se instanciar os objetos que representam a tela diretamente. Se no for
possvel abrir a tela dessa maneira, pode-se adaptar o cdigo do sistema, ou, ento, o objeto pode
ser encapsulado no mtodo de set up em um outro objeto que permita a abertura da tela. Algumas
ferramentas de testes fornecem suporte para isso.
Implementao - WUI: A pgina deve ser aberta diretamente atravs da URL, por mais que o endereo
seja longo. S necessrio cautela para que o domnio da aplicao esteja denido em apenas um
local da aplicao, o que evita a replicao de cdigo e facilita a manuteno dos casos de teste.
Exemplo - GUI - Java/Swing/JUnit/Fest: Temos uma tela de conguraes em teste, exibida na
Figura 8.3 (fotograa de uma tela do sistema GinLab). O primeiro passo abrir a tela para que
ela seja manipulada pelos testes. Essa tela aberta da mesma forma que um usurio do sistema,
utilizando links ou atalhos de teclado presentes em outra tela do sistema, como mostrado na
Figura 8.4.
Neste caso, o set up dos testes precisa descrever todos os passos que o usurio faria, como
mostrado na Figura 8.5. Note que necessrio conhecer alguns detalhes de implementao e do
funcionamento da tela principal (representada pelo objeto TelaPrincipalFrame) do sistema para
poder fazer os testes da tela de congurao. Isso torna o teste menos robusto, mais complexo,
lento e ilegvel.
130
Figura 8.3: Tela de conguraes a ser testada.
Figura 8.4: Tela principal do sistema que contm links e atalhos de teclado para abrir a tela de congu-
raes a ser testada.
Contudo, possvel quebrar esta dependncia se conseguirmos instanciar isoladamente a janela
que ser testada (representada pelo objeto TelaConfiguracoesFrame), como apresentado na
Figura 8.6. pertinente notar que os testes do menu e dos atalhos so importantes de serem
realizados, mas eles devem estar agrupados com os testes da janela que os contm, ou seja, com
os testes da tela principal.
Exemplo em Java - WUI/WebDriver: Para testar sistemas Web, podemos acessar sua pgina inicial e
ento navegar at o mdulo desejado. A Figura 8.7 segue esta estratgia para acessar uma pgina
de autenticao da aplicao. Note que este um exemplo simples, onde necessrio passar por
apenas uma pgina para encontrar um link para o local que queremos testar. Em outras situaes,
pode ser necessrio navegar por diversas outras pginas, deixando o cdigo dos testes ainda mais
complexo e lento.
Para sistemas Web, mais simples acessar as pginas diretamente, j que, normalmente, o en-
dereo completo da pgina desejada pode ser aberto diretamente, como mostrado na Figura
8.8. Quando no for possvel acessar o mdulo para teste diretamente, deve ser utilizado o en-
dereo da pgina mais prxima para que se possa navegar at o local desejado. Isso, geralmente,
necessrio quando for preciso carregar algumas informaes por intermdio da submisso de
formulrios Web antes de acessar a pgina que ser testada.
Padres Relacionados: O padro Estado Inicial da Tela (Seo 8.4.2) facilita a implementao desse
padro.
Usos Conhecidos: Os testes dos sistemas Janus e GinLab seguem essa organizao.
131
1 // junit
2 import org.junit.Before;
3 // FEST
4 import org.fest.swing.fixture.FrameFixture;
5 // Cdigo do pacote AWT utilizado pelo FEST
6 import java.awt.event.KeyEvent;
7
8 public class UmTest {
9 private FrameFixture window;
10
11 @Before
12 public void abreTelaEmTeste() {
13 window = new FrameFixture(new TelaPrincipalFrame());
14 window.show();
15 window.focus();
16 window.menuItem("arquivo").click();
17 window.menuItem("configurar").click();
18
19 // ou poderia abrir a janela por atalhos de teclado:
20 // window.pressKey(KeyEvent.VK_CONTROL);
21 // window.pressKey(KeyEvent.VK_C);
22 // window.releaseKey(KeyEvent.VK_C);
23 // window.releaseKey(KeyEvent.VK_CONTROL);
24
25 // tela de configuraes aberta
26 }
27 // casos de testes aqui...
28 }
Figura 8.5: Exemplo de teste com a ferramenta Fest de uma tela sem o padro Tela como Unidade.
1 // junit
2 import org.junit.Before;
3 // FEST
4 import org.fest.swing.fixture.FrameFixture;
5
6 public class UmTest {
7 private FrameFixture window;
8
9 @Before
10 public void abreTelaEmTeste() {
11 window = new FrameFixture(new TelaConfiguracoesFrame());
12 window.show();
13 window.focus();
14 // tela de configuraes aberta
15 }
16 // casos de testes aqui...
17 }
Figura 8.6: Refatorao do exemplo da Figura 8.5 para utilizar o padro Tela como Unidade.
132
1 // referncias do JUnit
2 import org.junit.Before;
3 // referncias do WebDriver
4 import org.openqa.selenium.By;
5 import org.openqa.selenium.WebDriver;
6 import org.openqa.selenium.WebElement;
7
8 public class LoginTests {
9 public static final HOST = "http://localhost:8000";
10
11 @Before
12 public void abreTelaDeLogin() {
13 // Cria um cliente (navegador)
14 WebDriver driver = new HtmlUnitDriver();
15 // Abre uma pgina armazenada em um servidor local
16 driver.get(HOST);
17 // Procura o link para pgina de autenticao
18 WebElement login_link = driver.findElement(By.id("login"));
19 login_link.click();
20 // tela de login aberta
21 }
22
23 // casos de testes aqui
24 }
Figura 8.7: Exemplo de teste de uma pgina Web de autenticao sem o padro Tela como Unidade.
1 // referncias do JUnit
2 import org.junit.Before;
3 // referncias do WebDriver
4 import org.openqa.selenium.WebDriver;
5
6 public class LoginTests {
7 public static final HOST = "http://localhost:8000";
8
9 @Before
10 public void abreTelaDeLogin() {
11 // Cria um cliente (navegador)
12 WebDriver driver = new HtmlUnitDriver();
13 // Abre uma pgina de login diretamente
14 driver.get(HOST + "/login");
15 // tela de login aberta
16 }
17
18 // casos de testes aqui
19 }
Figura 8.8: Refatorao do exemplo da Figura 8.7 para utilizar o padro Tela como Unidade.
133
8.4.2 Estado Inicial da Tela
Tipo: Organizacional
Quando utilizar: Idealmente, em todos os testes de interface de usurio. Se muitos casos de testes
necessitarem de um mesmo estado diferente do inicial, este padro ainda dever ser usado, mas o
set up nessa situao necessita ter um cdigo adicional que alterar o estado da interface para o
desejado.
Inteno: Facilitar o entendimento do cdigo-fonte e a escrita de testes independentes.
Motivao: A tela a ser testada geralmente aberta no mtodo de set up, no entanto, uma mesma
tela da interface de usurio pode ter vrios estados; por exemplo, com dados carregados ou com
conguraes especcas. Se a cada vez que o set up executado, a interface iniciada em um
estado diferente devido a informaes previamente carregadas, ento no ca claro para os testes
qual o estado da interface que est sendo testada. Isso ajuda a tornar os testes intermitentes e
rebuscados.
Soluo: Padronizar que o mtodo de set up sempre ir carregar o estado inicial da tela em teste, ou
seja, todas as informaes que podem inuenciar o estado da tela devem ser apagados. Se for
necessrio fazer alguma modicao no estado inicial para realizao de algum cenrio, essa
modicao dever ser feita nos respectivos mtodos de teste. Se muitos casos de testes precis-
arem de um mesmo estado diferente do inicial, ento os testes podem ser agrupados em outra
classe que denir o estado desejado como estado inicial da tela.
Consequncias: O mtodo de set up se torna mais consistente, j que a tela sempre ser a mesma e
com o mesmo estado aps a sua execuo. Isso torna os testes mais fceis de serem entendidos,
pois evitada a adio de estruturas de controle de uxo para lidar com cada estado da tela.
Ainda, quando o estado precisar ser modicado para realizao de um teste, o trecho de cdigo
ca explcito no mtodo de teste, o que facilita o entendimento do caso de teste especco e no
prejudica a legibilidade dos outros casos.
Implementao: O padro Tela como Unidade pode ser o suciente para carregar uma tela no seu
estado inicial, pois evita que dados sejam lidos e processados durante a navegao por outras telas
do sistema em teste. Se no for suciente, devem ser desmantelados os dados j carregados no
mtodo de set up antes mesmo de exibir a tela.
Quando muitos testes possurem comportamento inicial repetido, devem ser feitas duas refa-
toraes: (1) a congurao do estado pode ser movida para um mtodo separado que ser
chamado por cada caso de teste; ou (2) pode ser criada uma nova classe especca para estes
casos de testes que podem compartilhar um mtodo de set up idntico.
Implementao - WUI: No caso de sistemas Web necessrio ateno com os dados carregados no
escopo da aplicao e na sesso de usurio, pois podem inuenciar o estado das telas. Ainda,
se for necessrio navegar entre algumas pginas, evite submeter formulrios desnecessrios para
evitar o carregamento de novas informaes.
O carregamento implcito de informaes no pertinentes aos casos de testes pode produzir falsos
resultados positivos ou negativos, principalmente quando as vericaes so pouco precisas; por
exemplo, quando vericado se uma determinada palavra aparece em qualquer local da tela.
Exemplo: A Figura 8.9 mostra uma organizao comum de testes de interface, mas que no se preocupa
com o estado da tela no momento do teste. J a Figura 8.10 apresenta solues simples que
garantem que no incio de cada teste o estado da tela dever ser sempre o mesmo.
134
1 // referncias do JUnit
2 import org.junit.BeforeClass;
3 // referncias do WebDriver
4 import org.openqa.selenium.WebDriver;
5
6 public class MapaDoSiteTests {
7 public static final HOST = "http://localhost:8000";
8
9 // A pgina em teste acessada apenas uma vez.
10 // Todos os testes iro manipular a interface, ento no claro
11 // qual o estado inicial da interface no incio de cada teste.
12 @BeforeClass
13 public void acessaPaginaDoMapaDoSite() {
14 WebDriver driver = new HtmlUnitDriver();
15 // Acessou uma pgina diferente da que est sendo testada.
16 // Informaes adicionais e irrelevantes para os testes
17 // podem ter sido carregadas desnecessariamente.
18 driver.get(HOST);
19 // Acessa a pgina que ser testada.
20 WebElement login_link = driver.findElement(By.id("login"));
21 login_link.click();
22 }
23
24 // Testes...
25 }
Figura 8.9: Exemplo de organizao sem o padro Estado Inicial da Tela.
1 // referncias do JUnit
2 import org.junit.BeforeClass;
3 // referncias do WebDriver
4 import org.openqa.selenium.WebDriver;
5
6 public class MapaDoSiteTests {
7 public static final HOST = "http://localhost:8000";
8
9 // Pgina acessa antes de cada teste, garantindo que todas as
10 // manipulaes (sem estado) feitas por testes anteriores
11 // sero descartadas.
12 @Before
13 public void acessaPaginaDoMapaDoSite() {
14 WebDriver driver = new HtmlUnitDriver();
15 // Pgina acessada diretamente.
16 driver.get(HOST + "/mapadosite");
17
18 // Uma maneira radical de forar que uma nova sesso seja utilizada
19 // para cada um dos testes.
20 driver.manage().deleteAllCookies();
21 }
22
23 // Testes ...
24 }
Figura 8.10: Exemplo de organizao com o padro Estado Inicial da Tela.
135
Padres Relacionados: O padro Tela como Unidade (Seo 8.4.1) ajuda a garantir que o mnimo de
informaes necessrias sero carregadas para o teste, facilitando a implementao desse padro.
Usos Conhecidos: Os testes dos sistemas Janus e GinLab seguem esta organizao.
136
8.4.3 Camada de Abstrao de Funcionalidades
Tipo: Organizacional
Quando utilizar: Idealmente, para todos os testes de interface de usurio. A camada de abstrao de
funcionalidades, descrita no padro, pode ser compartilhada pelos testes de correo da interface,
leiaute, usabilidade e acessibilidade.
Inteno: Separar o cdigo da manipulao da interface daquele que descreve os cenrios de testes para
facilitar a escrita e o entendimento dos testes.
Motivao: Muitos casos de testes da interface so descritos por meio de vericaes realizadas aps
a execuo de uma ou mais funcionalidades do sistema. No entanto, a chamada de uma fun-
cionalidade do sistema via interface grca , geralmente, representada por diversos comandos de
um usurio. Por isso, o cdigo-fonte que contm os cenrios de testes de interface tende a car
extenso e pouco legvel.
Alm disso, muitos cenrios de testes utilizam o mesmo conjunto de aes que manipulam a inter-
face, mas com pequenas diferenas. Portanto, natural a separao destas aes para reutilizao
de cdigo-fonte.
Soluo: Separar os casos de testes em duas camadas: uma de abstrao de funcionalidades, que ir
manipular a interface como um usurio, e outra, que ir fazer as chamadas das funcionalidades e
as vericaes necessrias na interface.
Consequncias: A abstrao das funcionalidades diminui a extenso do cdigo dos testes e melhora
a legibilidade. Esta modularizao tambm permite a melhor reutilizao do cdigo de acesso
interface, podendo at ser utilizada por baterias de tipos de testes diferentes.
Implementao: O teste deve conter apenas chamadas s funcionalidades da interface e vericaes.
Todo conjunto de aes de usurio que compe uma funcionalidade deve ser encapsulado em um
mtodo separado de uma classe independente dos casos de teste, ou seja, uma classe que pertence
camada de abstrao de funcionalidades. A Figura 8.11 mostra como ca a organizao do
cdigo-fonte dos testes utilizando esse padro.
Figura 8.11: Organizao recomendada de testes de interface de usurio.
Exemplo - WUI - Java/JUnit/WebDriver: A Figura 8.12 possui um exemplo de teste de uma tela de
autenticao de um sistema Web sem utilizar o padro Camada de Abstrao de Funcionali-
dades. Note que os testes so relativamente extensos para simplicidade do que se pretende veri-
car. Isso se deve s diversas aes necessrias para se autenticar no sistema.
Esses testes podem ser separados em duas camadas: a Camada de Abstrao de Funcionali-
dades como mostrado na Figura 8.13 e a de vericaes, que contm a descrio legvel dos
137
1 // referncias do JUnit
2 import org.junit.Test;
3 import static org.junit.Assert.*;
4 // referncias do WebDriver
5 import org.openqa.selenium.By;
6 import org.openqa.selenium.WebDriver;
7 import org.openqa.selenium.WebElement;
8
9 public class LoginTests {
10 public static final HOST = "http://localhost:8000";
11 // Cria uma instncia do navegador
12 WebDriver driver = new HtmlUnitDriver();
13
14 @Test
15 public void testaLoginValidoRedirecionaParaPaginaInicial() {
16 // Abre pgina de login
17 driver.get(HOST + "/login");
18 // Encontra objetos na tela
19 WebElement usuario = driver.findElement(By.id("usuario"));
20 WebElement senha = driver.findElement(By.id("senha"));
21 WebElement login = driver.findElement(By.id("login"));
22 // Simula aes do usurio
23 usuario.sendKeys("admin");
24 senha.sendKeys("1234");
25 login.click();
26 // Faz verificaes
27 assertTrue(driver.getCurrentUrl().endsWith("/home"));
28 assertTrue(driver.getPageSource().contains("Ol admin!"));
29 }
30
31 @Test
32 public void testaLoginInvalidoMostraMensagemDeErroNaMesmaTela() {
33 // Abre pgina de login
34 driver.get(HOST + "/login");
35 // Encontra objetos na tela
36 WebElement usuario = driver.findElement(By.id("usuario"));
37 WebElement senha = driver.findElement(By.id("senha"));
38 WebElement login = driver.findElement(By.id("login"));
39 // Simula aes do usurio
40 usuario.sendKeys("admin");
41 senha.sendKeys("senha_errada");
42 login.click();
43 // Faz verificaes
44 assertTrue(driver.getCurrentUrl().endsWith("/login"));
45 assertTrue(driver.getPageSource().contains("Login invlido."));
46 }
47
48 }
Figura 8.12: Exemplo de testes de uma pgina Web de autenticao sem utilizar o padro Camada de
Abstrao de Funcionalidades.
138
testes, como mostrado na Figura 8.14. Note que a camada de vericaes possui a mesma es-
trutura do exemplo original e apenas substitui os comandos de usurio por chamadas camada de
abstrao das funcionalidades.
J a camada de abstrao de funcionalidades deve apenas possuir mtodos ou funes que encap-
sulem um conjunto de aes que simulem a chamada de uma funcionalidade por um usurio do
sistema. Dessa forma, essa camada deve ser independente dos casos de teste; ou seja, os testes
devem ter conhecimento da camada de abstrao, mas no o contrrio. Alm disso, a camada no
deve possuir vericaes, pois no faz parte de seu objetivo testar o sistema.
1 // interessante separar a camada de abstrao das funcionalidades em um local
diferente
2 package funcionalidadesUI;
3
4 // referncias do WebDriver
5 import org.openqa.selenium.By;
6 import org.openqa.selenium.WebDriver;
7 import org.openqa.selenium.WebElement;
8 // Note que no h dependncias do arcabouo de teste porque no so feitas
verificaes nesta camada
9
10 public class Sistema {
11 WebDriver driver;
12 String host;
13
14 public Sistema(WebDriver driver, String host) {
15 this.driver = driver;
16 this.host = host;
17 }
18
19 public void login(String usuario, String senha) {
20 // Abre pgina de login
21 driver.get(host + "/login");
22 // Encontra objetos na tela
23 WebElement username = driver.findElement(By.id("username"));
24 WebElement password = driver.findElement(By.id("password"));
25 WebElement login = driver.findElement(By.id("login"));
26 // Simula aes do usurio
27 username.sendKeys(usuario);
28 password.sendKeys(senha);
29 login.click();
30 }
31 }
Figura 8.13: Refatorao do exemplo da Figura 8.12. Essa classe faz parte da Camada de Abstrao
de Funcionalidades.
Ainda, a camada de abstrao pode ser parametrizvel para que ela seja adaptvel a vrios casos
de teste sem replicao de cdigo. Tambm podem ser criados mtodos como acar sinttico
para as combinaes de parmetros mais comuns, o que facilita a escrita dos testes, assim como
melhora a sua legibilidade. AFigura 8.15 possui acares sintticos comuns que podemser usados
em diversos casos de testes e em diferentes baterias de testes.
Padres Relacionados: A inicializao das interfaces pode ser includa na camada de abstrao de
funcionalidades, dessa forma, essa organizao pode ser integrada com as recomendaes do
padro Tela como Unidade (Seo 8.4.1).
139
1 // referncias do JUnit
2 import org.junit.Test;
3 import static org.junit.Assert.*;
4 // referncias do WebDriver
5 import org.openqa.selenium.WebDriver;
6
7 public class LoginTests {
8 public static final HOST = "http://localhost:8000";
9 WebDriver driver = new HtmlUnitDriver();
10 Sistema sistema = new Sistema(driver, HOST);
11
12 @Test
13 public void testaLoginValidoRedirecionaParaPaginaInicial() {
14 sistema.login("admin", "123456");
15 // Faz verificaes
16 assertTrue(driver.getCurrentUrl().endsWith("/home"));
17 assertTrue(driver.getPageSource().contains("Ol admin!"));
18 }
19
20 @Test
21 public void testaLoginInvalidoMostraMensagemDeErroNaMesmaTela() {
22 sistema.login("admin", "senha_errada");
23 // Faz verificaes
24 assertTrue(driver.getCurrentUrl().endsWith("/login"));
25 assertTrue(driver.getPageSource().contains("Login invlido."));
26 }
27
28 }
Figura 8.14: Continuao da refatorao do exemplo da Figura 8.12. Camada que contm as vericaes
utilizando a Camada de Abstrao de Funcionalidades.
1 // ...
2 public class Sistema {
3
4 public void login(String usuario, String senha) {
5 // ...
6 }
7
8 public void logaComoAdministrador() {
9 login("admin", "123456");
10 }
11
12 public void logaComoUsuarioComum() {
13 login("user", "1234");
14 }
15 }
Figura 8.15: Acares sintticos para melhorar ainda mais a legibilidade dos testes.
140
Usos Conhecidos: O sistema Janus organiza seus testes de interface utilizando esse padro. A docu-
mentao da ferramenta WebDriver descreve o padro Objeto Pgina (Page Object)
8
, que descreve
como devem ser implementados os objetos da Camada de Abstrao de Funcionalidades.
8
http://code.google.com/p/selenium/wiki/PageObjects.
141
8.4.4 Fotograa da Interface
Tipo: Organizacional
Quando utilizar: Idealmente, em todos os casos de teste de interface grca de usurio.
Inteno: Facilitar a anlise dos testes que falham por meio de uma fotograa da interface que cap-
turada no momento em que o erro ocorre.
Motivao: Testes de interface podem ter resultados falso-negativos por muitas razes, como devido
a alteraes do leiaute, erros de implementao do teste ou, at mesmo, por problemas de in-
fraestrutura, para o caso de testes integrados. Por causa disso, pode ser demorado identicar o
motivo das falhas do teste, principalmente quando necessrio depurar o sistema. A fotograa
serve de complemento s outras informaes armazenadas pelo arcabouo de teste, como os val-
ores de variveis.
Soluo: Capturar uma fotograa da interface toda vez que um teste falhar, a qual dever ser o ponto
de partida para anlise do erro.
Consequncias: A fotograa pode facilitar o entendimento do que aconteceu de errado ou at mesmo
elucidar imediatamente a causa do erro.
Implementao: A implementao desse padro complexa, pois pode depender de detalhes do sis-
tema operacional, das bibliotecas de interface ou dos navegadores. Por isso, s recomendvel
utilizar esse padro com o auxlio de alguma ferramenta que disponibilize essa funcionalidade.
Contudo, algumas ferramentas de teste de interface j fornecem em sua biblioteca padro de fun-
cionalidades esse tipo de comando, como o caso da ferramenta Selenium.
Exemplo - WUI Java/Selenium/Util4Selenium: A ferramenta Util4Selenium disponibiliza um as-
pecto que facilita a implementao desse padro de modo que reduzido drasticamente a repli-
cao de cdigo-fonte. A Figura 8.16 mostra um trecho da implementao desse aspecto. Todos
os mtodos que forem anotados com o metadado @Screenshot recebero um cdigo que auto-
maticamente capturar uma fotograa da interface Web caso uma exceo seja lanada. Quando
uma classe possuir essa informao, ento o mesmo cdigo adicionado a todos os seus mtodos.
Um bom modo de utilizar essa ferramenta com a criao de uma classe base (Figura 8.17) que
dever ser herdada por todas as classes de testes de interface do sistema (Figura 8.18). Como
ela possui a anotao @Screenshot, ento o padro Fotograa da Interface ser automaticamente
propagado para todos os casos de teste do sistema.
Padres Relacionados: Esse padro tambm pode ser utilizado na Camada de Abstrao de Fun-
cionalidades (Seo 8.4.3).
Usos Conhecidos: A ferramenta Selenium disponibiliza uma funcionalidade que bate uma fotograa
da pgina renderizada no navegador Web e a Util4Selenium utiliza essa funcionalidade de forma
automtica, por exemplo, ela pode ser congurada para bater fotos toda vez que um caso de teste
falhar, como mostrado no exemplo anterior.
142
1 // Referncias Java e AspectJ
2 import org.aspectj.lang.reflect.MethodSignature;
3 import java.lang.annotation.Annotation;
4 import org.aspectj.lang.Signature;
5 // Outras referncias foram ocultas
6
7 public aspect AspectScreenshotByAnnotation {
8 // Qualquer mtodo ou classe anotado com @Screenshot
9 pointcut annotationHandler():
10 if(System.getProperty("selenium.screenshot") != null &&
11 System.getProperty("selenium.screenshot").equals("true")) &&
12
13 // Mtodo
14 // @Screenshot (void|objeto) umMetodo(argumentos): public,private..
15 (execution(@utilities.util4selenium.annotations.Screenshot * *(..)) ||
16
17 // Classe
18 // (public/private..) (@Screenshot UmaClasse).umMetodo(argumentos)
19 (execution(* (@utilities.util4selenium.annotations.Screenshot *).*(..)) &&
20 !execution(public * selenium())));
21
22 after() throwing(): annotationHandler() {
23 Signature signature = thisJoinPoint.getSignature();
24 MethodSignature methodSignature = (MethodSignature) signature;
25 Annotation annotation = methodSignature.getMethod().getAnnotation(Screenshot.
class);
26 if(annotation == null) {
27 annotation = signature.getDeclaringType().getAnnotation(Screenshot.class);
28 }
29 if(annotation != null && thisJoinPoint.getThis() instanceof SeleniumClass) {
30 SeleniumClass obj = (SeleniumClass) thisJoinPoint.getThis();
31 ScreenshotHelper helper = new ScreenshotHelper(obj.selenium());
32 String clazz = signature.getDeclaringType().getSimpleName();
33 String method = signature.getName();
34 helper.screenshot(clazz + "-" + method);
35 }
36 }
37 }
Figura 8.16: Aspecto fornecido pela biblioteca Util4Selenium para bater fotograas da interface.
143
1 // Classe base pra todas clases de teste da interface Web
2
3 // Referncias do TestNG
4 import org.testng.annotations.AfterSuite;
5 import org.testng.annotations.BeforeSuite;
6 // Referncias do Util4Selenium
7 import testutilities.util4selenium.annotations.Screenshot;
8 import testutilities.util4selenium.annotations.Screenshot.ScreenshotPolicy;
9 // Referncias do Selenium-RC/Java
10 import com.thoughtworks.selenium.DefaultSelenium;
11 import com.thoughtworks.selenium.Selenium;
12
13 // Padro Fotografia da Interface
14 @Screenshot(policy = ScreenshotPolicy.ON_ERROR)
15 public class SeleniumTestCase {
16 public Selenium navegador;
17
18 @BeforeSuite public void abreNavegador() {
19 navegador = new DefaultSelenium(
20 "localhost", 4444,
21 "*chrome", "http://localhost:8000");
22 navegador.start();
23 }
24
25 @AfterSuite public void fechaNavegador() {
26 navegador.stop();
27 }
28 }
Figura 8.17: Classe base que ativa o padro Fotograa da Interface.
1 // Referncias do JUnit + Hamcrest
2 import org.junit.*;
3 import static org.junit.Assert.*;
4 import static org.hamcrest.Matchers.*;
5 // Referncias do Selenium-RC/Java
6 import org.testng.annotations.Test;
7
8 public class MapaDoSiteTests extends SeleniumTestCase {
9
10 @Before public void acessaPaginaEmTeste() {
11 navegador.open("/mapadosite");
12 }
13
14 @Test public void verificaLinksImportantes() {
15 // Se falhar, ser capturada uma fotografia da interface e
16 // salva no arquivo MapaDoSiteTests-verificaLinksImportantes.png
17 }
18 }
Figura 8.18: Exemplo de classe de teste que utiliza a classe base SeleniumTestCase.
144
8.4.5 Localizar Elemento por ID
Tipo: Robustez
Quando utilizar: Em todos os testes, principalmente para localizao dos principais componentes da
interface.
Inteno: Tornar a localizao de componentes na interface independente do leiaute, do estado dos
componentes e da internacionalizao (i18n) do sistema.
Motivao: A localizao dos componentes da interface uma tarefa delicada. Os testes no devem
ser frgeis a tal ponto de quebrarem por qualquer alterao do leiaute.
Soluo: Atribuir IDs aos principais componentes da interface de usurio para facilitar a localizao
dos mesmos. Apenas necessrio cuidado para que mais de um componente no possua ID
idntico, j que uma mesma tela pode conter diversos painis que possuem campos semelhantes.
Uma forma de organizao que evita que isso acontea concatenar os nomes dos painis ou das
telas como prexo do ID do componente.
Consequncias: O cdigo de localizao dos elementos pode car mais claro, pois no necessrio
o uso de expresses de busca como DOM e XPath. Alm disso, o identicador tem como pre-
missa ser uma propriedade nica e exclusiva de um elemento, portanto facilita a identicao dos
componentes.
Implementao: Os componentes que sero manipulados precisam ter IDs denidos pelos progra-
madores. Apesar disso, algumas ferramentas de testes permitem que se dena os IDs em tempo
de execuo do teste. Neste caso, recomendado separar a denio dos IDs em um local isolado
para no prejudicar a legibilidade dos testes. Um bom local para denio dos IDs na Camada
de Abstrao de Funcionalidades.
importante notar que existem arcabouos de interface de usurio que geram IDs dinamicamente
para os componentes, contudo esses IDs podem prejudicar a legibilidade dos testes. Para que
no sejam gerados identicadores repetidos, os respectivos algoritmos concatenam caracteres adi-
cionais e no intuitivos que podem criar ambiguidade no entendimento dos cenrios de teste.
Exemplo: A Figura 8.19 mostra um exemplo do padro com a ferramenta WebDriver e HTMLUnit.
1 // Cria um cliente (navegador)
2 WebDriver driver = new HtmlUnitDriver();
3 // Procura um link pelo ID
4 WebElement link = driver.findElement(By.id("mapadosite"));
Figura 8.19: Exemplo de localizao de um elemento por ID com WebDriver e HTMLUnit.
Padres Relacionados: O padro Localizar Elemento por Tipo do Componente (Seo 8.4.6) serve
de alternativa para quando esse padro no puder ser utilizado.
Usos Conhecidos: um padro das ferramentas de teste de interface fornecer mecanismos para lo-
calizar elementos por um identicador.
145
8.4.6 Localizar Elemento por Tipo do Componente
Tipo: Robustez
Quando utilizar: Quando o componente a ser localizado no possui um ID, ou, ento, quando o tipo
do componente utilizado importante para o entendimento do teste.
Inteno: Tornar explcito o tipo de componente no cdigo do teste para facilitar a compreenso.
Motivao: Em algumas situaes, mais fcil de entender um caso de teste quando sabemos quais os
tipos dos componentes que esto sendo manipulados. Quando utilizamos apenas o ID, o tipo do
componente abstrado.
Soluo: Localizar um componente pelo seu tipo. No entanto, quando a tela possuir mais de um com-
ponente do mesmo tipo, outras propriedades devem ser usadas para ltrar apenas os elementos
desejados. Nesses casos, d preferncia para propriedades que no estejam relacionadas com o
leiaute da tela.
Consequncias: O cdigo de localizao dos elementos tende a car mais extenso e mais preso aos
tipos dos componentes utilizados. Contudo, o teste pode car mais fcil de ser entendido.
Implementao: Algumas ferramentas disponibilizam mtodos genricos, que buscam qualquer tipo
de componente. J outras possuem mtodos que buscam um tipo de componente especco. Para
esse ltimo, caso pode-se utilizar apenas o identicador do componente.
Implementao - WUI: Geralmente, as ferramentas permitem localizar elementos por expresses
XPath. Para explicitar que o componente uma caixa de texto, poderia-se utilizar a seguinte
expresso: input[type="text", id="id_do_componente"]. Este tipo de expresso pode en-
contrar mais de um elemento, por isso a necessidade do ID. Ainda h a possibilidade de utilizar
outras propriedades, mas devem ser evitadas, pois isso poderia tornar o teste frgil em relao a
alteraes do leiaute.
Exemplo: A Figura 8.20 mostra um exemplo com a ferramenta WebDriver e HTMLUnit para buscar
um elemento na rvore HTML. A busca feita por meio de uma expresso XPath, que muito
exvel e aceita tanto como parmetros de leiaute como de propriedades do componente. Contudo,
a expresso contm apenas informaes referentes ao tipo de componente e de propriedades que
so nicas do elemento.
1 // Cria um cliente (navegador)
2 WebDriver driver = new HtmlUnitDriver();
3 // Procura um link pelo seu tipo e por suas propriedades, com XPath.
4 WebElement link = driver.findElement(By.xpath("//a[@href=/mapadosite]"));
Figura 8.20: Exemplo de localizao de um elemento pelo tipo com WebDriver e HTMLUnit.
Padres Relacionados: Estratgia alternativa para o padro Localizar Elemento por ID (Seo 8.4.5).
Usos Conhecidos: um padro das ferramentas de testes de interface Web, tais como Selenium e
HTMLUnit, fornecer mecanismos para localizar os elementos atravs de XPath.
146
8.4.7 Localizar Clula de Tabela pelo Cabealho e Contedo
Tipo: Robustez
Quando utilizar: Em testes que fazem vericaes em clulas especcas de tabelas.
Inteno: Tornar a localizao de clulas de tabelas menos frgil em relao a alteraes de leiaute ou
a mudana dos dados.
Motivao: Muitas vezes necessrio vericar o contedo ou obter componentes de clulas especcas
de tabelas. Um modo de acessar clulas especcas a partir dos ndices da linha e coluna (Figura
8.21), mas essa abordagem tornam os testes muito frgeis. Qualquer alterao do leiaute ou novo
registro carregado pode quebrar os testes.
1 // Referncias do HTMLUnit
2 import com.gargoylesoftware.htmlunit.html.HtmlPage;
3 import com.gargoylesoftware.htmlunit.html.HtmlTable;
4 import com.gargoylesoftware.htmlunit.html.HtmlTableCell;
5
6 public class HTMLTableHelper {
7 public HtmlTableCell buscaCelulaPeloLayout(HtmlPage pagina, String idTabela, int
linha, int coluna) {
8 HtmlTable tabela = pagina.getHtmlElementById(idTabela);
9 return tabela.getCellAt(linha, coluna);
10 }
11 }
Figura 8.21: Busca da clula de uma tabela pelo leiaute.
Soluo: Identicar o ndice da clula por meio de um algoritmo que percorra todas as linhas de uma
coluna com determinado cabealho at que o contedo da clula corrente seja o desejado. Quando
os dados da tabela esto organizados por colunas em vez de linhas, o algoritmo deve seguir a
mesma ideia, mas percorrendo todas as colunas de uma linha.
Consequncias: Apesar de os testes perderem desempenho, eles cam mais resistentes a alteraes do
leiaute. A legibilidade do teste tambm melhora, pois os nmeros dos ndices so substitudos por
strings que so mais intuitivas.
Implementao: Algumas ferramentas j disponibilizam mtodos prontos para facilitar a busca de
clulas. Quando utilizada uma que no possui esta facilidade, importante criar um mtodo
independente do caso de teste para realizao dessa tarefa. Dessa forma, o mtodo pode ser re-
utilizado para outros casos de teste e at mesmo ser enviado como sugesto para a equipe da
ferramenta.
Este mtodo deve receber o identicador da tabela e uma informao da linha e uma da coluna.
Supondo que cada linha da tabela representa um registro, a informao da coluna pode ser o ID
da clula de cabealho, que, geralmente, a primeira da tabela. Para identicar a linha, pode
se passar parte do contedo esperado, como textos, componentes ou expresses regulares. Outra
abordagem mais orientada a objetos seria criar as estruturas Tabela, Linha, Coluna e Clula. Com
isso, o algoritmo pode car mais modularizado e exvel.
Algumas tabelas so mais complexas, podendo conter outras tabelas internas ou outras formas de
diviso. Se no for possvel seguir este padro completamente, pode ser interessante utiliz-lo
em conjunto com ndices. Dessa forma, reduzido o uso de ndices das clulas, tornando o teste
menos frgil.
147
Exemplo: A ferramenta HTMLUnit j fornece diversos mtodos para leitura de tabelas que facilitam
bastante a criao dos testes, contudo, ainda possvel criar mtodos auxiliares para forar o uso
desse padro. A Figura 8.22 mostra duas funcionalidades que percorrem as clulas da tabela em
busca da clula desejada para manipulao e vericao. Apenas importante notar que essas
funcionalidades nem sempre podem ser utilizadas, pois elas no consideram a complexidade das
tabelas e tambm supe que as clulas possuem contedo nico.
1 // Referncias do HTMLUnit
2 import com.gargoylesoftware.htmlunit.html.HtmlPage;
3 import com.gargoylesoftware.htmlunit.html.HtmlTable;
4 import com.gargoylesoftware.htmlunit.html.HtmlTableCell;
5 import com.gargoylesoftware.htmlunit.html.HtmlTableRow;
6
7 public class HTMLTableHelper {
8 public HtmlTableCell buscaCelulaPorConteudo(HtmlPage pagina, String idTabela,
String conteudoLinha) {
9 HtmlTable tabela = pagina.getHtmlElementById(idTabela);
10 for(HtmlTableRow linha: tabela.getRows()) {
11 for(HtmlTableCell celula: linha.getCells()) {
12 if(celula.asText().contains(conteudoLinha))
13 return celula;
14 }
15 }
16 throw new RuntimeException("Clula com contedo " + conteudoLinha + " no
encontrada.");
17 }
18
19 public HtmlTableCell buscaCelulaPorCabecalhoEConteudo(HtmlPage pagina, String
idTabela, String idCabecalho, String conteudoLinha) {
20 HtmlTable tabela = pagina.getHtmlElementById(idTabela);
21
22 HtmlTableRow linhaCabecalho = tabela.getRow(0);
23 List<HtmlTableCell> celulasCabecalho = linhaCabecalho.getCells();
24 int indiceColunaReferencia = -1;
25 for(HtmlTableCell celula: celulasCabecalho) {
26 indiceColunaReferencia += 1;
27 if(celula.getId().equals(idCabecalho))
28 break;
29 }
30 if(indiceColunaReferencia == -1 || indiceColunaReferencia == celulasCabecalho.
size())
31 throw new RuntimeException("Cabealho de ID " + idCabecalho + " no
encontrado.");
32
33 for(HtmlTableRow linha: tabela.getRows()) {
34 HtmlTableCell celula = linha.getCell(indiceColunaReferencia);
35 if(celula.asText().contains(conteudoLinha))
36 return celula;
37 }
38 throw new RuntimeException("Clula com contedo " + conteudoLinha + " no
encontrada.");
39 }
40 }
Figura 8.22: Exemplo de Localizar Clula pelo Cabealho e Contedo com o HTMLUnit.
Padres Relacionados: Os padres Localizar Elemento por ID (Seo 8.4.5) e Localizar Elemento
148
por Tipo do Componente (Seo 8.4.6) devem ser utilizados para implementao desse padro.
Usos Conhecidos: Sistema GinLab e Janus implementame utilizamesse padro. As ferramentas HTM-
LUnit e Util4Selenium tambm fornecem essas funcionalidades.
8.5 Antipadres
Nas subsees seguintes sero descritos antipadres de automao para testes que envolvem a interface
de usurio, seguindo o esqueleto apresentado na Seo 5.4. Os indcios de problemas citados nos padres
so descritos na Seo 5.2.
8.5.1 Navegao Encadeada
Tipo: Organizacional
Contexto: Para testar uma tela pode ser necessrio a navegao entre diversas telas do sistema. Pen-
sando em desempenho e praticidade para criao dos testes, pode-se criar um grande teste que
vai vericando as telas medida que elas vo sendo carregadas. Essa prtica tende a criar testes
muito extensos, complexos e ilegveis. Isso os torna difceis de manter e entender, alm de que
alteraes em uma das telas pode atrapalhar os testes de outras.
Indcios de Problemas Relacionados: Obscure Test, Test Code Duplication, Erratic Test, Fragile Test,
Frequent Debugging, Slow Tests, Buggy Tests, Developers Not Writing Tests e High Test Mainte-
nance Cost (vide Seo 5.2).
8.5.2 Localizar Componente pelo Leiaute
Tipo: Robustez
Contexto: Dependendo das ferramentas de teste possvel localizar um componente de muitas
maneiras. Uma das alternativas utilizar propriedades como a posio na tela ou, ainda, a or-
dem de exibio. No entanto, qualquer alterao no leiaute pode quebrar o teste, mesmo que
o sistema esteja correto. Como todo teste que falha requer uma avaliao, os testes quebrados,
que so falso-negativos, desperdiam tempo de desenvolvimento com a depurao dos testes e do
sistema.
Indcios de Problemas Relacionados: Obscure Test, Fragile Test, Frequent Debugging e High Test
Maintenance Cost (vide Seo 5.2).
8.5.3 Vericaes Rgidas
Tipo: Robustez
Contexto: Existem ferramentas ou tnicas que fazem vericaes muito rgidas na interface de usurio.
Por exemplo, h ferramentas que fazem anlises pixel a pixel para vericar se houveram alter-
aes. Outra abordagem transforma o cdigo da interface em um hash, que pode ser comparado
com o mesmo propsito. Estas abordagens so muito inexveis, pois qualquer refatorao e at
identao do cdigo-fonte pode quebrar os casos de teste.
Indcios de Problemas Relacionados: Fragile Test, Developers Not Writing Tests e High Test Mainte-
nance Cost (vide Seo 5.2).
149
8.6 Concluses
Para fazer testes de interface fundamental a utilizao de arcabouos de testes especializados. No
obstante, a qualidade dos testes automatizados que simulam usurios dependem da boa abstrao e das
facilidades que os arcabouos de testes de interface disponibilizam. Tambm importante notar que
essas ferramentas so geralmente complexas de implementar, por isso muitas ainda possuem limitaes.
As boas ferramentas de gravao de interao dos usurios so muito teis para criao de vrios
tipos de testes que envolvem a interface de usurio. No entanto, necessrio ateno com o cdigo-fonte
por elas gerado para que os testes automatizados no sejam de baixa qualidade, prejudicando e atrasando
o desenvolvimento do sistema.
O desempenho dos testes de interface tambm importante. recomendvel utilizar ferramentas
leves e criar testes completamente independentes para que seja possvel execut-los em paralelo. Bate-
rias de testes independentes podem ser executadas em diversos ambientes dinstintos, por exemplo, para
buscar erros de portabilidade.
Alm disso, h diversos padres e antipadres que podem inuenciar signicativamente na organi-
zao e na robustez dos testes automatizados, o que fundamental para que a automao dos testes seja
bem feita e ajude no dia a dia do desenvolvimento de sistemas.
150
Captulo 9
Tcnicas de Desenvolvimento de Software
com Testes Automatizados
Como foi discutido nos captulos anteriores, as baterias de testes automatizados precisam estar bem
implementadas para que o custo-benefcio dessa prtica seja baixo. Assim como o cdigo-fonte do
sistema, o dos testes automatizados tambm est sujeito a imperfeies que podem trazer malefcios
graves para um projeto. Por isso, importante o conhecimento de boas prticas e padres que auxiliem
na criao de testes automatizados de qualidade.
Existem diversas tcnicas de desenvolvimento de software com testes automatizados que inuen-
ciam diretamente na qualidade dos testes e do sistema. Essas tcnicas so descritas por processos sim-
ples e sistemticos. Basicamente, elas denem a relao dos testes automatizados com o processo de
desenvolvimento e propem um roteiro de quando implementar os casos de teste de correo.
Dentre as tcnicas que sero descritas esto TAD, TFD, TDD e BDD, que j foram citadas no
Captulo 3. Entretanto, sero apresentadas as vantagens e as desvantagens de cada tcnica, assim como
algumas comparaes entre elas.
Apesar de as tcnicas citadas neste captulo serem generalizadas para qualquer tipo de teste (vide
a NASA que usava o ciclo de TDD para cartes perfurados [84]), ser evidenciado apenas os testes
automatizados de unidade, com exceo do caso de BDD que incluir testes de aceitao.
Os testes de correo de interface de usurio tambm podem ser escritos com as tcnicas citadas,
mas algumas delas so incompatveis com certas ferramentas de testes de interface. Por exemplo, TDD e
TFD requerem que os testes sejam feitos antes da implementao, o que inviabiliza o uso de gravadores
de interao.
9.1 Testes Aps a Implementao (TAD)
Testar aps a implementao (TAD de Test After Development) a tcnica de implementar e executar os
testes depois que um ou todos os mdulos de um sistema esto nalizados (Figura 9.1). Esse o modo
convencional e natural da abordagem dos testes dinmicos (vide Seo 3.1), j que para executar testes
em tempo de execuo necessrio que o sistema ou parte dele esteja implementado.
Quando os testes so implementados aps classes ou mtodos serem nalizados, TAD pode inuen-
ciar signicativamente o cdigo-fonte e a arquitetura do sistema devido ao rpido feedback dos testes.
J quando os testes so realizados apenas ao trmino do desenvolvimento, TAD tende a se tornar uma
prtica de controle e garantia de qualidade para as unidades do sistema.
Todavia, a proposta principal de TAD fazer vericaes no sistema. TAD no s surgiu em con-
junto com testes automatizados e arcabouos de teste, como tambm herdou a caracterstica da abor-
dagem tradicional de testes manuais de software de realizar os testes aps a implementao. No faz
151
Figura 9.1: Fluxo do TAD.
parte da proposta principal de TAD inuenciar na criao de cdigo-fonte do sistema.
Fazer os testes aps a implementao coerente, j que sistemas sem testes podem funcionar corre-
tamente, mas testes sem sistema no fazem sentido; portanto, o ideal sempre priorizar a implementao
do sistema (mesmo nos dias de hoje). Apesar disso, essa abordagem, assim como as outras, no a mais
indicada para todas as situaes e projetos. A seguir sero apresentadas as principais caractersticas de
TAD e quando recomendamos sua utilizao.
Caractersticas
Quando os testes so implementados aps um trecho do sistema ser nalizado, eles precisam se adaptar
estrutura de cdigo j existente. Se a testabilidade do cdigo alta, ento no h grandes problemas
durante a automao. Os testes no inuenciam no design do sistema, mas se tornam teis para veri-
cao. Entretanto, se a testabilidade do cdigo baixa, ento a automao de testes pode seguir por
vrios caminhos.
A primeira opo parar a automao de teste at que o sistema seja refatorado para melhorar a
estrutura e aumentar a testabilidade. Nesse caso, a automao no efetivamente concretizada, mas ela
serviu para fornecer feedback sobre a modelagem do sistema.
No entanto, se os testes automatizados forem realmente implementados, ento pode ser necessrio
o uso do antipadro Ganho para os Testes (Seo 6.5.1), que suja o cdigo do sistema, para contornar
as diculdades causadas pelo design acoplado. Caso esse antipadro no seja aplicado, ento o cdigo
dos testes que se tornaro rebuscados. Como os testes precisam contornar as falhas de testabilidade
para conseguir simular os cenrios desejados, seu cdigo-fonte provavelmente car mais extenso e,
consequentemente, com pior legibilidade e clareza.
Por causa disso, a implementao e a manuteno dos testes cam mais complexas e, portanto, mais
cara. Esta queda do custo-benefcio da automao dos testes pode resultar na diminuio do escopo das
vericaes, ou seja, cenrios importantes podem deixar de ser realizados e a cobertura dos testes tende
a diminuir.
A falsa impresso de o sistema estar nalizado e correto, em conjunto com a diculdade de criar os
casos de teste, pode levar a equipe de desenvolvimento ou gerentes a crer que a automao dos testes
desnecessria. Por isso, importante lembrar que o alto custo de manuteno dos sistemas sem testes
automatizados no se deve apenas fase de desenvolvimento, mas, principalmente, a mdio e longo
prazo.
152
De qualquer maneira, em casos extremos de diculdade, a automao de testes pode ser realmente
desnecessria. Em situaes em que a testabilidade muito baixa, mais vantajoso fazer testes manuais
e integrados que consigam simular os principais casos de testes. Apenas importante notar que qualquer
cenrio que diminua as tarefas de vericao do sistema torna propcio a identicao de erros em
ambientes de produo.
Quando Utilizar
O fato de TAD possuir fases distintas para implementar e testar uma vantagem para situaes espec-
cas, como para a manuteno de sistemas legados. Como a automao de testes ainda uma prtica
recente, muitos sistemas legados que precisam de manuteno no possuem baterias de testes automati-
zados.
J que a manuteno desses sistemas pode ser uma tarefa crtica, recomendvel que sejam feitos
pelo menos algumas baterias de testes automatizados antes de alterar o cdigo-fonte para certicar que
erros de regresso no sero adicionados [55]. Assim, TAD a abordagem mais recomendada para estes
cenrios. Contudo, aps a criao de um conjunto pertinente de casos de testes, podem ser utilizadas
outras tcnicas para implementar novos testes e alteraes do sistema.
Outra situao tpica em que TAD recomendada quando um sistema possui uma falha j identi-
cada. Antes corrigi-la, deve-se criar um caso de teste que reproduz o cenrio defeituoso. Este caso de
teste ajuda a identicar quando a tarefa de correo foi nalizada, e serve de precauo para que o erro
no ocorra novamente.
Testar depois da implementao tambm til para as equipes que esto comeando a aprender
testes automatizados e as ferramentas de teste. Como TAD possui como proposta principal apenas
testar o sistema, o estudo ca voltado para a automao de testes. Dessa forma, o aprendizado no
desvirtuado para a soluo de problemas, elaborao de arquitetura ou detalhes de implementao.
9.2 Testes a Priori (TFD)
Desenvolvimento com testes a priori (TFD de Test-First Development) a tcnica que prope implemen-
tar todos ou uma boa quantidade de casos de teste antes de desenvolver o cdigo-fonte de uma unidade
do sistema.
Para que esses testes sejam implementados, necessrio o conhecimento prvio do que ser a ar-
quitetura do sistema e a assinatura das classes em teste. Ainda, preciso o planejamento prvio dos
casos de testes.
Depois da implementao dos testes, invivel a execuo dos mesmos porque todos devem falhar,
j que nada foi implementado ainda. Alm disso, se a linguagem de programao utilizada tiver tipagem
esttica, o cdigo dos testes pode at mesmo no compilar. Assim, os testes s podero ser executados
aps a implementao dos trechos pertinentes do sistema, que devem seguir o design denido. A imple-
mentao do sistema deve ser feita at que todos os testes possam ser executados com sucesso. Depois
disso, as etapas so repetidas at que a fase de desenvolvimento termine. Esse uxo pode ser visualizado
na Figura 9.2.
A prtica de elaborar casos de testes independentemente da implementao do sistema no nova.
Muitas equipes de analistas de qualidades trabalham dessa forma, s que executam os testes aps o
sistema estar nalizado. Isso possvel porque, para elaborar os casos de testes, necessrio apenas o
conhecimento detalhado dos requisitos.
Contudo, a ideia de implementar os testes antes mesmo do sistema uma abordagem completamente
diferente do modelo tradicional de testes de software. Ela segue fortemente a proposta da preveno de
erros, j que, provavelmente, casos importantes de serem vericados no sero deixados de lado por
problemas com prazo ou por irresponsabilidade, pois o desenvolvimento se d at que todos os testes
153
Figura 9.2: Fluxo do TFD.
obtenham sucesso. Esse aumento da prioridade da vericao do sistema tende a melhorar a sua qual-
idade, assim como minimizar a quantidade de erros encontrados em fases posteriores do desenvolvi-
mento.
Caractersticas
Note que TFD, assim como TAD, sugere que a implementao dos testes e a do sistema sejam tarefas
que se complementem. Contudo, a ordem em que os testes e o sistema so implementados a oposta.
Essa diferena resulta em caractersticas bem peculiares de TFD em relao a TAD.
Da mesma forma em que com TAD os testes precisam se adaptar ao cdigo do sistema, com TFD
o cdigo do sistema induzido a se adaptar ao dos testes, o que resulta na criao de sistemas com
alta testabilidade. Apesar de os testes serem implementados com base em uma arquitetura previamente
denida, as estruturas de dados devem ser modicadas de acordo com o feedback de testabilidade dos
testes. Essas mudanas na arquitetura devem ser de fcil realizao porque o sistema ainda no foi
implementado.
Sendo assim, a automao de testes com TFD pode afetar signicativamente o desenvolvimento
dos sistemas de software. Contudo, imprescindvel o conhecimento de padres e boas prticas de
automao de testes para que o feedback gerado inuencie positivamente no cdigo do sistema. Se os
testes forem mal implementados, provavelmente as falhas de design no sero identicadas.
Alm disso, implementar os testes antes ou depois do sistema no impede que antipadres sejam
utilizados. Aprincipal vantagemde implementar os testes antes do cdigo do sistema deve-se liberdade
para criao de testes implementados de qualidade, ou seja, os antipadres so mais facilmente evitados,
pois no necessrio adaptar o cdigo dos testes a uma arquitetura indesejada do sistema.
Uma boa maneira para evitar antipadres manter o cdigo dos testes o mais simples possvel. Se
os casos de testes estiverem complicados de se elaborar ou de se implementar, um indcio de que algo
do design do sistema ou da unidade precisa ser melhorado. Por exemplo, pode ser um sinal de que a
unidade possui mais de uma responsabilidade, ou de que existe uma intimidade inapropriada entre elas.
J quando a unidade em teste est difcil de ser isolada, um indcio de que no possvel injetar as
dependncias, ou seja, que a construo do objeto est mal implementada.
Contudo, um dos maiores benefcios de se realizar os testes antes da implementao o fato de que
o desenvolvedor forado a reetir sobre o comportamento esperado do sistema e o que pode dar errado
antes mesmo de implement-lo.
154
9.3 Desenvolvimento Dirigido por Testes (TDD)
Desenvolvimento Dirigido por Testes (TDD de Test-Driven Development) uma tcnica de desenvolvi-
mento de software que se d pela repetio disciplinada de um ciclo curto de passos de implementao
de testes e do sistema (Figura 9.3) [82]. Esta tcnica foi descrita em 2002 por Kent Beck no livro
Test-Driven Development: By Example [16].
Figura 9.3: Ciclo de TDD.
O ciclo de TDD denido por trs passos:
1. Implementar apenas um caso de teste;
2. Implementar apenas um trecho de cdigo de produo que seja suciente para o novo caso de
teste ter sucesso de tal modo que no quebre os testes previamente escritos;
3. Se necessrio, refatorar o cdigo produzido para que ele que mais organizado. Vale notar que
refatorao no altera a funcionalidade do sistema e, portanto, no deve quebrar os testes j im-
plementados [59, 14, 122, 79]. Ainda, a refatorao pode ser feita no prprio cdigo dos testes.
TDD comumente confundido com TFD, pois ambas as tcnicas sugerem criar os testes antes da
implementao do sistema, no entanto, as diferenas so signicativas. Ao contrrio de TFD, TDD
sugere a criao dos testes e do sistema como apenas uma tarefa, ou, por outro lado, como duas tarefas
distintas que so realizadas paralelamente e sincronizadamente.
Alm disso, o ciclo de TDD muito menor do que o de TFD, pois escrever apenas um teste e um
pequeno trecho de cdigo por vez muito mais rpido do que pensar em vrias situaes de teste e
do sistema de uma vez. Exatamente por isso, TDD tambm no pode ser descrito como TFD com
Refatorao.
Ainda, TDD no apenas uma tcnica voltada para criao de sistemas com testes automatizados,
ela tambm utilizada para auxiliar a criao do design do sistema, por isso, certos autores preferem
a denominao Test-Driven Design. Isso pode ser resumido como um dos objetivos de TDD, que
escrever um cdigo limpo que funcione.
Caractersticas
Enquanto TAD e TFD apenas adicionam a criao de testes automatizados ao processo do desenvolvi-
mento dos sistemas de software, TDD muda completamente a forma tradicional de implementao de
sistemas. Por isso, existem diversos estudos e pesquisas que tentam provar empiricamente a eccia
155
dessa tcnica [92]. Dentre eles, existem os que obtm concluses neutras, contra e a favor de TDD. Por
causa das inmeras pesquisas realizadas, um estudo foi feito para tentar unir os resultados das pesquisas
para chegar a uma concluso nica, mas mesmo este estudo no obteve concluses signicativas [33].
Os aspectos mais questionveis so: se TDD aumenta a qualidade dos sistemas [147, 25, 94]; se
desenvolver com TDD produtivo [116]; e se TDD inuencia positivamente o design do sistema [75,
74].
TDD uma prtica que ajuda a controlar e garantir a qualidade do sistema. Ela sugere uma forma
de desenvolvimento simples e disciplinada, com forte nfase na preveno de erros e na criao de
sistemas bem modularizados. Dessa forma, se ela for aplicada corretamente, dicilmente no melhorar
a qualidade do produto nal. No obstante, o prprio ciclo de TDD propicia que os testes cubram uma
grande parcela do cdigo-fonte, j que s deve ser implementado o suciente para que os testes sejam
executados com sucesso. A alta cobertura dos testes no uma garantia de qualidade, mas um bom
indcio.
Em relao produtividade, difcil chegar a uma concluso, pois depende muito de cada pessoa.
O tipo e o nvel de experincia de um programador em relao a TDD e o desenvolvimento de software
inuencia na produtividade. Alm disso, existem questes ainda mais subjetivas, como as relacionadas
com os gostos e costumes de cada um. Pode ser difcil e at prejudicial mudar o comportamento de um
desenvolvedor que trabalha h dcadas de uma mesma forma.
Quanto ao design, o ciclo curto de passos denido por TDD cria uma dependncia forte entre o
cdigo do sistema e os testes, o que favorece e facilita a criao de sistemas com alta testabilidade.
um mito dizer que com TDD todo o design de um sistema emerge dos testes, mas eles ajudam signica-
tivamente a criao de parte dele. O mesmo ocorre com TFD, mas com TDD o ritmo de alterao do
design mais dinmico, j que a cada teste e refatorao podem surgir novas ideias.
Contudo, a elaborao prvia de uma arquitetura do sistema deve ser pensada e inicialmente seguida,
mas, a partir da, os casos de teste e as refatoraes guiam a criao e as alteraes no design do sistema.
O design inicial do sistema pode ser elaborado com a ajuda de DDD (Domain-Driven Design) [8]. Outra
maneira de pensar a respeito do design inicial das unidades com o auxlio dos testes de aceitao.
Quando estas estratgias so utilizadas, recomendado o uso de ferramentas apropriadas, como as que
seguem a linguagem de BDD, que ser descrito a seguir.
9.4 Desenvolvimento Dirigido por Comportamento (BDD)
Como foi descrito na seo anterior, TDD no apenas uma prtica de vericao do cdigo-fonte. Ela
uma prtica de desenvolvimento de software que ajuda a criao de um cdigo limpo que funcione e
que inuencie na elaborao do design. Apesar disso, TDD no deve ser utilizado como soluo nica
para criao de sistemas bem desenhados. imprescindvel um vasto conhecimento de programao,
tais como os principais conceitos de modularizao e de orientao a objetos.
Alm disso, um bom design de sistema aquele que representa adequadamente o contexto da apli-
cao e as necessidades do cliente. Para isso, fundamental o entendimento dos requisitos. Mtodos
geis recomendam que haja colaborao com o cliente, principalmente por meio da comunicao fre-
quente e efetiva (preferencialmente face a face).
Contudo, h uma grande ponte entre o entendimento dos requisitos e a implementao pertinente do
cdigo-fonte do sistema e dos testes. Este distanciamento pode ser reduzido com a ajuda dos testes de
aceitao e com a utilizao de uma linguagem nica e uente a todos os membros da equipe, incluindo
os clientes [104]. Uma das tendncias das ferramentas de testes automatizados tornar os testes cada vez
mais prximos de uma documentao do sistema com linguagem natural. Algumas ferramentas criam
DSLs (Domain Specic Languages) prprias para isso, como a Hamcrest; j outras geram documentos
legveis a partir do cdigo dos testes, como a TestDox.
156
Entretanto, mesmo com a ajuda destas ferramentas, no trivial criar uma linguagem ubqua entre
cliente e time de desenvolvimento. Tambm no certo que as histrias sero bem denidas e os
testes de aceitao sero bem implementados. A comunicao e a colaborao entre os envolvidos no
desenvolvimento de um sistema de software algo to subjetivo que pode ser impossvel determinar
todos os possveis problemas que podem ocorrer. Pensar atravs do comportamento de um sistema pode
ajudar a amenizar essas diculdades.
Desenvolvimento Dirigido por Comportamento (BDD de Behavior-Driven Development) uma
prtica de desenvolvimento identicada por Dan North em 2003 [34]. Ela recomenda o mesmo ciclo de
desenvolvimento de TDD, contudo, induzindo os participantes a utilizar uma linguagem diferente. Ao
invs de usar os termos tpicos de testes e vericaes como test suite, test case e assert das ferramentas
xUnit, as ferramentas de BDD induzem o uso de uma linguagem nica (ubqua) entre cliente e equipe
de desenvolvimento. Os termos utilizados por elas so comuns em descries de requisitos, tais como
specication, behavior, context e should.
No obstante, BDD integra explicitamente alguns princpios de DDD, de testes de aceitao e das
reas de qualidade de software para simplicar e sistematizar a denio das funcionalidades e dos
cenrios de teste. A denio das funcionalidades deve complementar o esqueleto denido na Figura
9.4. Este formato simples torna a descrio das funcionalidades especca, mensurvel, vivel, relevante
e estimvel. Um exemplo de histria pode ser visto na Figura 9.5.
1 Funcionalidade: ...
2 Como um(a) ...
3 Quero ...
4 Com o objetivo de ...
Figura 9.4: Esqueleto de histria sugerido por BDD.
1 Funcionalidade: Clculo total de imposto da empresa
2 Como um(a) contador(a)
3 Quero somar todos impostos da empresa dentro de um perodo
4 Com o objetivo de exibir os dados na internet para protestar contra o governo
Figura 9.5: Exemplo de histria no formato sugerido por BDD.
Os cenrios de teste tambm possuem um esqueleto predenido de passos, que o padro das
descries de teste de analistas de qualidade (Figura 9.6). Os passos Dado so semelhantes aos mtodos
de set up das ferramentas xUnit. Os passos Quando correspondem chamada da funcionalidade em
teste. Por ltimo, a chamada Ento anloga s vericaes. A Figura 9.7 possui um exemplo de
cenrio de teste para a histria da Figura 9.5.
A ferramenta JBehave (primeira ferramenta de BDD), que foi criada por Dan North, baseia-se na
leitura de arquivos de texto com histrias descritas no formato de passos, com uma linguagem prxima
a de pessoas que no possuem perl tcnico de computao. O cdigo dos testes (comportamentos)
carregam estes arquivos e os traduzem para fazer chamadas s funcionalidades em teste. Vale ressaltar
que os passos podem ser parametrizveis, o que facilita a reutilizao de cdigo-fonte dos testes.
A ideia do JBehave semelhante da ferramenta Fit
1
, criada por Ward Cunningham por volta de
2002. Aprincipal diferena que, enquanto Fit trabalha comarquivos contendo diversos tipos de tabelas,
JBehave trabalha com arquivos unicamente neste formato. Essas ferramentas podem ser tanto utilizadas
1
Framework for Integrated Testing.
157
1 Cenrio: ...
2 Dado ...
3 Quando ...
4 Ento...
5
6 # Cenrios mais complexos podem possuir passos extras concatenados com "E":
7 Cenrio: ...
8 Dado ...
9 E ...
10 Quando ...
11 Ento ...
12 E ...
Figura 9.6: Esqueleto de histria sugerido por BDD.
1 Cenrio: Calcular total de impostos sobre o faturamento anual
2 Dado que em 2009 a empresa faturou R$ 200.000,00 bruto
3 E o total de impostos chega a 40% do total bruto
4 Quando calculo o total de impostos da empresa em 2009
5 Ento a empresa gastou R$ 80.000,00 em impostos
6 E obteve rendimento lquido de apenas R$ 120.000,00
Figura 9.7: Exemplo de histria no formato sugerido por BDD.
para testes de unidade quanto para testes integrados (como os de aceitao). Como mostra a Figura 9.8,
pode-se escrever os testes com BDD seguindo o ciclo de ATDD, descrito na Seo 3.2.
Figura 9.8: Ciclo de ATDD.
Hoje, existe uma grande gama de ferramentas de BDD para diversas linguagens de programao,
todas seguindo a mesma abordagem. Dentre elas esto RSpec, Cucumber, JDave e BDoc.
158
9.5 Concluses
O nvel de testabilidade do sistema implica diretamente na qualidade dos testes automatizados. Mesmo
que o desenvolvedor conhea padres e boas prticas de automao, nem sempre ele conseguir colocar
emprtica seu conhecimento durante a implementao dos testes porque eles precisaro necessariamente
contornar as diculdades causadas pelo alto acoplamento dos mdulos e objetos da aplicao.
Quando os sistemas so implementados sem se preocupar com os possveis cenrios de testes, os
sistemas tendem a possuir uma baixa testabilidade, mesmo que eles tenham arquiteturas elegantes e
estejam bem implementados. Apesar de os sistemas com cdigo-fonte de qualidade serem mais fceis
de se testar, os testes automatizados precisam ter total controle do sistema em teste para que os casos de
testes sejam implementados com facilidade.
Por isso, altamente recomendvel utilizar as abordagens em que os testes so implementados antes
da implementao (TFD, TDD e BDD), pois elas foram os desenvolvedores a criarem cdigo mais
coeso, pouco acoplado e com alta testabilidade.
Entretanto, programas que possuem uma boa modelagem orientados a objetos tende a ter alta testa-
bilidade. Se cada classe tiver apenas uma responsabilidade e for possvel injetar suas dependncias,
ento a preparao dos testes tornam-se mais simples com o auxlio de Objetos Dubls (vide Seo 6.2)
e as vericaes necessrias cam fceis de serem elaboradas.
Para esses casos, o uso de TAD tambm se torna uma alternativa promissora. TAD s deve ser
evitada quando o custo da criao e da manuteno dos testes se torna mais alto do que a execuo
montona e repetida dos testes manuais.
159
160
Parte III
Gerenciamento de Testes Automatizados
161
Captulo 10
Mtricas
Mtrica uma relao de uma ou mais medidas para denir se um sistema, componente ou processo
possui um certo atributo. Uma medida uma avaliao em relao a um padro denido. Por exemplo,
para saber se um sistema grande (atributo) podemos utilizar a medida de linhas de cdigo, que tambm
podemos chamar de mtrica de linhas de cdigo [128, 127], j que toda medida representa um atributo,
e uma mtrica pode ser composta de uma nica medida.
Mtricas so fundamentais para reviso, planejamento e gerenciamento de projetos. Este captulo
discute seus benefcios e apresenta algumas mtricas que so pertinentes para acompanhar os testes
automatizados e a qualidade do sistema. Dentre elas esto Cobertura e Testabilidade, que podem ser
teis para muitos projetos, e outras que so mais bencas para projetos com certas caractersticas, tais
como projetos legados ou os que possuem equipes inexperientes em testes.
10.1 Mtricas para Testes Automatizados
Toda metodologia de desenvolvimento de software busca respeitar acordos e contratos denidos com
o cliente, sejam acordos de prazos, qualidade, escopo ou custo. O sucesso de um projeto depende de
organizao, planejamento, gerenciamento e aprendizado.
Organizao o princpio bsico para que todas as informaes estejam claras para facilitar o en-
tendimento do contexto e da situao corrente do projeto. reas de trabalho informativas [130] contendo
poucas informaes, mas que so muito relevantes, so mais valiosas do que documentos completos e
detalhados que acabam sendo deixados em segundo plano devido ao grande tempo que necessrio para
o estudo.
Planejamento uma proposta de organizao de tarefas para serem executadas [41]. A proposta
feita contendo previses do futuro, criadas, geralmente, com base na experincia obtida de trabalhos an-
teriores. Como nenhum planejamento e ningum consegue prever o futuro com exatido, indiscutvel
que todos eles esto sujeitos a enganos. O que pode ser feito tentar minimizar a quantidade de enganos.
Para isso, os mtodos geis recomendam trabalhar em iteraes curtas de desenvolvimento, pois mais
fcil prever o futuro prximo (uma ou duas semanas) do que prever o que ir acontecer a longo prazo
(meses ou anos).
J o gerenciamento feito pela observao do andamento do projeto e pela coordenao da equipe
para concentrar o trabalho nas tarefas mais prioritrias no momento da iterao. Para observar, com
xito, o andamento dos projetos, so necessrias informaes rpidas, claras, atualizadas e pertinentes
[41].
O aprendizado fundamental para o sucesso de trabalhos futuros devido experincia adquirida que
ajuda a evitar que erros sejam repetidos. Mtodos geis incentivam a criao de reunies de retrospec-
tivas depois do trmino de uma iterao de desenvolvimento para revisar e relembrar o andamento do
projeto, principalmente referente s diculdades encontradas [49]. Nessa reunio, devem ser reforados
163
os pontos que foram positivos e que precisam ser valorizados nas iteraes seguintes, assim como
previsto que sejam encontradas solues para aspectos que no foram satisfatrios e que precisam ser
melhorados [130].
As mtricas so fundamentais para qualquer metodologia alcanar o sucesso em um projeto, pois
elas so um artifcio bsico para reviso, planejamento e gerenciamento. Como diz Morris A. Cohen:
No podemos gerenciar o que no podemos medir [47]. Elas exercem um papel fundamental no
gerenciamento de tarefas e projetos, mas precisam ser bem organizadas e utilizadas nos momentos cor-
retos. Existem estudos e abordagens sistematizadas para coleta de mtricas e avaliao da qualidade de
sistemas [48].
As mtricas podem ser utilizadas apropriadamente quando houver necessidade de conhecer certos
aspectos de um trabalho para estabelecer objetivos, como sugere o processo PDCA
1
[134]. Em alguns
momentos, os problemas no esto claros ou visveis para a equipe, por isso a coleta de mtricas ajuda
a identicar pontos que devem ser melhorados. As curtas iteraes das metodologias geis seguem esta
estrutura.
Quando os objetivos j esto denidos, pode-se utilizar a abordagem GQM
2
[12], que sugere a
coleta unicamente das mtricas pertinentes para alcanar o objetivo denido. Isso evita um esforo
desnecessrio de coletar e interpretar outras mtricas menos importantes para o contexto. Portanto,
GQM til para ajudar a acompanhar as solues propostas dos problemas citados nas retrospectivas.
Uma das tarefas mais importantes do processo de desenvolvimento gerenciar a qualidade do
cdigo-fonte e do produto produzido, que uma tarefa complexa devido ao carter altamente subje-
tivo e pessoal da caracterstica. Para acompanhar a evoluo da qualidade, fundamental o emprego de
uma ou mais mtricas que consigam representar a qualidade para o contexto do projeto.
No caso das metodologias que integram testes automatizados como controle de qualidade, em es-
pecial a Programao eXtrema que recomenda TDD como uma de suas prticas primrias, comum a
coleta de mtricas de testes automatizados para o acompanhamento dos testes, da qualidade do cdigo-
fonte e do produto nal [11, 101]. Como os testes inuenciam diretamente a qualidade e o progresso
de um projeto, um bom conjunto de mtricas dos testes pode elucidar o estado e ajudar a corrigir o
andamento do projeto, estabelecer prioridades e estipular novas metas.
As sees seguintes apresentam algumas mtricas de testes automatizados e de qualidade que so
teis tanto para equipes que esto comeando a aprender e aplicar testes automatizados como para
aquelas j experientes que possuem grandes baterias de testes automatizados. Tambm so valiosas
tanto para projetos legados quanto para os recm-criados.
10.2 Cobertura
A mtrica de cobertura de cdigo indica quais pontos do sistema foram exercitados (executados ou
cobertos) pelos casos de teste [144]. Os pontos do sistema podem ser classes, mtodos, blocos e linhas,
sendo que a granularidade mais na de cobertura que geralmente as ferramentas obtm so as linhas de
cdigo executadas. A Figura 10.3 apresenta o relatrio de cobertura dos testes gerados com a ferramenta
Eclemma para Java aps a execuo dos testes da Figura 10.2 sob o cdigo da Figura 10.1 que possui
simplesmente um mtodo que calcula o mximo divisor comum (m.d.c.) de dois nmeros naturais.
As linhas em tons mais claros (verde: 7, 8, 10, 11, 12 e 17) foram executadas pelos testes, ao
contrrio das linhas com tom mais escuro (vermelho: 13, 14 e 15). As linhas que no foram executadas
indicam que faltam testes para o cenrio onde o resto da diviso entre dividendo e divisor diferente de
zero. O tom intermedirio (amarelo: 9) signica que a linha foi parcialmente executada, isto , algumas
das operaes foram realizadas e outras no. Neste caso, a cobertura aponta que faltam cenrios de teste
1
Plan -> Do -> Check -> Act ou Planeje -> Faa -> Estude -> Aja.
2
GQM: Goal -> Question -> Metrics ou Objetivo -> Questo -> Mtricas.
164
1 public class MathHelper {
2
3 // Algoritmo de Euclides: mdc(a, b) = mdc(b, resto(a, b)) => (a = q * b + r)
4 public static long mdc(long a, long b) {
5 long dividendo = Math.max(a, b);
6 long divisor = Math.min(a, b);
7 if(dividendo < 0 || divisor < 0) throw new IllegalArgumentException("ops");
8 if(dividendo == 0 || divisor == 0) return 0;
9 long resto = dividendo % divisor;
10 while(resto != 0) {
11 dividendo = divisor;
12 divisor = resto;
13 resto = dividendo % divisor;
14 }
15 return divisor;
16 }
17
18 }
Figura 10.1: Exemplo de cdigo para vericao da cobertura.
1 // referncias do JUnit
2 import static org.junit.Assert.assertEquals;
3 import org.junit.Test;
4
5 public class MathHelperTests {
6
7 @Test public void mdcComZeroEhZero() {
8 assertEquals(0, MathHelper.mdc(0, 1));
9 assertEquals(0, MathHelper.mdc(1, 0));
10 assertEquals(0, MathHelper.mdc(0, 0));
11 }
12
13 @Test public void mdcComUmEhUm() {
14 assertEquals(1, MathHelper.mdc(1, 1));
15 assertEquals(1, MathHelper.mdc(1, 7));
16 assertEquals(1, MathHelper.mdc(1, 20));
17 assertEquals(1, MathHelper.mdc(1, 25));
18 assertEquals(1, MathHelper.mdc(1, 100));
19 }
20
21 }
Figura 10.2: Exemplo de testes para vericao da cobertura.
165
Figura 10.3: Visualizao da cobertura do cdigo-fonte com a ferramenta Eclemma.
com dados de entrada invlidos, em que pelo menos um dos dados de entrada um nmero negativo.
Sendo assim, a condio if foi executada, enquanto o lanamento da exceo de erro no foi processada.
Note que um trecho exercitado no signica que ele est livre de defeitos ou que foi testado com-
pletamente [108]. Por exemplo, se a linha 11 possusse o cdigo incorreto long resto = 1, todos os
testes da Figura 10.2 continuariam sendo executados sem falhas. A cobertura nem sequer mostra se um
trecho est realmente sendo testado. Por exemplo, se o cdigo dos testes zesse apenas as chamadas do
mtodo mdc sem fazer as vericaes, isto , MathHelper.mdc(a, b), em vez de assertEquals(x,
MathHelper.mdc(a, b)), o resultado da cobertura continuaria sendo o mesmo.
A nica certeza que a mtrica de cobertura fornece que os trechos no exercitados no foram
testados. A falta de testes pode indicar trechos do sistema que so desnecessrios ou, ainda, pontos
especcos que podem conter falhas e que precisam ser vericados. Para exemplicar, qualquer erro
que no seja de compilao na linha 15 passa despercebido pela fraca bateria de testes apresentada.
Poderia ter desde erros de distrao, como, por exemplo, resto = dividendo / divisor, at um
erro grosseiro, como resto = 0.
Portanto, esta mtrica precisa ser interpretada com ateno e no deve ser utilizada como nico
indicador de qualidade do sistema, necessrio outras mtricas que complementam o conhecimento
adquirido da cobertura de testes.
Esta mtrica muito til para diversos contextos. Quando o sistema j possui uma bateria de testes
consideravelmente grande, ela fundamental para indicar novos pontos que precisam ser vericados.
Quando a bateria de testes pequena, no til para dar viso do sistema como um todo, mas pode ser
utilizada para encontrar novos pontos de vericao dentro de um pequeno mdulo do sistema.
Para os sistemas que no possuem testes automatizados, esta mtrica desnecessria porque o re-
sultado sempre ser 100% de trechos no cobertos. at possvel utilizar as ferramentas de coleta de
cobertura durante a realizao de testes manuais, mas os resultados obtidos s so teis para o instante
da execuo, isto , eles no so teis para serem acompanhados com o tempo porque as execues no
so elmente idnticas, o que torna invivel a interpretao coerente dos resultados.
Quando o sistema implementado com TDD ou TFD, a cobertura de cdigo tende a ser alta, j
que cada trecho de cdigo s deve ser adicionado aps um teste que o cubra [153]. Ento, ela pode
ser utilizada para auxiliar o desenvolvimento com testes a priori para indicar falhas no processo e para
vericar se um sistema possui indcios de ter sido escrito com TDD ou TFD.
166
10.3 Testabilidade
Testabilidade de software mede a facilidade da escrita de testes de qualidade dentro de um contexto
[142]. Testar um sistema ou uma funcionalidade nem sempre trivial, seja por meio de testes manuais
ou automatizados. Primeiramente, tem de ser possvel controlar o software, isto , execut-lo de acordo
com as necessidades do teste. Posteriormente, necessrio observar os efeitos colaterais causados por
uma determinada execuo que sero comparados com valores esperados.
Para que seja possvel controlar e observar um sistema apropriadamente necessrio que ele esteja
bem modularizado e isolado, pois, caso contrrio, os testes podem ser difceis ou at impossveis de
serem realizados. Testes complicados de serem criados ou mantidos tendem a ser pouco legveis e muito
suscetveis a erros. Tudo isso aumenta o custo-benefcio da automao de testes.
Testabilidade no uma mtrica intrnseca ao sistema, como total de linhas de cdigo, nmero de
classes etc. necessrio medir diversos fatores para ento calcular o grau de testabilidade de acordo com
alguma frmula matemtica baseada em determinaes subjetivas. Por isso, importante ter cuidado
ao interpretar esta mtrica, j que ela pode ser mais ou menos apropriada para um contexto especco.
Tambm preciso cautela ao comparar o grau de testabilidade entre sistemas que possuem contextos
diferentes.
A Figura 10.4 mostra um exemplo do grau de testabilidade de um mdulo do software Eclipse me-
dido com a ferramenta Testability-Explorer [69]. A ferramenta analisa o cdigo-fonte de cada classe
Java em busca de variveis de classe mutveis, incoerncias segundo a Lei de Demeter
3
[88] e classes
que no permitem injetar dependncias. As informaes coletadas so convertidas em um grau de testa-
bilidade que representa custo para se testar uma classe do sistema, sendo assim, quanto maior o custo,
pior.
Figura 10.4: Grau de testabilidade do mdulo Workbench do software Eclipse, medido com a ferramenta
Testability-Explorer.
As classes que possuem boa ou excelente testabilidade so mais fceis de testar automaticamente,
enquanto as que possuem baixa testabilidade (Needs Work) requerem mais ateno. Pode ser bem com-
plexo criar testes para as classes com baixa testabilidade, pois, geralmente, necessrio uma grande
quantidade de cdigo para preparar o ambiente de testes apropriadamente. Em algumas situaes, pode
at ser fcil de implementar os testes, mas provvel que eles contenham antipadres, tais como testes
lentos, intermitentes e frgeis.
3
A Lei de Demeter prope um estilo de design em que cada unidade deve ter conhecimentos limitados sobre outras
unidades. Uma unidade s deve trocar informaes com suas dependncias imediatas. Este princpio particularmente til
para criar sistemas orientados a objetos com baixo acoplamento.
167
10.3.1 Padres e Antipadres Inuenciam a Testabilidade
A testabilidade de um sistema est diretamente relacionada com o bom design [117, 97, 27, 78]. O grau
de testabilidade pode ser avaliado a partir de boas prticas de modularizao e de programao orientada
a objetos, que ajudam a tornar os sistemas mais simples e coesos, e, consequentemente, os testes cam
mais claros e fceis de implementar.
Um dos fatores mais comuns que afetam a testabilidade do sistema est relacionado com a im-
plementao do construtor de objetos. Objetos que so difceis de criar e de congurar dicultam a
criao de testes isolados. Existem inmeros antipadres no nomeados que prejudicam a testabilidade
de um sistema. A Figura 10.5 apresenta exemplo de construtores escritos em Java com alguns destes
antipadres. Para facilitar, os comentrios de cada exemplo esto nas prprias guras.
J a Figura 10.6 mostra objetos que so fceis de serem criados e isolados por meio do padro
Injeo de Dependncia [113]. Quando a criao dos objetos mais complexa, recomendado que o
processo de criao seja isolado em objetos prprios, atravs do uso de padres de projeto de criao,
tais como Builder, Factory e Prototype [61].
A denio das responsabilidades dos objetos e da forma como eles iro interagir determinam o
design de um sistema orientado a objetos. Isso uma das tarefas mais difceis e delicadas da orientao
a objetos, pois qualquer falha pode comprometer a manutenibilidade e a testabilidade. A Figura 10.7
apresenta um mtodo pouco coeso que viola a Lei de Demeter [88], portanto torna os testes difceis
de serem isolados. A Figura 10.8 apresenta como seria o mtodo refatorado para aumentar a coeso e
testabilidade do sistema.
Uma das boas prticas de orientao a objetos denir uma responsabilidade por classe. Esse padro
torna as classes fceis de serem implementadas, entendidas e testadas. Quando uma classe possui muitas
responsabilidades, o conjunto de casos de testes para test-la tende a aumentar consideravelmente, j que
as combinaes de dados de entrada podem aumentar fatorialmente. Alm disso, os testes tendem a ter
a legibilidade prejudicada. Quanto mais complexa for uma classe, maior sero os mtodos de set up e
mais vericaes so necessrias por casos de teste.
Existem vrios indcios que ajudam a identicar se uma classe est realizando mais tarefas do que
deveria. O primeiro deles se d pela facilidade de entendimento da classe. Outros indcios so os
atributos da classe raramente usados, que podem indicar que ela deve ser repartida entre outras menores.
Mais um indcio comum o uso de nomes de classes e variveis muito genricas, tais como manager,
context, environment, principal, container, runner etc. Devido ao carter extremamente abstrato dessas
classes, coerente que muitas responsabilidades sejam associadas a elas.
Ainda, a modelagem incorreta de heranas entre classes, por exemplo, que ferem o Princpio de Sub-
stituio de Liskov [89], podem tornar os testes difceis de serem modularizados e, consequentemente,
propiciar a replicao de cdigo-fonte (vide Seo 6.3.3).
Outro aspecto que prejudica a automao de testes so os estados globais mutveis, tais como var-
iveis globais e classes com o padro Singleton [61]. Estados globais so acessveis a vrios casos de
testes, portanto, os testes no cam completamente isolados. Isso signica que se um caso de teste
alterar um valor global, outros testes podero falhar.
Uma soluo que torna os testes mais complexos e lentos, mas que pode resolver o problema de
maneira padronizada, utilizar os mtodos de set up para denir o estado inicial das variveis globais
antes da execuo dos testes. Contudo, esta soluo requer que os testes sejam executados individual-
mente e sequencialmente, o que inviabiliza o uso de ferramentas de otimizao de testes que executam
paralelamente os casos de testes.
Esses padres e antipadres citados compem apenas uma pequena parcela das inmeras formas de
implementao que inuenciam a testabilidade do sistema. Ainda, existem diversos fatores prprios de
cada linguagem de programao que tambm podem facilitar ou dicultar os testes de software. O que
vlido para todas elas que denir e escrever os casos de testes antes da prpria implementao propicia
a criao de cdigo altamente testvel, j que o cdigo do sistema se adapta aos testes, e no o contrrio.
168
1 public class ObjetoComContrutorDeBaixaTestabilidade1 {
2 // No da para isolar (classe no tem mtodo setter)
3 private Dependencia dependencia = new Dependencia();
4 public ObjetoComContrutorDeBaixaTestabilidade1() {
5 }
6 }
7
8 public class ObjetoComContrutorDeBaixaTestabilidade2 {
9 private Dependencia dependencia;
10 public ObjetoComContrutorDeBaixaTestabilidade2() {
11 // No da para isolar (classe no tem mtodo setter)
12 dependencia = new Dependencia();
13 }
14 }
15
16 public class ObjetoComContrutorDeBaixaTestabilidade3 {
17 private Dependencia dependencia;
18 public ObjetoComContrutorDeBaixaTestabilidade3() {
19 // Arcabouos que usam reflexo para criao de objetos precisam do construtor
padro.
20 // Mas necessrio cuidados porque o objeto no est inicializado
21 // apropriadamente enquanto no forem injetadas as dependncias.
22 }
23 public void setDependencia(Dependencia dependencia) {
24 this.dependencia = dependencia;
25 }
26 }
27
28 public class ObjetoComContrutorDeBaixaTestabilidade4 {
29 public ObjetoComContrutorDeBaixaTestabilidade4() {
30 // Muita lgica no contrutor pode prejudicar a testabilidade.
31 // necessrio um trabalho adicional para criar o objeto apropriadamente.
32 // Use algum padro de projeto de criao de objetos.
33 if (x == 3) { ... }
34 for(int i = 0; i < n; i++) { ... }
35 while(true) { ... }
36 }
37 }
38
39 public class ObjetoComContrutorDeBaixaTestabilidade5 {
40 public ObjetoComContrutorDeBaixaTestabilidade5(Dependencia dependencia) {
41 // Testes no ficam isolados da classe DependenciaGlobal
42 DependenciaGlobal.metodoGlobal(dependencia);
43 }
44 }
Figura 10.5: Exemplo de implementao de construtores que tornam os objetos difceis de serem testa-
dos.
169
1 public class ObjetoComContrutorDeAltaTestabilidade1 {
2 private List list;
3 public ObjetoComContrutorDeAltaTestabilidade1() {
4 // Detalhes internos do objeto podem ser instanciados no contrutor
5 // lista geralmente uma exceo
6 list = new ArrayList();
7 }
8 }
9
10 public class ObjetoComContrutorDeAltaTestabilidade2 {
11 private Dependencia dependencia;
12 public ObjetoComContrutorDeAltaTestabilidade2(Dependencia dependencia) {
13 this.dependencia = dependencia; // Possvel injetar dependncia
14 }
15 }
Figura 10.6: Exemplo de implementao de construtores que tornam os objetos fceis de serem testados.
1 public class A {
2
3 public metodo(B b) {
4 // Violao da Lei de Demeter:
5 // Objeto A conhece toda hierarquia de classes do objeto B
6 // Difcil de isolar: A pergunta para B por informaes
7 var estado = b.getObjetoC().getObjetoD().getObjetoE().getEstado();
8 // ...
9 }
10 }
Figura 10.7: Exemplo de implementao de mtodos que so difceis de serem testados.
1 public class A {
2
3 // No pergunte, diga!
4 public metodo(E e) { // Possvel isolar dependncias
5 var estado = e.getEstado(); // A s conhece E
6 // Objetos B, C e D so dispensveis
7 // ...
8 }
9 }
Figura 10.8: Exemplo de implementao de mtodos que so fceis de serem testados.
170
Por isso recomendado o uso de TFD, TDD e BDD para criao de sistemas com alta testabilidade.
10.3.2 Quando Utilizar
Testabilidade pode ser til para analisar riscos e estabelecer quais pontos so mais crticos para se testar,
principalmente para equipes que esto comeando a aplicar testes automatizados em sistemas legados.
Contudo, ela tambm importante para acompanhar a qualidade dos testes automatizados, pois baixa
testabilidade (ou alto custo para se testar) implica testes com muitos antipadres.
Essa mtrica tambm auxilia na identicao dos mdulos do sistema em teste que precisam ser
refatorados, isto , mdulos que no possuem um bom design. Dessa forma, a anlise da testabilidade
do sistema, antes de adicionar novas funcionalidades, importante, pois ajuda a prevenir que uma nova
poro de cdigo seja inserida sobre uma arquitetura confusa, que pode tornar a implementao mais
complicada, alm de piorar o design do sistema.
TDD e TFD no s proporcionam alta cobertura dos testes, como tambm favorecem para que o
sistema seja testvel, pois a criao dos testes a priori implica que o cdigo do sistema se adapte aos
testes, e no o contrrio [16]. Portanto, testabilidade tambm til para acompanhar e vericar se o
desenvolvimento com TDD ou TFD est sendo feito apropriadamente.
10.4 Outras mtricas
As mtricas de cobertura e testabilidade podem ser teis para todos os contextos de desenvolvimento
de sistemas de software, mesmo quando estamos seguindo a abordagem PDCA ou GQM. No entanto,
existem muitas outras mtricas que so teis para contextos especcos e que podem ajudar a encontrar
defeitos, melhorar o cdigo do sistema e dos testes, alm serem mtricas valiosas para acompanhar a au-
tomao de testes, tanto para novos projetos quanto para projetos legados [144]. A seguir apresentada
uma lista com algumas destas mtricas:
1. Fator de Teste: o total de linhas dos testes pelo total de linhas do sistema. til para comparar
mdulos de um mesmo projeto e ajudar a determinar quais so os mdulos mais testados e quais
precisam de maior ateno. Esta mtrica no recomendada para o acompanhamento da evoluo
dos testes de um projeto, pois a lgica e o tamanho do cdigo dos testes no possuem qualquer
relao com a lgica do cdigo do sistema.
2. Nmero de testes por linha de cdigo do sistema: Esta mtrica pode ser til para acompanhar
a evoluo dos testes automatizados de um projeto, desde que o sistema cresa sem alteraes
drsticas quanto a sua complexidade.
3. Nmero de linhas de testes: Anlogo ao nmero de linhas de um sistema, esta mtrica d uma
pequena dimenso do cdigo dos testes e pode ser utilizada para o planejamento de tarefas de
estudo e manuteno do cdigo. A avaliao dessa mtrica em uma amostra do cdigo, como
classes ou mtodos, pode identicar testes que precisam de refatorao.
4. Nmero de testes: Mtrica para acompanhar a evoluo do desenvolvimento de testes. til,
principalmente, em projetos que esto comeando a ter testes automatizados.
5. Nmero de asseres: uma mtrica que ajuda a detectar se os testes esto realmente testando o
sistema, isto , se esto fazendo vericaes.
6. Nmero de testes pendentes: comum escrever testes marcados como pendentes (se o ar-
cabouo de teste fornecer essa funcionalidade) que sero implementados no momento apropriado.
Por exemplo, se o acompanhamento da quantidade dos testes ao longo de uma iterao indicar
171
que o nmero de pendncias no est diminuindo, pode ser um sinal de que os prazos esto curtos
e que os testes esto sendo sacricados.
7. Nmero de testes falhando: Esta mtrica til para detectar a fragilidade dos testes, alm de
servir de acompanhamento para o conserto dos mesmos.
8. Nmero de asseres por mtodo: Indica mtodos que talvez precisam ser refatorados caso o
nmero seja alto, pois podem ser responsveis por testar mais de uma ideia.
9. Replicao de cdigo dos testes: Identica trechos do cdigo dos testes que precisam ser refa-
torados, assim como pode indicar que o cdigo do sistema tambm possui replicao de cdigo.
10. Quantidade de defeitos encontrados: Pode indicar a qualidade do sistema e tambm a falta de
testes automatizados.
11. Tempo de execuo da bateria dos testes: Mtrica para determinar se o programa ou os casos
de testes possuem gargalos de desempenho que precisam ser otimizados ou refatorados.
10.5 Concluses
Os valores obtidos das mtricas esto diretamente relacionados ao contexto do projeto e do sistema,
pois elas dependem de muitos fatores como a linguagem de programao e a complexidade do produto.
Dessa forma, invivel utiliz-las isoladamente para denir o estado de um projeto ou mesmo para
comparar projetos distintos.
Para estes ns, sempre necessrio uma anlise que far a interpretao das informaes, prin-
cipalmente porque os resultados podem apresentar valores que no so esperados para a realidade do
projeto, isto porque as mtricas so, muitas vezes, facilmente burladas, propositalmente ou por falta de
experincia com o desenvolvimento dos testes, como demonstram os exemplos a seguir:
Exemplo 1: Um nmero alto de testes e de fator de teste pode aparentar que um sistema possui
poucos defeitos, j que passa a impresso de que foram vericados diferentes cenrios de testes,
mas tambm pode indicar que o cdigo do sistema possui uma grande replicao de cdigo, e,
portanto, os testes tambm so replicados.
Exemplo 2: Uma alta cobertura do cdigo provavelmente indica que o sistema est muito bem
testado, j que no h trechos de cdigo esquecidos, mas tambm pode mostrar que o sistema
foi muito mal testado, caso os testes no possuam vericaes, apenas chamadas dos mtodos do
sistema.
Estas mtricas relacionadas a testes automatizados ajudam a estabelecer objetivos de melhoria da
qualidade e da produtividade da automao dos testes, dentre outros objetivos que so comuns a diversos
projetos. A Tabela 10.1 aponta alguns destes objetivos e as mtricas mais recomendadas para ajudar no
gerenciamento.
importante lembrar que outras mtricas podem ser geradas a partir da combinao de uma ou mais
destas mtricas, pois cada uma delas utiliza uma medida diferente. A busca de novas mtricas sempre
til, pois quanto mais evidncias, mais fcil a anlise dos dados e tambm a denio de estratgias.
No entanto, a coleta de mtricas no deve prejudicar a agilidade do processo, assim como o excesso de
informaes no deve tirar o foco do que realmente necessrio melhorar.
172
X
X
X
X
X
X
X
X
X
X
X
Objetivo
Mtrica
1 2 3 4 5 6 7 8 9 10 11 12 13
Encontrar defeitos o o o
Melhorar o cdigo do sistema o o o o
Melhorar o cdigo dos testes o o o o o o o o o o
Introduzir testes automatizados em novos projetos o
Introduzir testes automatizados em sistemas legados o o
Acompanhar a automao dos testes o o o o o o o
Tabela 10.1: Objetivo vs. Mtrica (Goal vs. Metric). Legenda: (1) Testabilidade; (2) Cobertura; (3)
Fator de Teste; (4) Nmero de testes por linha de cdigo do sistema; (5) Nmero de linhas de testes;
(6) Nmero de testes; (7) Nmero de asseres; (8) Nmero de testes pendentes; (9) Nmero de testes
falhando; (10) Nmero de asseres por mtodo; (11) Replicao de cdigo dos testes; (12) Quantidade
de defeitos encontrados; e (13) Tempo de execuo da bateria dos testes.
173
174
Captulo 11
Consideraes Finais
Desenvolvimento de software uma tarefa complexa que exige conhecimento tcnico, organizao,
ateno, criatividade e tambm muita comunicao. previsvel que durante o desenvolvimento alguns
destes requisitos falhe, mas imprevisvel o momento que iro falhar. Por isso, imprescindvel que
exista uma maneira fcil e gil de executar todos os testes a qualquer momento, e isso vivel com o
auxlio de testes automatizados.
A automao dos testes traz segurana para fazer alteraes no cdigo, seja por manuteno, refa-
torao ou at mesmo para adio de novas funcionalidades. Alm disso, um teste programtico permite
criar testes mais elaborados e complexos, que podero ser repetidos identicamente inmeras vezes.
Ainda, a automao aumenta a quantidade de tempo gasto com a vericao do sistema e diminui
o tempo gasto com a identicao e correo de erros (tempo perdido). Todos os testes podem ser
executados a qualquer momento e, por consequncia, os erros tendem a ser encontrados mais cedo.
possvel at automatizar a execuo dos testes, com ferramentas que cam constantemente vericando
se um cdigo foi alterado ou com aquelas que obtm o cdigo de um repositrio automaticamente e
rodam a bateria de testes por meio de um script.
No entanto, a automao de testes um processo complexo, sujeito a erros e que precisa de
manuteno. Por isso, fundamental que as baterias de testes sejam de alta qualidade, ou seja, organi-
zadas, legveis, rpidas etc. Para isso, essencial o conhecimento de boas prticas, padres, antipadres,
e indcios de problemas.
Alm disso, os testes automatizados possuem inuncia na forma que um software modelado. Os
sistemas que so implementados sem testes automatizados tendem a possuir uma baixa testabilidade,
mesmo que o cdigo seja de alta qualidade. Por isso, aconselhvel utilizar abordagens que foram os
desenvolvedores a criarem cdigo com alta testabilidade.
Apesar dos testes automatizados ajudarem na criao de uma modelagem coesa e pouco acoplada
do sistema, o objetivo principal desta prtica vericar a qualidade de diferentes caractersticas que
so importantes para o projeto. Portanto, fundamental a utilizao das solues propostas pela rea
de Teste de Software, que so completamente compatveis com as abordagens sugeridas pela rea de
Metodologias geis. Por exemplo, possvel integrar boas prticas de vericao de cdigo emconjunto
com desenvolvimento dirigido por testes, alm de que o progresso da automao de testes de um projeto
pode ser acompanhado por meio de mtricas de software.
11.1 Pontos para Pesquisa
Esta rea de pesquisa est em crescimento, existem muitas pesquisas a serem feitas, muitas ferramentas
ainda no produzidas e muitas tcnicas ainda no evidenciadas. Testes automatizados j tm trazido
benefcios signicativos para muitos projetos, mas pesquisas que comparam as tcnicas de escrita ou
que comprovam a eccia dessa prtica ainda podem ser teis. Todavia, a tendncia facilitar a escrita
175
dos testes para baixar o custo de implementao e manuteno. Esta tendncia comprovada por ferra-
mentas com APIs mais fceis de usar, que geram cdigo de teste, e outras que at geram casos de testes
pertinentes.
Abaixo, segue uma lista de propostas de ferramentas para serem implementadas e de estudos empri-
cos que so difceis de serem realizados, j que complicado isolar outras variveis do desenvolvimento
de software que atrapalham a interpretao dos resultados.
Sugestes de pesquisas: Pesquisa em que quatro grupos pequenos com o mesmo nvel de ex-
perincia de programao iro implementar um mesmo sistema. Uma das equipes utilizar
TDD, outra TFD, outra TAD e outra ir fazer apenas testes manuais. O tempo de desenvolvi-
mento e a qualidade do cdigo e do produto gerado sero analisados para buscar evidncias
de vantagens e de desvantagens de cada prtica.
Pesquisa em que dois grupos com o mesmo nvel de experincia de programao e de TDD
iro implementar um mesmo sistema. Uma das equipes utilizar TDD e com o uso exaustivo
de Objetos Dubls, enquanto o segundo grupo ir fazer testes contendo certa integrao dos
mdulos e s utilizar Objetos Dubls para casos crticos. O tempo de desenvolvimento e a
qualidade do cdigo, dos testes e do produto gerado sero analisados para buscar evidncias
de vantagens e de desvantagens de cada prtica.
Pesquisa em que dois grupos com o mesmo nvel de experincia de programao e de TDD
iro implementar um mesmo sistema que tenha um linguajar no conhecido pelas equipes.
Uma das equipes utilizar TDD enquanto a outra, o BDD. O tempo de desenvolvimento e a
qualidade do cdigo, dos testes e do produto gerado sero analisados para buscar evidncias
de vantagens e de desvantagens de cada prtica.
Sugestes de Estudos: Continuar a documentar padres, antipadres e indcios de problemas.
Encontrar padres ao se testar os Padres de Projetos e os Arquiteturais.
Encontrar padres de testes para Programao Funcional.
Encontrar padres de testes de Web Services.
Sugestes de Ferramentas: Criar arcabouos para testes com aspectos. A partir de pointcuts,
prottipos de classes podem ser gerados automaticamente para a realizao dos testes.
Aperfeioar as ferramentas de relatrios de testes para torn-los mais legveis e terem maior
utilidade para documentao. Por exemplo, as ferramentas podem analisar os nomes dos
mtodos que utilizam a conveno camel case ou o caractere underline para formatar de
uma maneira mais legvel, com espao. J existem ferramentas com esse propsito, mas
ainda falta integrao com as ferramentas mais populares.
Complemento da ferramenta Python-QAssertions e converso da ferramenta para outras lin-
guagens. Outras asseres podem ser adicionadas, como uma que produza casos teis de
testes para expresses regulares, ou, ento, asseres que gerem testes teis para padres de
projetos e operaes comuns em banco de dados (CRUD).
Criar ferramentas que facilitem e incentivem o uso de padres identicados.
Criar frameworks de testes automatizados prprios para testarem sistemas paralelos e dis-
tribudos.
Sugestes de Ferramentas para Testes com Persistncia de Dados: Adaptar as ferramentas de
testes com persistncia de dados de arcabouos Web para que os testes sejam executados em
diversas instncias de banco de dados em memria, assim, os testes podero ser executados
em paralelo.
176
Sugestes de Ferramentas para Testes de Interface de Usurio: Ferramenta que gera uma Ca-
mada de Abstrao das Funcionalidades da interface de usurio para facilitar a escrita dos
testes de interface.
Aperfeioamento das ferramentas de gravao de testes de interface, de tal modo que facilite
a criao de mdulos, evitando a repetio de cdigo. Tambm pode-se evidenciar os pontos
que precisam ser refatorados.
Estudos e ferramentas para testes de usabilidade, baseadas em heursticas recomendadas pela
rea de Interao Homem-Computador. Para testes de interface Web, podem ser analisados
documentos CSS para identicar o contraste das cores dos componentes, assim como o
tamanho das fontes utilizadas.
Ferramentas para facilitar testes de leiaute. Elas podem detectar componentes que no esto
visveis assim como irregularidades do leiaute. Em aplicaes Web, podem ser analisados
os componentes que possuam a propriedade de invisibilidade (display), assim como as pro-
priedades de localizao tridimensional (z-index).
Sugestes de Ferramentas de Mtricas de Testes: Criar mtricas de padres de qualidade que
se baseiam padres do qualidade descritos na dissertao.
Criar ferramentas que detectem antipadres nos testes, assim como o Testability-Explorer
encontra antipadres de testabilidade no cdigo do sistema.
Ferramentas para coleta e exibio de mtricas de testes automatizados. Converter a ferra-
menta Testability-explorer (para Java) para outras linguagens.
Criar um rob que explore repositrios de cdigo e ferramentas de administrao de defeitos
para se obter mtricas que relacionam quantidade de defeitos com a quantidade de testes.
177
178
Apndices
179
Apndice A
Teste de Carga com JMeter
JMeter uma ferramenta livre para Desktop, implementada em Java/Swing e que facilita a criao de
testes de carga, estresse, desempenho e longevidade. Os testes so criados com auxlio da interface
de usurio, dispensando o uso de cdigo-fonte. O teste denido por intermdio de uma rvore de
comandos a ser executados (Plano de Teste), sendo que cada comando representado por um elemento
fornecido pela interface. As guras a seguir mostram um exemplo simples de um teste de carga para
uma aplicao Web.
Na Figura A.1 possvel ver as informaes globais do teste (lado direito da gura) e a rvore de
comandos a ser executados (lado esquerdo). No Plano de Teste, possvel denir inmeras variveis (a
tabela da gura), as quais so visveis a todos os comandos do teste. J em relao a rvore de elementos,
cada tipo de comando representado por um cone e um nome. Alguns desses comandos sero descritos
nas prximas guras.
Figura A.1: Conguraes do Plano de Teste com JMeter.
O comando Usurios do tipo Thread Group (Grupo de Threads, Figura A.2), que dene a quan-
181
tidade de usurios que sero simulados acessando o sistema (Number of Threads). Ainda, possvel
congurar algumas opes de como esses usurios iro fazer as requisies (as outras opes da parte
direita da janela). Por exemplo, a Loop Count dene quantas vezes cada usurio ir repetir os passos do
teste.
Note que os valores denidos nessa janela utilizam algumas das variveis denidas no comando
Plano de Teste. Isso foi feito para centralizar as conguraes mais importantes em um s lugar. Assim,
uma mesma rvore de comandos pode ser facilmente aproveitada para realizar os testes em diferentes
ambientes, bastando alterar as variveis pertinentes.
Figura A.2: Conguraes dos Usurios que sero simulados pelo JMeter.
Outro comando de congurao, que essencial para testes de aplicaes Web, o do tipo HTTP
Request Defaults (Figura A.3). Nele possvel denir o protocolo de acesso, o servidor e a porta,
assim como o tipo de codicao (encoding) e os tempos mximos de conexo e resposta (timeouts) das
requisies, alm de outras conguraes.
Tendo denido as conguraes centrais do teste, momento de denir quais pginas os usurios
simulados iro acessar, representado pelo comando Test. Esse comando serve para agrupar um conjunto
de aes para melhorar a organizao e reutilizao dos elementos. Existem ainda outros comandos
lgicos, tais como condicionais e de laos.
Nesse teste simples, o usurio ir apenas acessar a pgina inicial (Home, Figura A.4) e fazer uma
busca (Busca, Figura A.5), que so comandos do tipo HTTP Request (Requisio HTTP). Para acessar
a pgina inicial, basta a execuo de uma requisio HTTP do tipo GET no caminho /, enquanto, para
executar a busca, necessrio fazer um POST para /search contendo o texto a ser buscado.
O comando de requisio HTTP ainda possui outras opes, alm de que possvel sobrescrever
as conguraes denidas no comando HTTP Request Defaults. Para denir essas opes, preciso
conhecer em detalhes como funciona o sistema.
Quando o Plano de Teste executado, o JMeter carrega as conguraes, cria as threads que simu-
laro os usurios e executa as requisies previamente denidas. Entretanto, um teste no completa-
182
Figura A.3: Conguraes padres do servidor.
Figura A.4: Requisio HTTP GET na pgina inicial do sistema em teste.
183
Figura A.5: Requisio HTTP POST para realizar uma busca no sistema.
mente automatizado se ele no coleta e exibe as informaes pertinentes para anlise, por isso, o JMeter
tambm fornece diversos elementos que geram relatrios.
Por exemplo, a Figura A.6 mostra um grco onde possvel visualizar todos os tempos de resposta
das requisies feitas pelos usurios. A partir desses valores, so calculados a mdia, mediana, desvio
padro e, tambm, a vazo que representa a quantidade de requisies que so suportadas por minuto.
Esse exemplo bem simples, mas que pode ser bem til para avaliar a capacidade da infraestrutura
da sua aplicao. Para transform-lo em um teste de estresse, basta aumentar a quantidade de usurios e
de requisies at que o servidor caia ou o desempenho se torne insuportavelmente lento.
Os testes podem ser feitos para cada funcionalidade do sistema, ou, ento, pode-se criar uma sequn-
cia de passos que comum dos usurios fazerem. Apenas importante ressaltar que as funcionalidades
mais populares e mais pesadas do sistema devem ser priorizadas, ou seja, as que possuem mais risco de
derrubar os servidores.
184
Figura A.6: Um dos grcos que pode ser gerado pelo JMeter.
185
186
Apndice B
Biblioteca CUnit
Na Seo 6.4.12 h um exemplo de testes criados com o arcabouo CUNit, agora, a Figura B.1 apresenta
um esqueleto de como criar uma bateria (suite) de testes, ou seja, como cadastrar as funes que devem
ser executadas pelo arcabouo (linhas 13 a 33).
OCUnit fornece vrias maneiras de executar as baterias de testes. Omodo convencional a Interface
Automatizada (linhas 42 a 44), que executa os testes sem interveno humana e imprime os resultados
em um arquivo XML. A Interface Bsica (linhas 35 a 40) tambm inicia os testes automaticamente,
mas permite executar individualmente baterias ou testes. Quanto aos resultados, eles so impressos no
console, com quantidade de detalhes que pode ser congurada. Ainda h a Interface Interativa, a qual
permite que o usurio controle o uxo de execuo dos testes.
187
1 #include <stdio.h>
2 /* Referncias do CUnit */
3 #include <CUnit/CUnit.h>
4 #include <CUnit/Basic.h>
5 #include <CUnit/Automated.h>
6
7 void test_um(void) { /* ... */ }
8 void test_dois(void) { /* ... */ }
9 void test_tres(void) { /* ... */ }
10
11 /* Execuo dos testes com CUnit */
12 int main() {
13 CU_pSuite suite = NULL;
14
15 /* Inicializa registro de testes do CUnit */
16 if (CUE_SUCCESS != CU_initialize_registry())
17 return CU_get_error();
18
19 /* Adiciona a suite de testes ao registro */
20 suite = CU_add_suite("Suite", NULL, NULL);
21 if (NULL == suite) {
22 CU_cleanup_registry();
23 return CU_get_error();
24 }
25
26 /* Adiciona casos de testes suite de testes */
27 if ((NULL == CU_add_test(suite, "test_um", test_um)) ||
28 (NULL == CU_add_test(suite, "test_dois", test_dois)) ||
29 (NULL == CU_add_test(suite, "test_tres", test_tres))
30 ) {
31 CU_cleanup_registry();
32 return CU_get_error();
33 }
34
35 /* Executa todos os testes usando Interface Bsica */
36 CU_basic_set_mode(CU_BRM_VERBOSE);
37 CU_basic_run_tests();
38 printf("\n");
39 CU_basic_show_failures(CU_get_failure_list());
40 printf("\n\n");
41
42 /* Executa todos os testes usando Interface Automatizada */
43 CU_automated_run_tests();
44 CU_list_tests_to_file();
45
46 return CU_get_error();
47 }
Figura B.1: Biblioteca CUnit.
188
Referncias Bibliogrcas
[1] Gojko Adzic. Bridging the Communication Gap: Specication by Example and Agile Acceptance
Testing. Neuri Limited, 2009.
[2] Scott W. Ambler. Test driven database design. TASS Quarterly magazine, page 4, September
2006. Toronto Association of Systems and Software Quality.
[3] Scott W. Ambler and Ron Jeffries. Agile Modeling: Effective Practices for Extreme Programming
and the Unied Process. Wiley, 2002.
[4] Scott W. Ambler and Pramod J. Sadalage. Refactoring Databases: Evolutionary Database De-
sign. Addison-Wesley, 2006.
[5] Prasanth Anbalagan and Tao Xie. Apte: automated pointcut testing for aspectj programs. In
WTAOP 06: Proceedings of the 2nd workshop on Testing aspect-oriented programs, pages 27
32, New York, NY, USA, 2006. ACM.
[6] Ann Anderson, Ralph Beattie, Kent Beck, David Bryant, Marie DeArment, Martin Fowler, Mar-
garet Fronczak, Rich Garzaniti, Dennis Gore, Brian Hacker, Chet Hen-drickson, Ron Jeffries,
Doug Joppie, David Kim, Paul Kowalsky, Debbie Mueller, Tom Murasky, Richard Nutter, Adrian
Pantea, and Don Thomas. Chrysler goes to extremes. Distributed Computing, 1(10):2428, Oc-
tober 1998.
[7] Susan G. Archer, Laurel Allender, and Celine Richer. Software durability - is it important? can
it be achieved? In Proceedings of the Seventh International Conference on Human-Computer
Interaction, pages 593596, 1997.
[8] Abel Avram and Floyd Marinescu. Domain-Driven Design Quickly. Lulu.com, 2007.
[9] Alberto Avritzer and Elaine J. Weyuker. Generating test suites for software load testing. In
International Symposium on Software Testing and Analysis (ISSTA), pages 4457, 1994.
[10] Alberto Avritzer and Elaine J. Weyuker. The automatic generation of load test suites and the
assessment of the resulting software. IEEE Transactions on Software Engineering, 21(9):705
716, September 1995.
[11] Liane Ribeiro Pinto Bandeira. Metodologia baseada em mtricas de teste para indicao de testes
a serem melhorados. Dissertao eletrnica, Biblioteca Digital de Teses e Dissertaes da UFPE,
Setembro 2008.
[12] Vitor R. Basili, Gianluigi Caldiera, and H. Dieter Rombach. The goal question metric. In Ency-
clopedia of Software Engineering, pages 528532, 1996.
[13] Kent Beck. Simple smalltalk testing: With patterns. First Class Software, Inc., 1994.
189
[14] Kent Beck. Make it run, make it right: Design through refactoring. The Smalltalk Report, 6(4):19
24, January 1997.
[15] Kent Beck. Extreme Programming Explained: Embrace Change. Addison-Wesley, 1999.
[16] Kent Beck. Test-Driven Development: By Example. Addison-Wesley, 2002.
[17] Kent Beck and Cynthia Andres. Extreme Programming Explained: Embrace Change, 2nd Edi-
tion. Addison-Wesley, 2004.
[18] Kent Beck et al. Manifesto for Agile Software Development. Home page: http://
agilemanifesto.org, 2001.
[19] Kent Beck and Martin Fowler. Planning Extreme Programming. Addison-Wesley, 2001.
[20] Kent Beck and Mike Potel. Kent Becks Guide to Better Smalltalk. Cambridge University Press,
1998.
[21] Boris Beizer. Black-Box Testing: Techniques for Functional Testing of Software and Systems.
Wiley, 1995.
[22] Yochai Benkler. Coases Penguin, or Linux and the Nature of the Firm. Computing Research
Repository (CoRR), 2001.
[23] Yochai Benkler. The Wealth of Networks: How Social Production Transforms Markets and Free-
dom. Yale University Press, 2006.
[24] Mario Luca Bernardi and Giuseppe Antonio Di Lucca. Testing aspect oriented programs: an
approach based on the coverage of the interactions among advices and methods. In Quality of
Information and Communications Technology, 2007. QUATIC2007. 6th International Conference
on the, pages 6576. IEEE Computer Society, 2007.
[25] Thirumalesh Bhat and Nachiappan Nagappan. Evaluating the efcacy of test-driven development:
industrial case studies. In ISESE 06: Proceedings of the 2006 ACM/IEEE international sympo-
sium on Empirical software engineering, pages 356363, New York, NY, USA, 2006. ACM.
[26] Randolph Bias. Walkthroughs: Efcient collaborative testing. IEEE Software, 8(5):9495,
September 1991.
[27] Robert V. Binder. Design for testability in object-oriented systems. CACM: Communications of
the ACM, 37(9):87101, 1994.
[28] Robert V. Binder. Testing object-oriented systems: models, patterns, and tools. Addison-Wesley
Professional, 1999.
[29] Rex Black. Pragmatic Software Testing: Becoming an Effective and Efcient Test Professional.
Wiley, 2007.
[30] Joshua Bloch. Effective Java. Prentice Hall PTR, 2008.
[31] Barry W. Boehm. A spiral model of software development and enhancement. IEEE Computer,
pages 6172, May 1988.
[32] Frank Buschmann, Regine Meunier, Hans Rohnert, Peter Sommerlad, and Michael Stal. Pattern-
Oriented Software Architecture, Volume 1, A System of Patterns. Hardcover, 1996.
190
[33] Gerardo Canfora, Aniello Cimitile, Felix Garcia, Mario Piattini, and Corrado Aaron Visaggio.
Evaluating advantages of test driven development: a controlled experiment with professionals. In
ISESE 06: Proceedings of the 2006 ACM/IEEE international symposium on Empirical software
engineering, pages 364371, New York, NY, USA, 2006. ACM.
[34] David Chelimsky, Dave Astels, Bryan Helmkamp, Dan North, Zach Dennis, and Aslak Hellesoy.
The RSpec Book: Behaviour Driven Development with RSpec, Cucumber, and Friends. Pragmatic
Bookshelf, 2009.
[35] Paulo Cheque and Fabio Kon. Desenvolvendo com agilidade: Experincias na reimplementao
de um sistema de grande porte. In Primeiro Workshop de Desenvolvimento Rpido de Aplicaes
(WDRA), realizado em conjunto com o VI Simpsio Brasileiro de Qualidade de Software, 2007.
[36] Paulo Cheque and Fabio Kon. A importncia dos testes automatizados: Controle gil, rpido e
convel de qualidade. Engenharia de Software Magazine, 1(3):5457, 2008.
[37] Tony Clear. The waterfall is dead: long live the waterfall!! ACM SIGCSE (Special Interest Group
on Computer Science Education) Bulletin, 35(4):1314, 2003.
[38] Alistair Cockburn. Agile Software Development. Addison-Wesley Longman, 2002.
[39] Alistair Cockburn and Laurie Williams. The costs and benets of pair programming. In Proceed-
ings of the First International Conference on Extreme Programming and Flexible Processes in
Software Engineering (XP2000), Cagliari, Sardinia, Italy, June 2000.
[40] Mike Cohn. User Stories Applied: For Agile Software Development. Addison Wesley Longman
Publishing Co., Inc., Redwood City, CA, USA, 2004.
[41] Mike Cohn. Agile Estimating and Planning. Prentice Hall PTR, 2005.
[42] Microsoft Corporation. Engineering Software for Accessibility. Microsoft Press, 2009.
[43] Lisa Crispin and Janet Gregory. Agile Testing: A Practical Guide for Testers and Agile Teams
(Addison-Wesley Signature Series). Addison-Wesley, 2009.
[44] Lisa Crispin and Tip House. Testing Extreme Programming. Addison-Wesley, 2002.
[45] Philip B. Crosby. Quality Is Free. Mentor, 1980.
[46] Alexandre Freire da Silva. Reexes sobre o ensino de metodologias geis na academia, na
indstria e no governo. Masters thesis, Departamento de Cincia da Computao, Instituto de
Matemtica e Estatstica - Universidade de So Paulo, Setembro 2007.
[47] Thomas H. Davenport and Jeanne G. Harris. Competing on Analytics: The New Science of Win-
ning. Harvard Business School Press, 2007.
[48] Vieri del Bianco, Luigi Lavazza, Sandro Morasca, Davide Taibi, and Davide Tosi. The qualispo
approach to oss product quality evaluation. In FLOSS 10: Proceedings of the 3rd International
Workshop on Emerging Trends in Free/Libre/Open Source Software Research and Development,
pages 2328, New York, NY, USA, 2010. ACM.
[49] Esther Derby and Diana Larsen. Agile Retrospectives: Making Good Teams Great. Pragmatic
Bookshelf, 2006.
[50] Edsger W. Dijkstra. The humble programmer. CACM: Communications of the ACM, 15, 1972.
191
[51] M. E. Drummond, Jr. A perspective on system performance evaluation. IBM Systems Journal,
8(4):252263, 1969.
[52] Paul Duvall, Steve Matyas, and Andrew Glover. Continuous Integration: Improving Software
Quality and Reducing Risk. Addison-Wesley Professional, 2007.
[53] Eduardo Martins Guerra. Um estudo sobre refatorao de cdigo de teste. Masters thesis, Insti-
tuto Tcnolgico de Aeronutica, 2005.
[54] Gerald D. Everett and Raymond McLeod Jr. Software Testing. John Wiley and Sons, Inc, 2007.
[55] Michael Feathers. Working Effectively with Legacy Code. Prentice Hall, 2008.
[56] Mark Fewster and Dorothy Graham. Software Test Automation. Addison-Wesley Professional,
1999.
[57] Dairton Luiz Bassi Filho. Experincias com desenvolvimento gil. Masters thesis, Departamento
de Cincia da Computao, Instituto de Matemtica e Estatstica - Universidade de So Paulo,
Maro 2008.
[58] Ira R. Forman and Nate Forman. Java Reection in Action. Manning Publications, 2004.
[59] Martin Fowler. Refactoring: Improving the Design of Existing Code. Addison-Wesley, 1999.
[60] Steve Freeman and Nat Pryce. Growing Object-Oriented Software, Guided by Tests. Addison-
Wesley Professional, 2009.
[61] Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. Design Patterns Elements of
Reusable Object-Oriented Software. Professional Computing Series. Addison-Wesley, 1995.
[62] David Gelperin and Bill Hetzel. The growth of software testing. CACM: Communications of the
ACM, 31(6):687695, 1988.
[63] Tom Gilb and Dorothy Graham. Software Inspection. Addison Wesley, 1993.
[64] Robert L. Glass. Persistent software errors. IEEE Transactions on Software Engineering,
7(2):162168, March 1981.
[65] Robert L. Glass. The standish report: does it really describe a software crisis? 49(8):1516, 2006.
[66] The Standish Group. The CHAOS report, 1994.
[67] The Standish Group. The CHAOS report, 2003.
[68] Atul Gupta and Pankaj Jalote. Test inspected unit or inspect unit tested code? In Empirical
Software Engineering and Measurement (ESEM), pages 5160. IEEE Computer Society, 2007.
[69] Misko Hevery. Testability explorer: using byte-code analysis to engineer lasting social changes
in an organizations software development process. In OOPSLA Companion 08: Companion
to the 23rd ACM SIGPLAN conference on Object-oriented programming systems languages and
applications, pages 747748, New York, NY, USA, 2008. ACM.
[70] Dorota Huizinqa and Adam Kolawa. Automated Defect Prevention: Best Practices in Software
Management. Wiley-IEEE Computer Society Press, 2007.
[71] Andy Hunt and Dave Thomas. Pragmatic Unit Testing in Java with JUnit. The Pragmatic Pro-
grammers, 2003.
192
[72] The IEEE. IEEE standard for software reviews and audits. ANSI/IEEE STD 1028-1988, IEEE
Computer Society, 1988.
[73] Melody Y. Ivory and Marti A Hearst. The state of the art in automating usability evaluation of
user interfaces. ACM Comput. Surv., 33(4):470516, 2001.
[74] David Janzen. Software architecture improvement through test-driven development. In Ralph E.
Johnson and Richard P. Gabriel, editors, OOPSLA Companion, pages 240241. ACM, 2005.
[75] David S. Janzen and Hossein Saiedian. On the inuence of test-driven development on software
design. In CSEET 06: Proceedings of the 19th Conference on Software Engineering Education
& Training, pages 141148, Washington, DC, USA, 2006. IEEE Computer Society.
[76] Cem Kaner. Improving the maintainability of automated test suites. Proceedings of the Tenth
International Quality Week, 1997.
[77] Cem Kaner, Jack Falk, and Hung Q. Nguyen. Testing Computer Software. Wiley, 1999.
[78] R. A. Khan and K. Mustafa. Metric based testability model for object oriented design (mtmood).
SIGSOFT Softw. Eng. Notes, 34(2):16, 2009.
[79] Joshua Kierievsky. Refactoring to Patterns. Addison-Wesley Professional, 2001.
[80] Taeksu Kim, Chanjin Park, and Chisu Wu. Mock object models for test driven development.
In Software Engineering Research, Management and Applications, 2006. Fourth International
Conference on, pages 221228. IEEE Computer Society, 2006.
[81] Donald Knuth. Structured programming with go to statements. ACM Journal Computing Surveys,
6(4), 1974.
[82] Lasse Koskela. Test Driven: Practical TDD and Acceptance TDD for Java Developers. Manning
Publications, 2007.
[83] Mohit kumar, Akashdeep sharma, and Sushil Garg. A study of aspect oriented testing techniques.
In Industrial Electronics & Applications, 2009. ISIEA 2009. IEEE Symposium on, pages 996
1001. IEEE Computer Society, 2009.
[84] Craig Larman and Victor R. Basili. Iterative and incremental development: a brief history. IEEE
Computer, pages 4756, July 2003.
[85] Otvio Augusto Lazzarini Lemos, Fabiano Cutigi Ferrari, Paulo Cesar Masiero, and
Cristina Videira Lopes. Testing aspect-oriented programming pointcut descriptors. In Roger T.
Alexander, Stephan Herrmann, and Dehla Sokenou, editors, Workshop on Testing Aspect-
Oriented Programs (WTAOP), pages 3338. ACM, 2006.
[86] Otvio A. L. Lemos, Jos Carlos Maldonado, and Paulo Cesar Masiero. Teste de unidades de
programas orientados a aspectos. In Simpsio Brasileiro de Engenharia de Software, 2004.
[87] Karl R. P. H. Leung and Wing Lok Yeung. Generating user acceptance test plans from test cases.
In COMPSAC, pages 737742. IEEE Computer Society, 2007.
[88] K. J. Lienberherr. Formulations and benets of the law of demeter. 1989.
[89] Barbara Liskov. Keynote address - data abstraction and hierarchy. In OOPSLA 87: Adden-
dum to the proceedings on Object-oriented programming systems, languages and applications
(Addendum), pages 1734, New York, NY, USA, 1987. ACM.
193
[90] Henry H. Liu. Software Performance and Scalability: A Quantitative Approach (Quantitative
Software Engineering Series). Wiley, 2009.
[91] Cristina Videira Lopes and Trung Chi Ngo. Unit-testing aspectual behavior. In In proc. of Work-
shop on Testing Aspect-Oriented Programs (WTAOP), held in conjunction with the 4th Interna-
tional Conference on Aspect-Oriented Software Development (AOSD05), 2005.
[92] Kim Man Lui and Keith C.C. Chan. Test-driven development and software process improvement
in china. In Proceedings of the 5th International Conference on eXtreme Programming and Ag-
ile Processes in Software Engineering (XP 2004), volume 3092 of Lecture Notes on Computer
Science, pages 219222, 2004.
[93] Tim Mackinnon, Steve Freeman, and Philip Craig. Endo-testing: unit testing with mock objects,
pages 287301. Addison-Wesley Longman Publishing Co., Inc., Boston, MA, USA, 2001.
[94] Lech Madeyski. Test-Driven Development: An Empirical Evaluation of Agile Practice. Springer,
2009.
[95] Jos Carlos Maldonado, Mrcio Eduardo Delamaro, and Mario Jino. Introduo ao Teste de
Software. Campus, 2007.
[96] Robert C. Martin. The test bus imperative: Architectures that support automated acceptance
testing. IEEE Software, 22(4):6567, 2005.
[97] Robert C. Martin. Clean Code: A Handbook of Agile Software Craftsmanship. Prentice Hall
PTR, 2008.
[98] Deborah J. Mayhew. The Usability Engineering Lifecycle: A Practitioners Handbook for User
Interface Design (Interactive Technologies). Morgan Kaufmann, 1999.
[99] Gerard Meszaros. XUnit Test Patterns: Refactoring Test Code. Addison-Wesley, 2007.
[100] Bertrand Meyer. Object-Oriented Software Construction, Second Edition. The Object-Oriented
Series. Prentice-Hall, Englewood Cliffs (NJ), USA, 1997.
[101] James B. Michael, Bernard J. Bossuyt, and Byron B. Snyder. Metrics for measuring the effective-
ness of software-testing tools. In International Symposium on Software Reliability Engineering
(ISSRE), pages 117128. IEEE Computer Society, 2002.
[102] Rodrigo M. L. M. Moreira, Ana C. R. Paiva, and Ademar Aguiar. Testing aspect-oriented pro-
grams. In Information Systems and Technologies (CISTI), 2010 5th Iberian Conference on, pages
16. IEEE Computer Society, 2010.
[103] Tomer Moscovich and John F. Hughes. Indirect mappings of multi-touch input using one and two
hands. pages 12751284. ACM, 2008.
[104] Rick Mugridge and Ward Cunningham. Fit for Developing Software: Framework for Integrated
Tests. Prentice Hall, 2005.
[105] Glenford J. Myers. The Art of Software Testing. John Wiley and Sons, New York, 1979.
[106] Syed Asad Ali Naqvi, Shaukat Ali, and M. Uzair Khan. An evaluation of aspect oriented testing
techniques. In Emerging Technologies, 2005. Proceedings of the IEEE Symposium on, pages
461466. IEEE Computer Society, 2005.
[107] NIST. National institute of standards and technology, 2002.
194
[108] H. Ohba. Software quality = test accuracy * test coverage. In International Conference on
Software Engineering (ICSE), pages 287295, 1982.
[109] Taiichi Ohno. Toyota Production System: Beyond Large-Scale Production. Productivity Press,
1998.
[110] William F. Opdyke. Refactoring Object-Oriented Frameworks. Ph.D. thesis, University of Illi-
nois, 1992.
[111] Behrooz Parhami. Defect, fault, error,..., or failure? In Reliability, IEEE Transactions on, vol-
ume 46, pages 450451. IEEE Reliability Society, 1997.
[112] Mary Poppendieck and Tom Poppendieck. Lean Software Development: An Agile Toolkit.
Addison-Wesley Professional, 2003.
[113] Dhanji Prasanna. Dependency Injection. Manning Publications, 2009.
[114] IEEE Press. Standard 610.12. IEEE standard glossary of software engineering terminology, 1990.
[115] Roger Pressman. Software Engineering: A Practitioners Approach. McGraw-Hill Science/Engi-
neering/Math, 2009.
[116] Viera K. Proulx. Test-driven design for introductory oo programming. In SIGCSE 09: Proceed-
ings of the 40th ACM technical symposium on Computer science education, pages 138142, New
York, NY, USA, 2009. ACM.
[117] Nat Pryce. Growing Object-Oriented Software, Guided by Tests. Addison-Wesley Professional,
2009.
[118] Vaclav Rajlich. Changing the paradigm of software engineering. Communications of the ACM,
49(8):6770, August 2006.
[119] Reginaldo R, Otvio Augusto Lazzarini Lemos, and Paulo Cesar Masiero. Minimizing stub
creation during integration test of aspect-oriented programs. In WTAOP 07: Proceedings of the
3rd workshop on Testing aspect-oriented programs, pages 16, New York, NY, USA, 2007. ACM.
[120] Stuart Reid. The art of software testing, second edition. glenford J. myers. Softw. Test, Verif.
Reliab, 15(2):136137, 2005.
[121] Andr Restivo and Ademar Aguiar. Towards detecting and solving aspect conicts and interfer-
ences using unit tests. In SPLAT 07: Proceedings of the 5th workshop on Software engineering
properties of languages and aspect technologies, page 7, New York, NY, USA, 2007. ACM.
[122] Don Roberts, John Brant, and Ralph E. Johnson. A refactoring tool for Smalltalk. Theory and
Practice of Object Systems (TAPOS), 3(4):253263, 1997.
[123] Winston W. Royce. Managing the development of large software systems: concepts and tech-
niques. In ICSE 87: Proceedings of the 9th international conference on Software Engineering,
pages 328338, Los Alamitos, CA, USA, 1987. IEEE Computer Society Press.
[124] David Saff and Michael D. Ernst. Can continuous testing speed software development? In
Fourteenth International Symposium on Software Reliability Engineering (ISSRE), pages 281
292, 2003.
[125] Goutam Kumar Saha. Understanding software testing concepts. Ubiquity, 2008(1):1, February
2008.
195
[126] Joc Sanders and Eugene Curran. Software Quality. Addison-Wesley, 1994.
[127] Danilo Sato, Alfredo Goldman, and Fabio Kon. Tracking the Evolution of Object Oriented Qual-
ity Metrics. In Proceedings of the 8th International Conference on Extreme Programming and
Agile Processes in Software Engineering (XP2007), pages 8492, 2007.
[128] Danilo Toshiaki Sato. Uso ecaz de mtricas em mtodos geis de desenvolvimento de software.
Masters thesis, Departamento de Cincia da Computao, Instituto de Matemtica e Estatstica -
Universidade de So Paulo, Agosto 2007.
[129] Ulrich Schoettmer and Toshiyuki Minami. Challenging the high performance high cost
paradigm in test. In International Test Conference (ITC 95), pages 870879, Altoona, Pa.,
USA, October 1995. IEEE Computer Society Press.
[130] Ken Schwaber. Agile Project Management with Scrum. Microsoft Press, 2004.
[131] Ken Schwaber and Mike Beedle. Agile Software Development with SCRUM. Prentice Hall, 2001.
[132] Mike Potel Sean Cotter. Inside Taligent Technology. Taligent Press, 1995.
[133] Helen Sharp, Yvonne Rogers, and Jenny Preece. Interaction Design: Beyond Human-Computer
Interaction. Wiley, 2007.
[134] Walter Andrew Shewhart. Statistical method from the viewpoint of quality control. In Dover
Publications, 1939.
[135] Sandro Silvestre. Desenvolvimento de software robusto. PhD thesis, Instituto de Pesquisas Tec-
nolgicas do Estado de So Paulo - Universidade de So Paulo, Dezembro 2006.
[136] Diomidis Spinellis. Code Quality: The Open Source Perspective. Addison-Wesley Professional,
2006.
[137] Susan H. Strauss and Robert G. Ebenau. Software Inspection Process. McGraw-Hill, 1994.
[138] Dave Thomas and Andy Hunt. Mock objects. In Software, IEEE, volume 19, pages 2224. IEEE
Computer Society, 2002.
[139] Jenifer Tidwell. Designing Interfaces. OReilly Media, 2005.
[140] James E. Tomayko. A comparison of pair programming to inspections for software defect reduc-
tion. Computer Science Education, 12(3):213222, 2002.
[141] Richard Torkar. Towards automated software testing - techniques, classications and frameworks.
Masters thesis, School of Engineering - Dept. of Systems and Software Engineering/Blekinge
Institute of Technology, 2006.
[142] K. Vahidi and A. Orailoglu. Testability metrics for synthesis of self-testable designs and effective
test plans. In VTS 95: Proceedings of the 13th IEEE VLSI Test Symposium, page 170, Washing-
ton, DC, USA, 1995. IEEE Computer Society.
[143] Arie van Deursen, Leon M. F. Moonen, Alexander van den Bergh, and Gerard Kok. Refactoring
test code. Preprint, Centrum voor Wiskunde en Informatica, department Software Engineering
(SEN), 2001.
[144] Auri Marcelo Rizzo Vincenzi, Jos Carlos Maldonado, Eric W. Wong, and Mrcio Eduardo Dela-
maro. Coverage testing of java programs and components. Sci. Comput. Program., 56(1-2):211
230, 2005.
196
[145] James A. Whittaker and Mike Andrews. How to break Web software: functional and security
testing of Web applications and Web services. Addison-Wesley, 2006.
[146] Laurie Williams and Robert Kessler. Pair Programming Illuminated. Addison-Wesley, 2002.
[147] Laurie A. Williams, E. Michael Maximilien, and Mladen A. Vouk. Test-driven development as a
defect-reduction practice. In ISSRE, pages 3448. IEEE Computer Society, 2003.
[148] Stephen Withall. Software Requirement Patterns (Best Practices). Microsoft Press, 2007.
[149] Yuk Kuen Wong. Modern Software Review: Techniques and Technologies. IRM Press, 2006.
[150] Tao Xie and Jianjun Zhao. Perspectives on automated testing of aspect-oriented programs. In
WTAOP 07: Proceedings of the 3rd workshop on Testing aspect-oriented programs, pages 712,
New York, NY, USA, 2007. ACM.
[151] Edward Yourdon. Structured Walkthrough. Prentice-Hall, 4th edition, 1989.
[152] Chuan Zhao and Roger T. Alexander. Testing aspect-oriented programs as object-oriented pro-
grams. In WTAOP 07: Proceedings of the 3rd workshop on Testing aspect-oriented programs,
pages 2327, New York, NY, USA, 2007. ACM.
[153] Hong Zhu, Patrick A. V. Hall, and John H. R. May. Software unit test coverage and adequacy.
CSURV: Computing Surveys, 29, 1997.
197

Você também pode gostar