Você está na página 1de 9

capa_

Benefícios do
medidos na prática
TDD
Com a popularização dos méto-
dos ágeis, difundiu-se bastan-
te o desenvolvimento orientado
a testes (TDD – Test-driven
Development), disciplina
focada em design de sof-
tware que consiste em apli- Em poucas palavras, Test-driven Development
(TDD) é uma abordagem iterativa para desenvol-
car pequenos ciclos iterativos de vimento de software cujo princípio básico está em
teste-codificação-refatoração à escrever testes automatizados para a funcionalida-
de a ser implementada antes de ela ser codificada.
medida que a funcionalidade é O fato é que não é natural resolver um problema de
desenvolvida. O princípio central programação desta maneira para a maioria de nós.
Normalmente, o que fazemos é analisar os requisi-
do TDD consiste em escrever os tos, pensar na solução e, simplesmente, codificá-la.
testes antes do código a ser im- Isto é: mãos à obra! Queremos resolver o problema!
Essa dificuldade inerente do TDD suscita bas-
plementado. Essa prática costu- tante ceticismo em muitos desenvolvedores (espe-
ma ser vista de maneira reticen- cialmente os mais antigos) quanto à efetividade des-
ta prática. Será que os diversos ciclos de TDD não
te e cética pelas pessoas que não acarretam perda de produtividade? E as constantes
possuem experiência com TDD. refatorações não são um retrabalho desnecessário?
Quer dizer que o desenvolvedor não precisa mais
Afinal de contas, será que TDD pensar em arquitetura? Afinal de contas, os próprios
ajuda mesmo ou apenas “está na testes automatizados se pagam? Se sim, existe mes-
mo algum benefício substancial em escrevê-los an-
moda”? Existe vantagem real em tes do código?
escrever os testes antes ou eles Neste artigo, o objetivo é refletir um pouco so-
bre essas questões à luz de alguns estudos empíricos
podem ser escritos ao final com realizados sobre o uso de TDD em meio acadêmico e
os mesmos benefícios? Neste industrial. Primeiramente, faremos uma introdução
básica sobre TDD e discutiremos aspectos mais ge-
artigo, examinaremos algumas rais relacionados ao tema de testes automatizados e
destas questões, considerando sua importância para todo desenvolvedor profissio-
também alguns estudos empíri- nal. Mais a frente, analisaremos questões pertinen-
tes ao uso de TDD, tais como efeitos em produtivida-
cos publicados na área. de e qualidade.

/6
Alexandre Gazola | alexandregazola@gmail.com | @alexandregazola
Bacharel em Ciência da Computação pela Universidade Federal de Viçosa (UFV) e mestre em Informática pela PUC-Rio. Trabalha
como Analista de Sistemas no BNDES, desenvolve em Java desde 2003 e possui as certificações SCJP e SCWCD. É articulista e
editor-técnico da revista MundoJ, além de possuir um blog em http://alexandregazola.wordpress.com.

Dada à relevância do assunto, TDD e testes au- rio. TDD pode ser aplicado tanto para as pequenas
tomatizados são um tema frequentemente explora- partes que compõem um sistema (testes de unidade
do em artigos desta revista. Neste texto, partimos para métodos de classes) quanto para componentes
do pressuposto que o leitor já possui familiaridade maiores (testes de integração para métodos de uma
com esses tópicos. Não obstante, tentamos deixar camada de serviço ou testes via GUI, por exemplo).
o artigo o mais autocontido possível, de maneira a Além do benefício em design, “de quebra” o TDD
permitir que o mesmo seja também proveitoso para traz o grande benefício colateral de fazer com que
os mais leigos no assunto. Para mais informações e seja criada uma extensa suíte de testes de regressão
artigos introdutórios já publicados sobre o tema, ver para o sistema, com elevado nível de cobertura.
quadro “Para saber mais”, ao final do texto. Robert Martin (Uncle Bob) resumiu o TDD nas
seguintes “leis”:
Test-driven Development »» Não é permitido escrever nenhum código de
Em poucas palavras, Test-driven Development produção a menos que seja para fazer com que
(TDD) é uma abordagem iterativa para desenvol- um teste que esteja falhando passe;
vimento de software baseada em testes automa- »» Não é permitido escrever mais código de teste
tizados. A ideia é aplicar pequenos ciclos de teste- do que o suficiente para que ele falhe (consi-
-codificação-refatoração, também conhecido como derando que compilação também é uma falha)
red-green-refactor, como mostra a figura 1. – em outras palavras, o código do teste deve
Escrever o teste antes, prática conhecida como ser simples e exercitar um único aspecto da
test-first, obrigatoriamente força com que o códi- funcionalidade a ser implementada;
go produzido seja testável por construção, e código »» Não é permitido escrever mais código de pro-
testável implica código com baixo acoplamento, as- dução do que o suficiente para que o único tes-
pecto extremamente importante em qualquer bom te que está falhando passe.
design de software. Se você não está acostumado a programar usan-
Além disso, existe o feedback quanto à “corre- do TDD, muito provavelmente sentirá bastante difi-
tude” do que acabou de ser feito. Tem-se um critério culdade em manter a disciplina necessária para se-
claro e não ambíguo do que significa uma funcio- guir essas três leis de maneira estrita. Sendo assim,
nalidade estar pronta. Também é uma boa prática antes de entrar nos méritos ou não do TDD, vamos
para evitar o problema de over-engineering, ou seja, dar um passo atrás e dar uma olhada no assunto mais
implementar mais do que o estritamente necessá- geral a respeito de testes automatizados.

Testes automatizados são


imprescindíveis e ponto final
Testes automatizados são uma ferramenta ex-
tremamente valiosa de feedback, ajudando a garantir
tanto a qualidade externa (aquela perceptível pelo
usuário) quanto à qualidade interna (aquela percep-
tível pelo desenvolvedor).
A facilidade de poder executar continuamente
os testes permite a identificação imediata de altera-
ções indesejadas no sistema. Por essa razão, os testes
existentes para um sistema também são conhecidos
como testes de regressão, pois asseguram que um sis-
tema não irá regredir do ponto atual em que se en-
contra. Acréscimo de funcionalidade pode ser feito
sem medo de quebrar algo que já funcionava.
Os testes também favorecem a prática saudável
Figura 1. O Ciclo básico do Test-Driven Development [http://blog. da refatoração, que consiste em aplicar pequenas
fasagri.com.br/?p=101]. transformações na estrutura interna de um software,

7\
preservando o comportamento externo, com o obje- executar que um conjunto de testes de unidade que
tivo de melhorar o código, tornando-o mais legível exercitam o software de maneira isolada de recur-
e mais aderente às manutenções pelas quais deverá sos externos. Ter um conjunto de testes de unidade
passar. É curioso como muitos criticam essa práti- de rápida execução encoraja o desenvolvedor a exe-
ca, não entendendo que refatoração é uma técnica cutá-los mais frequentemente e, por isso, permitem
disciplinada para manter a boa qualidade da base de a obtenção de feedback instantâneo. O ideal é que os
código. Ao longo do tempo, uma base de código que desenvolvedores possam executar todos os testes de
não passa por refatoração tenderá a ser cada vez me- unidade constantemente à medida que desenvolvem
nos coesa e fatalmente começará a “cheirar mal”. A e, se não todos, pelo menos uma porção significativa
lei da entropia é cruel. Além disso, escrever código dos testes de integração antes de fazer um commit. A
é, em muitos aspectos, como escrever um texto. Di- execução completa frequente de todos os testes do
ficilmente um autor estará satisfeito com a primeira sistema deve ficar a cargo de um servidor de integra-
versão do que produziu. Código, assim como texto, ção contínua.
deve passar por refinamentos sucessivos até atingir Dito isto, vamos às exceções. Existem casos em
um estado suficientemente bom (note que escrevi su- que, em minha opinião, testes de integração podem
ficientemente bom, e não, perfeito). ser suficientes. Por exemplo, quando se trata de com-
Software, como o próprio nome diz, é maleável ponentes para acesso a dados (DAOs, repositórios,
e feito para mudar. Além disso, as boas práticas de arquivos etc.). No caso de DAOs, costumo escrever
desenvolvimento (RUP, XP, Scrum etc.) pregam o de- testes de integração usando DbUnit e banco de da-
senvolvimento iterativo e incremental, de forma que dos HSQLDb em memória, pois não creio haver muito
alterações e acréscimos devem ser continuamente benefício em mockar as interfaces do Hibernate para
realizados sobre algo já construído. Por isso a rede de fazer testes de unidade. Outro caso é quando existem
segurança provida por uma boa suíte de testes de re- componentes bastante orientados a dados, em que
gressão automatizados é tão importante. pode ficar difícil e enfadonho realizar a configuração
programática (muito stubbing ou mocking) necessária
Testes de unidade ou de integração? para os testes. Um terceiro exemplo poderia ser uma
Outra questão que desperta discussão e dúvida classe de managed bean (Java Server Faces) que não
entre os desenvolvedores: escrever testes de unida- possua lógica de negócios significativa e cujo com-
de ou de integração? Algumas pessoas advogam que portamento consista simplesmente na delegação de
apenas os testes de integração devem ser feitos ou tarefas a outros objetos e exibição de mensagens na
priorizados, visto que estão mais próximos do uso tela. Neste caso, testes realizados pela interface web
real do sistema, abarcam porções maiores do código e podem ser uma boa opção. Portanto, recomenda-se
(em tese) tendem a ser mais estáveis quando compa- bom senso na hora de decidir pelo tipo de teste a es-
rados a testes de unidade. Essas pessoas consideram crever.
que os testes de unidade possuem um acoplamento De qualquer forma, nunca é demais repetir: é vi-
muito forte com as entidades menores do sistema tal que existam testes automatizados que sejam fáceis e
(e.g.: classes e métodos) e, por isso, são mais sensí- rápidos de serem executados. Caso contrário, os testes
veis a qualquer mudança e, logo, ocasionam maiores serão executados poucas vezes e bugs serão desco-
custos de manutenção. bertos de forma tardia no ciclo de desenvolvimento.
Esse argumento é razoável, porém deixa de lado Para finalizar esta parte, apenas quero fazer um
um benefício valioso que os testes de unidade ofe- comentário acerca da questão relativa ao acoplamen-
recem: feedback1 localizado e instantâneo quando to entre as classes de testes de unidade e suas corres-
algum erro acontece. É muito mais eficiente saber pondentes classes de produção. De fato um acopla-
que o “DAO de pedidos” não persistiu o objeto cor- mento mínimo existe, pois os testes são uma espécie
retamente no banco de dados do que simplesmente de especificação sobre o que o sistema deve fazer
houve um erro na execução da rotina de fechamento (ótima fonte de documentação para as APIs do siste-
da compra do cliente. Isso é feedback localizado. ma, por sinal). Uma vez que surja a necessidade de al-
Outra questão bastante relevante diz respeito terar a implementação, então é natural que os testes
ao tempo necessário para rodar os testes. Testes de precisem ser alterados para refletir o novo comporta-
integração, por envolverem diversas camadas e es- mento esperado. É a ideia da “engrenagem”: os dois
tarem mais próximos do ambiente real, levam muito (código de teste e de produção) funcionam juntos e
mais tempo (e alguns segundos é muito tempo) para se validam mutuamente. Às vezes, inclusive, o código
de produção ajuda a descobrir problemas no código
1 Peço desculpas por repetir mais uma vez a palavra de teste!
feedback. É porque é disso que se trata praticamente De qualquer forma, o nível de acoplamento nos
todas as boas práticas de desenvolvimento de software. testes também depende de como eles são implemen-

/8
tados. Por exemplo, testes de unidade que fazem uso to (qualidade externa) e são realizados manualmente
extensivo de mock objects para validar interações es- (ainda que com o suporte de algumas ferramentas).
peradas de uma classe com suas dependências ten- Em especial, observe que, no quadrante 4, situam-se
dem a ter um acoplamento desnecessariamente mais os testes de características não funcionais do produto
alto. (desempenho, disponibilidade, escalabilidade, etc.),
os quais são aspectos não endereçados por testes de
Criar testes automatizados não é unidade e são de mais difícil automatização.
No lado esquerdo da figura, encontram-se os
trabalho para os testadores ou para a testes importantes para promover também a quali-
equipe de Q.A.? dade interna do software e uma maior aderência do
Para começar, muitas empresas não possuem a sistema a seus requisitos de negócio. No quadrante
famosa equipe de “qualidade” (Quality Assurance ou 1, estão localizados os testes que suportam o desen-
Q.A.) ou uma equipe de testadores. Neste caso ou no volvimento (testes de unidade e integração), ao passo
caso em que a equipe use TDD, não resta outra opção. que temos, no quadrante 2, a interseção entre os tes-
É trabalho para a equipe de desenvolvimento. Para tes que suportam o desenvolvimento e os testes de
as empresas que possuem pessoas dedicadas a testes, aceitação. Vale ressaltar que todas as facetas de testes
uma boa maneira de trabalhar poderia ser da seguin- presentes nos quatro quadrantes possuem a sua im-
te forma: portância.
»» Os testadores, a partir dos requisitos, elaboram
os casos de testes para uma determinada fun-
cionalidade;
E o TDD? Será que vale a pena?
Nesta seção, discutiremos alguns aspectos rela-
»» Os desenvolvedores implementam a funciona-
cionados à TDD e ao tema de testes automatizados.
lidade e seus testes [ou vice-versa], a partir dos
Usaremos como auxílio alguns resultados obtidos por
cenários fornecidos pela equipe de teste;
estudos empíricos na área.
»» Com a funcionalidade concluída, os testadores
realizam testes exploratórios a partir da inter-
face gráfica do sistema, à procura de eventuais TDD e Design
vulnerabilidades ou defeitos que possam não Mais uma vez: TDD é sobre design. A suíte de tes-
haver sido cobertos pelos cenários de testes tes automatizados resultante é um excelente efeito
criados inicialmente. colateral. Quando se programa test-first, o desenvol-
Em relação à automatização dos testes, se a equi- vedor é forçado a pensar sobre as interfaces do siste-
pe de testadores também possui conhecimento de ma do ponto de vista do cliente, ou seja, de quem vai
desenvolvimento, também é possível utilizá-la para usar aquele código. Essa simples mudança de foco faz
automatizar os testes de aceitação. Estes são testes com que sejam criadas interfaces que revelam mais
que simplesmente especificam como o sistema deve claramente a sua intenção (o foco recai mais em “o
se comportar do ponto de vista do usuário externo. quê?” e ”por quê?” em vez de “como?” as coisas de-
Quando se usa XP, normalmente usa-se a termino- vem ser feitas). Além disso, para que o teste seja de
logia given-when-then para especificar esses testes unidade, torna-se necessário isolar as dependências
(dado x quando y então z). Esses testes podem ser in- por meio de injeção de dependências, resultando em
clusive definidos pelo próprio cliente ou especialis- um design com baixo nível de acoplamento.
ta de domínio. Normalmente, os testes de aceitação O interessante é que essas decisões são feitas e
automatizados são realizados via interface gráfica ou
na camada imediatamente inferior. Também é pos-
sível aplicar TDD neste nível mais macro dos testes
de aceitação, normalmente usando técnicas como
ATDD (Acceptance Test-Driven Development) ou BDD
(Behavior-Driven Development), que são de uso mais
recente na indústria (FIT e JBehave são ferramentas
que têm sido usadas com esse propósito).
Para complementar a discussão dos tipos de tes-
tes, é interessante darmos uma olhada nos chamados
“Quadrantes dos Testes Ágeis”, exibidos na figura 2.
Esses quadrantes foram apresentados no livro “Agile
Testing”, de Lisa Crispin e Janet Gregory.
No desenvolvimento de software “tradicional”,
os testes se concentram mais nos quadrantes do lado
direito (3 e 4), ou seja, possuem foco maior no produ- Figura 2. Os quadrantes dos testes ágeis (do livro “Agile Testing”)

9\
Erros comuns que as pessoas cometem
Ao longo do aprendizado e amadurecimento no
uso de TDD, muitos erros são cometidos pelos desen-
volvedores. Mauricio Aniche, numa pesquisa on-line
feita com 218 programadores, identificou diversos
erros que as pessoas cometem ao praticar TDD (ou
tentar praticar TDD). Vejamos alguns deles e como
podemos tentar evitá-los:
Figura 3. Decisões de design feitas no estilo Test-first (TDD). »» Falta de refatoração (no código de produção
e no código de teste) – refatoração contínua é
manifestadas através de código de teste antes que o
passo fundamental para a manutenção do bom
código de produção seja escrito. Essa ideia de escre-
estado do sistema, e isso inclui o próprio có-
ver código como se outro pedaço de código existisse
digo de testes! Depois de obter a barra verde,
também é conhecida como programação por inten-
veja se o código de produção e dos testes está
ção. A figura 3 ilustra esse conceito por meio de um
legível, fácil de entender e manter. Elimine os
exemplo trivial de teste escrito para uma calculadora
maus cheiros encontrados.
financeira. Repare a quantidade de decisões de de-
»» Perda de foco com a refatoração – o outro
sign tomadas apenas para escrever esse simples teste.
extremo é refatorar demais, inclusive outras
Note também que as partes sublinhadas em vermelho
partes do código que não estão diretamente
referem-se a código que ainda não existe (i.e. classes
relacionadas com a funcionalidade sendo de-
Calculadora e CotadorMoeda, método converterPara-
senvolvida no momento. É importante manter
Reais etc.).
o foco e deixar eventuais melhorias em outras
Tudo bem que TDD é uma excelente ferramenta
áreas de código para um momento oportuno.
de design. O que muitos não entendem é que TDD não
»» Escrita de cenários de testes muito complexos
é um substituto para as disciplinas de arquitetura e
– isto pode ser um sinal de que a unidade para
design, como comenta Uncle Bob em seu post “TDD
a qual o teste está sendo escrito provavelmente
Triage” (ver referências). Existem decisões arquite-
está absorvendo muitas responsabilidades. O
turais que precisam ser feitas antes que se comece
recomendável é que o teste foque em apenas
qualquer codificação. Por exemplo, qual linguagem
um aspecto, de forma a gerar código coeso. É
de programação será usada, qual banco de dados
comum novos casos de testes virem à mente à
será usado, como a aplicação será distribuída... Ob-
medida que um teste está sendo escrito. Anote-
viamente, quanto mais essas decisões puderem ser
-os numa lista separada para implementação
adiadas, melhor. Tudo depende do ambiente e da or-
posterior. Comece também pelo teste mais
ganização.
simples, de forma que o código possa evoluir
Em termos de design, continua sendo essencial
aos poucos. Também é importante verificar o
saber criar modelos, conhecer os bons princípios,
valor que cada caso de teste está agregando e
práticas e padrões de projeto. É saudável e bastante
se não estão ocorrendo sobreposições entre
recomendável (eu diria até que é o ponto de parti-
testes (vários testes testando a mesma coisa).
da) discutir soluções com a equipe antes de começar
»» Uso de nomes ruins para os testes – os nomes
a codificar, seja apenas numa conversa informal ou
dos métodos de teste devem descrever correta-
por meio de um esboço de diagrama de classes numa
mente o que o teste faz, não importa o tamanho
folha de papel ou quadro branco... O papel do TDD
do nome necessário para isso. Não se esqueça
será validar a decisão de design já realizada.
de que um dos benefícios dos testes automati-
Esse tipo de abordagem é benéfico e recomen-
zados é o de documentar as APIs do sistema e,
dável, porém, lembre-se que deve ser feita num con-
para isso, bons nomes são fundamentais!
texto iterativo, considerando-se apenas o pedaço de
»» Execução apenas do teste que está atualmente
funcionalidade em questão, com base nos requisitos
falhando – nos diversos ciclos do TDD, muitas
existentes – evitando o BDUF – Big Design Up-front.
vezes é comum a execução apenas da classe de
Estão na moda os termos design emergente e arquite-
teste ou, pior ainda, apenas do teste que está
tura evolucionária, cuja ideia é a de implementar ape-
falhando. Não é raro descobrir mais tarde, ao
nas o que se sabe que será necessário, balanceando a
rodar todos os testes, que outros cenários de
tensão entre as mudanças antecipadas e preparando-
testes deixaram de passar. Lembre-se de execu-
-nos para as mudanças não antecipadas (ver série de
tar todos os testes de unidade frequentemente!
artigos do Neal Ford no developerWorks e a edição 50
Eu diria que outro erro que as pessoas cometem
da MJ sobre Arquitetura Ágil).
bastante é dizer que estão usando TDD só porque es-
tão programando com testes automatizados. É como

/ 10
para saber mais_
caso comparando diferentes projetos open-source,
“Arquitetura Ágil” – MJ50 desenvolvidos com TDD e sem TDD, indicou que
“Cinto de Utilidades: Testes Automatizados” – MJ 47
projetos desenvolvidos com TDD de fato obtiveram
melhor qualidade, traduzida em menor acoplamento,
“Behavior-driven Development em Java na prática, com classes menores e maior testabilidade [5]. No entan-
JBehave” – MJ 44 to, houve um reporte negativo em termos de coesão,
que, como admitem os autores, é uma métrica difícil
“Powermock: Melhorando seu relacionamento com código
de medir. No experimento, eles utilizaram o método
legado” – MJ 43
de Brian-Henderson-Seller conhecido como LCOMS
“A cultura TDD e o BDD” – MJ 43 (Lack of Cohesion of Methods), que é uma das muitas
técnicas cuja ideia é analisar o grau de compartilha-
“Evolução do Design através de Testes e o TDD” – MJ 41
mento de variáveis de instância entre métodos de
“Automatização de testes de persistência com FIT, DBUnit e uma classe (ver referências do artigo para mais de-
HSQLDB” – MJ 38 talhes).

“Testes de Unidade para Camadas de Persistência no


Produtividade
Mundo Real” – MJ 24
Vários estudos não relatam diferenças significa-
“Testes Unitários para Camadas de Negócios no Mundo tivas ou qualquer diferença em termos de produtivi-
Real“ – MJ 23 dade [4, 7, 8], ao passo que outros dizem ter observa-
do alguns desvios.
Boby George e Laurie Williams relatam que ob-
servaram menor produtividade [1]. Os experimentos
alguém disse: “TDD é a prática ágil mais citada, mas que fizeram mostraram que os desenvolvedores que
a menos usada”. usaram TDD levaram 16% mais tempo que os que
não usaram. Apesar disso, os próprios autores afir-
mam que a discrepância em desempenho dos times
Qualidade era grande e o grupo não-TDD praticamente não de-
Vejamos o que alguns estudos falam acerca do
senvolveu nenhum teste automatizado que agregas-
impacto de TDD na qualidade dos sistemas produ-
se valor, o que realmente torna o resultado bastante
zidos. Grosso modo, existem dois eixos de qualidade
questionável. Ademais, os experimentos foram feitos
a serem considerados: a qualidade interna e a qua-
com base em uma aplicação de tamanho pouco sig-
lidade externa. A primeira diz respeito a código em
nificativo (cerca de 200 linhas de código) e com um
si e a última normalmente esta associada à taxa de
grupo relativamente pequeno de desenvolvedores
defeitos encontrados no software. Obviamente, essas
(12 duplas).
duas facetas da qualidade estão inter-relacionadas e
Outros estudos, como o destacado na subseção
são afetadas pelo TDD. No entanto, como já frisamos,
seguinte, relatam aumento de produtividade em
o foco do TDD é em design e, por conseguinte, há uma
comparação com abordagens do tipo test-last. Kau-
maior preocupação com a qualidade interna.
fmann and Janzen observaram um aumento de 50%
Num experimento conduzido em dois diferentes
em produtividade num estudo em meio acadêmico
ambientes da Microsoft, foi observado um aumento
[6].
de qualidade significativo do código (mais que duas
Segundo Hakan Erdogmus, o esforço para codi-
vezes) para projetos desenvolvidos com TDD compa-
ficar os testes é menor quando o código de produção
rados a projetos similares não-TDD (mas com testes
é de natureza mais algorítmica [10] (e.g.: calcular os
feitos depois) [2]. Os autores também relataram 15%
juros compostos de um financiamento até uma data,
de tempo extra up-front para a escrita dos testes. O
ordenar uma lista de coisas segundo algum critério,
mesmo artigo menciona outro paper da IBM relativo
achar o maior elemento de uma lista etc.).Neste tipo
a um estudo realizado por um ano em que se verifica-
de código, uma fração bem maior do tempo é gasta
ram 40% menos defeitos que os encontrados em um
implementando-se a funcionalidade em si (o algorit-
produto similar desenvolvido de uma forma mais tra-
mo) e pouco esforço tende a ser gasto para se escrever
dicional. Segundo eles, a produtividade do time não
os testes (normalmente tem-se uma entrada e uma
foi afetada pela necessidade de escrita dos testes [3].
saída bem definidos, obtidos diretamente da formu-
A maioria dos estudos indica que existe melhoria
lação matemática do problema). Já quando o código
significativa de qualidade em termos de redução do
de produção está centrado em lógica de domínio ou
número de defeitos nos sistemas produzidos [4]. Nos
aspecto de negócio, o esforço despendido nos testes
estudos realizados, chegou-se a verificar uma redu-
tende a ser maior, algumas vezes inclusive superior
ção de bugs de 40 a 50%.
ao esforço para se implementar a funcionalidade
Em termos de qualidade interna, um estudo de

11 \
(existe mais refatoração envolvida também). Em outras palavras, consegue-se um ciclo sustentável
Na minha experiência, normalmente se gasta um de desenvolvimento.
tempo grande para criar a infraestrutura básica para
escrever os primeiros testes. Uma vez estabelecida Test-first vs. Test-last
essa infraestrutura, o tempo necessário para criar no- Analisemos agora mais de perto as diferenças en-
vos casos de testes do mesmo tipo tende a ser menor. tre as abordagens test-first (teste antes da implemen-
Alguns chamam essa prática de “Arquitetura de Tes- tação, como dita o TDD) e test-last (escrever os testes
tes”, cuja ideia é justamente investir um tempo inicial depois da implementação).
definindo como o teste de cada componente da arqui- Erdogmus, Morisio e Torchiano resolveram in-
tetura deverá ser realizado. Isso facilita a criação de vestigar, por meio de um experimento descrito no pa-
novos testes, principalmente para os que ainda não per “On the Effectiveness of the Test-First Approach to
sabem criar testes ou possuem pouca experiência. Programming” [9,] as diferenças entre as abordagens
Steve Freeman e Nat Pryce recomendam que sejam test-first (teste antes da implementação, como dita
escritos testes para um “walking skeleton” (esqueleto o TDD) e test-last (escrever os testes depois da im-
ambulante) – uma implementação básica grosseira da plementação). O experimento foi realizado com dois
arquitetura do sistema. Esta técnica pode ser útil no grupos em meio acadêmico, cada qual usando uma
início do projeto tanto para a realização das macro- das duas abordagens (test-first e test-last). As con-
-decisões de arquitetura quanto para a definição de clusões foram as seguintes: o grupo test-first acabou
uma boa infraestrutura de testes. escrevendo 52% mais testes do que o grupo test-last,
Voltando ao TDD, é oportuno um comentário a algo bastante significativo. Em termos de qualidade
respeito do tema produtividade. Nesses estudos, nor- externa, pelo estudo, não pareceu haver diferenças
malmente se comparam grupos que usaram TDD com significativas entre as duas abordagens.
grupos que deixaram os testes automatizados para o Na verdade, houve evidências de que a qualidade
final do desenvolvimento (test-last). Agora, quando se externa estaria mais relacionada ao número de testes
compara o esforço de desenvolvimento de uma fun- escritos do que quando estes são escritos. Segundo os
cionalidade com teste automatizado (seja test-first ou autores, apesar de a abordagem test-first por si só não
test-last) com a mesma funcionalidade sem qualquer aumentar a qualidade (em comparação com a abor-
teste automatizado, num curto prazo, o tempo de de- dagem test-last), esta pareceu ter um efeito positivo
senvolvimento da equipe que faz testes normalmente sobre a produtividade dos desenvolvedores, possivel-
é maior. Isto é, ocorre uma aparente “queda” na pro- mente por causa dos seguintes fatores:
dutividade. Num longo prazo, porém, esse esforço é »» Melhor compreensão do problema. Especificar
compensado devido à qualidade do código produzi- o teste antes força o desenvolvedor a refletir
do com testes e a boa suíte de testes de regressão, de maneira mais profunda e completa sobre o
os quais fazem com que o desenvolvimento das pró- problema a ser resolvido. Criar cenários de tes-
ximas funcionalidades ocorra de maneira facilitada. tes antes ajuda a “provar” a robustez da solução

referências_
Papers referenciados no artigo Kaufmann and Janzen

[1] – “An Initial Investigation of Test-Driven Development in [7] - “Towards Empirical Evaluation of Test-Driven Development in a
Industry” – Boby George e Laurie Williams University Environment” - Pancur et. al.

[2] – “Evaluating the efficacy of Test-Driven Development: Industrial [8] – “An empirical evaluation of the impact of Test-Driven
Case Studies” – Thirumalesh Bhat e Nachiappan Nagappan Development on software quality” – David Janzen

[3] – “Test-Driven Development as a Defect-Reduction Practice” - [9] – “On the Effectiveness of the Test-First Approach to
Laurie Williams, E. Michael Maximilien e Mladen Vouk Programming” - H. Erdogmus, M. Morisio, and M. Torchiano

