Para usar Python e TDD (Test-Driven Development) de forma eficiente, você deve seguir um ciclo contínuo conhecido como Red, Green, Refactor (Vermelho, Verde, Refatorar). Em vez de escrever o código e depois testar, você inverte o processo: escreve o teste primeiro para identificar o que sua aplicação deveria fazer, vê o teste falhar e, então, escreve o código para corrigir essa falha.
Abaixo, apresentamos o passo a passo prático de como aplicar o TDD para identificar, corrigir erros e evoluir uma aplicação Python utilizando a biblioteca nativa unittest.
🔄 O Ciclo TDD: Red, Green, Refactor
- RED (Falhar) → Escreva um teste que falha porque a funcionalidade não existe.
- GREEN (Passar) → Escreva o código mínimo necessário para o teste passar.
- REFACTOR (Melhor) → Limpe o código, remova duplicidades e melhore o design.
💻 Exemplo Prático: Criando uma Calculadora de Descontos
Imagine que precisamos criar uma função que calcula descontos para um e-commerce. Se o valor for acima de R$ 100, damos 10% de desconto. Se for menor, nenhum desconto é aplicado.
Passo 1: Escrever o Teste Primeiro (Red 🔴)
Crie um arquivo chamado test_calculadora.py. Como a função calcular_desconto ainda não existe, o teste vai falhar imediatamente.
import unittest
# Importamos a função que ainda vamos criar
from calculadora import calcular_desconto
class TestCalculadoraDesconto(unittest.TestCase):
def test_desconto_para_valores_acima_de_cem(self):
# Cenário: Valor de R$ 150 deve ter 10% de desconto (R$ 15)
resultado = calcular_desconto(150)
self.assertEqual(resultado, 15)
def test_sem_desconto_para_valores_baixos(self):
# Cenário: Valor de R$ 80 não deve ter desconto (R$ 0)
resultado = calcular_desconto(80)
self.assertEqual(resultado, 0)
if __name__ == '__main__':
unittest.main()Use o código com cuidado. Ao executar python test_calculadora.py, você verá um erro (ModuleNotFoundError ou ImportError). O teste falhou com sucesso! Você identificou o primeiro “erro”: a ausência do código.
Passo 2: Escrever o Código Mínimo (Green 🟢)
Crie o arquivo calculadora.py e escreva apenas o código necessário para fazer o teste passar. Não tente criar o código perfeito agora.
def calcular_desconto(valor):
if valor > 100:
return valor * 0.1
return 0Use o código com cuidado. Execute o teste novamente: python test_calculadora.py. Agora ele passará com sucesso. O comportamento esperado foi validado.
Passo 3: Refatorar (Refactor 🔵)
Se o código estiver confuso ou com números mágicos, limpe-o. Como os testes estão criados, você pode alterar o código com segurança. Se você quebrar algo, o teste avisará.
# Versão refatorada e mais limpa
LIMITE_DESCONTO = 100
PERCENTUAL_DESCONTO = 0.1
def calcular_desconto(valor):
if valor > LIMITE_DESCONTO:
return valor * PERCENTUAL_DESCONTO
return 0Use o código com cuidado.
🔍 Como o TDD Ajuda a Identificar e Corrigir Erros (Bugs)
Quando um bug é reportado em produção (ex: “A calculadora está aceitando valores negativos e dando desconto negativo!”), o processo de correção usando TDD segue uma lógica muito clara:
- Não mexa no código da aplicação ainda.
- Escreva um teste que reproduza exatamente o bug. Esse teste vai falhar (Red), provando que o erro existe.
- Corrija o código da aplicação até que o novo teste passe (Green).
- Garante que nada mais quebrou: Todos os outros testes antigos devem continuar passando.
Exemplo de correção de bug
Adicione o teste do bug no seu arquivo test_calculadora.py:
def test_valor_negativo_deve_retornar_erro(self):
# Valores negativos devem levantar um erro de valor (ValueError)
with self.assertRaises(ValueError):
calcular_desconto(-50)Use o código com cuidado. Ao rodar, o teste falha porque a função aceita o valor negativo. Agora você corrige a aplicação no calculadora.py:
def calcular_desconto(valor):
if valor < 0:
raise ValueError("O valor não pode ser negativo.")
if valor > LIMITE_DESCONTO:
return valor * PERCENTUAL_DESCONTO
return 0Use o código com cuidado. Rode os testes. O bug foi corrigido, e você tem certeza de que o resto da aplicação continua funcionando.
🛠️ Principais Ferramentas e Práticas para Python
- Pytest: Embora
unittestvenha nativo no Python, o Pytest é a ferramenta mais utilizada no mercado. Ele torna a escrita de testes muito mais simples, rápida e legível (substitui osself.assert...porassertpuros do Python). - Foque em Testes Unitários: Teste pequenas partes isoladas (funções, métodos) para que seja fácil descobrir exatamente onde o erro está quando um teste falhar.
- Mantenha os testes rápidos: O ciclo TDD exige que você rode os testes a cada poucos minutos. Se eles demorarem para rodar, você perderá o hábito de usá-los.
Para te ajudar a aplicar isso no seu cenário real, me conte:
- Você já tem uma aplicação existente ou está começando um projeto do zero?
- Qual é o tipo de aplicação? (Web/API, automação de scripts, análise de dados?)
- Prefere que eu mostre como configurar o Pytest, que é o padrão de mercado mais moderno?