Fluxo TDD

TDD – Test-Driven Development – Guia Rápido

O tempo passa, a tecnologia evolui, mas continuamos insistindo nos mesmos erros, reinventando a roda, etc. E por isso devemos falar sobre algo muito importante chamado TDD (Test-Driven Development) – ou num português claro e objetivo, Desenvolvimento Guiado por Testes.

TDD significa escrever os testes antes do código produtivo – em ciclos curtos e contínuos – reforçando o design, o desacoplamento e a eficácia em resolver os problemas que motivaram sua escrita.

Embora o TDD seja uma disciplina amplamente conhecida, dúvidas e questionamentos surgem durante o processo (aprendizado/execução), deixando o programador confuso e com receios de adotar a prática, tais como:

  • Como eu vou conseguir escrever teste para um código que nem existe!?
  • Não faço TDD porque demora mais do que desenvolver sem testes
  • Não preciso escrever testes pro meu código, pois sou um programador experiente
  • Sempre faço TDD, primeiro escrevo o código e depois os testes.

TDD não é Teste Unitário

Embora esses temas estejam ligados por um cordão umbilical, Teste Unitário é ferramenta, e TDD é técnica. Você pode escrever testes unitários sem fazer TDD, como Testes de Regressão (Regression Tests¹), ou Testes de Aprendizado (Learning Tests¹) por exemplo.

TDD é profissionalismo na mais pura essência

“Não acho que cirurgiões deveriam defender o fato de lavar as mãos, e não acho que programadores deveriam defender TDD.²”

Nós programadores temos obrigação em escrever testes, pois somente assim podemos ter maiores índices de acerto sobre a eficácia do código que escrevemos:

“Como você pode se considerar um profissional se você não sabe se todo o seu código funciona?²”.

Embora agressiva, a citação acima se resume num primordial princípio profissional, pois centenas de milhões da moeda à sua escolha (US$, R$, €, etc.) são gastos em projetos de reescrita de software todos os anos – de fato, código nasceu para ser reescrito, mas não ao pé-da-letra.

TDD deixa o programador mais corajoso

Código nasceu para ser reescrito: refatoração, mudança de tecnologias, melhorias, novas features e o que mais aparecer.

Se você escreve testes para o seu código, existe uma chance de seus cabelos brancos serem oriundos de causas naturais, não de estresse. Afinal de contas trabalhamos com código em produção, e cada deploy é um frio na barriga se não conhecermos todo o código-fonte ali presente.

Mas será que isso é humanamente possível? Conhecer cada detalhe de uma aplicação? Cada gambiarra solução alternativa e seus comportamentos que mais se parecem com um capítulo da Teoria do Caos? Então, não.

Testes unitários são documentos sobre as classes, módulos e funções, então quando um programador escreve testes para o código, está externalizando os objetivos deste, e para cada dúvida que surge, um novo caso de teste é escrito.

“Desenvolvimento Guiado por testes é uma forma de administrar o medo durante a programação.¹”

Encontrou um bug? Escreva um teste!¹

Quando um bug surge ele explicita a falta de um cenário na sua suíte de testes, logo, a forma mais fácil de resolvê-lo é criar um caso de teste e aplicar as modificações necessárias, garantindo que este bug fique no passado.

Mas e quanto aos cabelos brancos? E se o código recém alterado não possuía cobertura de testes? Como garantir seu pleno funcionamento? Será que ele foi transformado numa ferramenta que resolve somente um problema específico, e não mais o que já resolvia antes?

Mas suponhamos que a funcionalidade a quem o bug pertence já estivesse sendo razoavelmente coberta de testes, logo o novo caso de teste escrito por você virá a falhar, e as modificações necessárias serão feitas para que este teste passe, e que os testes pré-existentes não quebrem (a não ser que fossem testes ruins, e o algoritmo de fato nunca funcionou conforme o necessário). O resultado será uma funcionalidade com uma maior cobertura de testes, reduzindo o índice de falhas e permitindo que seu backlog deixe de ver o bug antes mesmo de dizer adeus.

Cobertura de Testes