[4] – “Test-Driven Development – Empirical Body of Evidence” – [10] – “An Overview of Test-Driven Development” - H. Erdogmus
Maria Siniaalto
[11] – “Iterative and Incremental Development: A Brief History” -
[5] – “Does Test-Driven Development really improve software design Craig Larman, Victor R. Basili.
quality?” – David Janzen e Hossein Saiedian
Outras referências
[6] - “Implications of test-driven development: a pilot study” -
“Test-driven – Practical TDD and Acceptance TDD for Java

/ 12
proposta. cabilidade limitada, pois muitos deles foram reali-
»» Melhor foco na tarefa a ser feita. Existe uma zados apenas em meio acadêmico (que obviamente
menor carga cognitiva sobre o desenvolvedor, é bastante diferente da indústria), com desenvolve-
pois ele estará concentrado em resolver apenas dores com diferentes perfis e projetos de naturezas
uma pequena porção do problema, somente diferentes. Por essas questões, é bastante difícil obter
o suficiente para atender o teste existente fa- conclusões mais concretas por meio de experimentos
lhando. comparativos. Afinal de contas, vale a pena usar TDD
»» Aprendizado mais rápido. O desenvolvedor ou uma abordagem test-last é suficiente?
saberá mais rapidamente se a funcionalidade É perfeitamente possível escrever código desa-
implementada está de acordo com o esperado. coplado apenas pensando na testabilidade. Com o
Além disso, existe um critério inequívoco para tempo, é possível fazer isso suficientemente bem,
saber quando o trecho de funcionalidade está basicamente empregando o padrão de injeção de de-
realmente pronto. pendências, em sistemas orientados a objeto. Nor-
»» Menos esforço de retrabalho. Numa abordagem malmente, não há maiores dificuldades para se es-
test-last, corre-se o risco de “ir com muita sede crever os testes imediatamente depois (note o uso
ao pote” e implementar de uma vez a funcio- da palavra “imediatamente”). Em outros tipos de
nalidade, incorrendo em retrabalho à medida ambientes onde o desenvolvedor esteja menos fami-
que os testes forem criados posteriormente e liarizado, o recomendável é que o teste seja escrito
apontarem outros problemas. antes, pois a refatoração posterior poderá ser muito
O que o estudo mostrou é que o TDD acaba por custosa ou inviável.
encorajar a escrita de um número maior de testes Os problemas da abordagem test-last são diver-
e, se a qualidade externa pode ser influenciada pela sos: primeiro, perde-se o benefício da programação
quantidade de testes, então, em última análise, o por intenção, ou seja, evoluir o software a partir do
TDD também desencadearia um aumento da quali- ponto de vista de como se espera que seja usado. Se-
dade. Seria interessante vermos novos estudos que gundo, corre-se o risco de over-engineering, isto é, es-
pudessem consubstanciar esse fato. crever código para coisas que talvez não sejam neces-
sárias. Terceiro, corre-se o risco de que simplesmente
Afinal de contas, vale a pena ou não os testes não sejam escritos, afinal, o código já está
pronto e aparentemente funciona bem (como ocorreu
usar TDD? em um dos estudos que referenciamos). Por último, o
Neste ponto, o leitor deve estar um pouco con-
número de testes tende a ser menor (como mostra-
fuso, pois os diversos estudos parecem obter resulta-
ram alguns estudos) e, consequentemente, a cober-
dos contraditórios, principalmente quanto à questão
tura dos testes tende a ser menor (numa abordagem
qualidade/produtividade com e sem o uso de TDD.
test-last, é fundamental utilizar uma ferramenta de
Bom, sabemos que todos esses estudos possuem apli-
cobertura, como o EclEmma ou o Cobertura, para

Developers” – Lasse Koskela - http://blog.objectmentor.com/articles/2009/10/06/echoes-from-the-


stone-age
“Growing Object-Oriented Software, Guided by Tests” – Steve
Freeman, Nat Pryce - http://blog.objectmentor.com/articles/2009/10/08/tdd-triage

“Test-driven Development: By Example” – Kent Beck - http://codebetter.com/darrellnorton/2004/05/10/notes-from-test-


driven-development-by-example-kent-beck/
- “Pragmatic Unit Testing in Java with JUnit” – Andy Hunt e Dave
Thomas - http://blog.jonasbandi.net/2010/02/agile-testing-quadrants.html

- “Agile Testing” – Lisa Crispin and Janet Gregory - http://haacked.com/archive/2008/01/22/research-supports-the-


effectiveness-of-tdd.aspx
- “Extreme Programming” – Vinicius Teles
- http://gsd.ime.usp.br/seminars/2010/presentation_mauricio.pdf
- http://www.ebah.com.br/content/ABAAABNfUAG/conceitos-
beneficios-tdd - http://evidencebasedse.com/?q=node/90

- Chaplin, D. “Test first programming”, TechZone, 2001. - http://www.infoq.com/news/2009/03/TDD-Improves-Quality

- http://alistair.cockburn.us/Walking+skeleton - http://www.ibm.com/developerworks/java/library/j-eaed1/index.
html
- http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd

13 \
Considerações finais
A motivação para este artigo veio de uma palestra
a que assisti em 2009 intitulada “Test-Driven Develo-
pment: Overview and Empirical Results” (“TDD: Visão
geral e resultados empíricos”), apresentada pelo Dr.
Hakan Erdogmus, editor-chefe da IEEE Software, que
na ocasião estava visitando a UFRJ. Segundo ele, a
efetividade do TDD não é comprovada, porém, exis-
tem evidências da sua efetividade, apesar de ainda
Figura 4. Números da pesquisa qualitativa em formato gráfico.
não haver nada definitivo em termos da análise qua-
lidade/produtividade. Para ele, o próprio nome TDD
não teria sido uma boa escolha. Em suas palavras:
“TDD incorpora e mistura atividades associadas tra-
identificar quais partes significativas do código pro- dicionalmente com diferentes ‘fases’: requisitos, design,
duzido não possuem testes). implementação, documentação e testes”.
O tamanho dos passos no TDD também é um as- Em termos subjetivos, porém, normalmente os
pecto que pode ser decidido pelo desenvolvedor. O que aplicam TDD (ou dizem aplicar) possuem uma
que se recomenda é que sejam utilizados pequenos percepção positiva. Numa pesquisa realizada com 24
passos (baby-steps). Por exemplo, no primeiro passo desenvolvedores profissionais, em média, 80% afir-
após o teste, que consiste em aplicar a implementa- maram que consideram TDD uma abordagem eficaz
ção mais simples para que o teste passe, muitos usam e 78% acreditam que haja melhora em produtividade.
a técnica da falsificação (“fake it”), retornando um 87,5% declaram que TDD contribui para um melhor
valor hard-coded e, em seguida, acrescentam mais entendimento dos requisitos e 95,8% dizem que TDD
um teste que force à generalização da implementa- reduz o esforço em debugging. Apesar disso, 56% dos
ção. Essa é uma abordagem de baby-steps, mas nada desenvolvedores consideram difícil pensar “do jeito
impede que o desenvolvedor codifique de uma vez a TDD” [1]. A figura 4 exibe os resultados da pesquisa
funcionalidade para que o teste passe. em formato gráfico.
Acredito que seja possível utilizar de maneira É fato que o TDD exige uma mudança de paradig-
eficaz uma abordagem híbrida, não sendo tão radical ma bastante radical ao que tradicionalmente fomos
em aplicar estritamente as “três leis do TDD” men- condicionados. Fomos educados a desenvolver sof-
cionadas no início. O próprio Uncle Bob afirma que tware com o pensamento design-codificação-testes.
TDD nem sempre é apropriado e existem situações Mas o TDD inverte esse ciclo para testes-codificação-
nas quais ele quebra a disciplina e escreve código an- -design. Não é fácil aprender a pensar com base nessa
tes dos testes (apesar de serem poucas as vezes). Ou- outra perspectiva, mas acredito que valha a pena ex-
tro exemplo de variação que alguns desenvolvedores perimentar. E como alguém disse: “se você não con-
adotam consiste em, dependendo da funcionalidade, segue escrever teste para o que você está prestes a
escrever mais de um teste (dois ou três) que falhe codificar, então você nem deveria estar pensando em
antes de realizar a implementação. A questão é que codificar!”.
o benefício maior está em haver uma alternância entre Para concluir, reitero a importância da criação
código de testes e código de produção, não importando dos testes automatizados, preferencialmente de ma-
tanto a ordem. neira intercalada com o código de produção sendo
Como com qualquer metodologia, prática ou tec- desenvolvido (seja de forma TDD ou não-TDD). Sof-
nologia, é importante o conhecimento e a aplicação de tware é feito para mudar (o lema do XP é o de “abra-
maneira contextual, entendendo os reais benefícios e çar a mudança”, lembra-se?) e, para isso, é de suma
realizando as adaptações que se fizerem necessárias. importância a existência de um bom conjunto de tes-
Note que mencionei a questão do conhecimento. Mui- tes automatizados. Aprenda as técnicas e ferramen-
tos consideram que é custoso ou inviável usar TDD tas relacionadas a testes. Experimente o TDD. Adapte
ou testes automatizados, simplesmente porque não e use o que funcionar melhor para você, mas busque
tomaram o tempo necessário para estudar e aprender conhecer a fundo a técnica e os princípios que a mo-
as técnicas e ferramentas necessárias e aplicá-las de tivam e suportam.
maneira efetiva (sobre esse tema, recomendo meu ar- Não tenha tanta confiança assim no seu código.
tigo “Cinto de Utilidades: Testes Automatizados”, na Prove que funciona!
MJ 47). Como curiosidade, vale a observação de que a “O crisol prova a prata, e o forno, o ouro; mas aos
filosofia por trás do TDD não é nova. Seu uso esteve corações prova o Senhor.” (Pv 17:3)
presente no projeto Mercury da NASA, de 1960! [11]

/ 14

Você também pode gostar