Cobertura de Testes nada mais é do que o percentual de linhas de código que a sua suíte de testes cobre, portanto quanto maior for sua cobertura de testes, menores serão as suas dores de cabeça.

Código testado é código saudável, e não necessariamente os bugs não existem, mas com o passar do tempo você aumentará o Tempo Médio Entre Falhas¹ – em inglês MTBF, ou Mean Time Between Failures – utilizada para medir a confiabilidade, e perguntemos: De quanto em quanto tempo seu software falha? Quanto maior o MTBF, melhor.

Refatoração

Refatoração (ou Refactoring) é a prática de melhorar um código-fonte que (supostamente) já funciona, alterando sua estrutura, diminuindo linhas de código, aprimorando performance, legibilidade, entre outras coisas. E refatorar fica mais fácil quando o seu código tem cobertura de testes, pois módulos inteiros serão aprimorados com baixos índices de falha.

Vermelho, Verde, Refatore¹

Este é o mantra do TDD, pois é o padrão de ciclos simples, rápidos e eficazes nas suas contribuições – Verdadeiramente rápidos, podendo variar de 30 segundos a poucos minutos.

Fluxo TDD
Fluxo TDD
  1. Vermelho: Escreva um teste que não funciona, e talvez nem compile
  2. Verde: Faça rapidamente o teste funcionar
  3. Refatore: Elimine as duplicatas feitas para o teste funcionar.

Pode se dizer que a seguinte citação se encaixa feito uma luva ao ciclo padrão do TDD:

“First do it, then do it right, then do it better” (4)

Primeiro faça: escreva o teste que falha, e veja a barra vermelha na execução deste.
Então faça correto: faça-o passar, e veja a barra verde ao executá-lo.
Então faça melhor: Refatore.

Triangulação¹

Triangulação é uma prática do TDD explicada através da analogia da triangulação de radares – Onde dois ou mais radares apontam para o mesmo alvo, e cálculos contendo as distâncias entre os radares e o alvo podem resultar na distância real do alvo.

TDD e Triangulação: A e B são os radares, ★ é o alvo e D é a distância perpendicular entre os radares e o alvo
Triangulação: A e B são os radares, ★ é o alvo e D é a distância perpendicular entre os radares e o alvo – Fonte: Nasa

Mas o que triangulação tem em comum com TDD?

Digamos que A e B sejam casos de teste e ★ seja o objetivo final que é uma função que soma dois números inteiros. Esta receberá dois argumentos (os somandos), e seu retorno será o resultado da soma. Ao triangular, A e B terão algo em comum: testar a mesma funcionalidade -> D.

Lista de tarefas¹

O TDD será muito mais difícil sem uma lista de tarefas, pois antes de começar a escrever os testes devemos prever e listar algumas tarefas que nos ajudarão a caminhar rumo ao nosso objetivo. Entretanto, durante o desenvolvimento ficaremos presos (stuck) – e impedidos de fazer ciclos “Vermelho, Verde, Refatore” – estes sintomas nos mostram que conseguiremos seguir adiante ao prever e adicionar novas tarefas na nossa lista.

Acabou o expediente e a funcionalidade ainda não foi concluída? Não se preocupe, pois na manhã seguinte você verá as tarefas que ainda não foram executadas, e logo retomará ao raciocínio sem dificuldade.

Conclusão

Enfim, TDD é um dos caminhos que pode nos levar a ter uma vida profissional mais simples e tranquila – pois nossa produtividade aumenta e a qualidade do que fazemos também. Além de nos depararmos com grandes realizações como times Test Infected³ e projetos que proporcionam rápida adaptação aos novos integrantes do time – causadas por amenas curvas de aprendizado.

 

Bibliografia:
¹ Beck, Kent – Test-Driven Development By Example
² Martin, Robert C. – Clean Coder – A Code Of Conduct For Professional Programmers
³ Gamma, Erich
4 Osmani, Addy

 

 

Wellington Moreira

1 comment

Deixe uma resposta

Your Header Sidebar area is currently empty. Hurry up and add some widgets.

%d blogueiros gostam disto: