O ATDD inverte a ordem usual: o QA escreve um teste de aceitação no Playwright antes de a feature existir. O teste falha e a feature está pronta quando passa. Essa única mudança move o QA de verificar trabalho finalizado para definir o que "pronto" significa.
O ciclo TDD: Red, Green, Refactor
O TDD segue um ciclo estrito de três etapas:
1. Red — escreva um teste que falha (porque a feature ainda não existe)
2. Green — escreva o código mínimo para fazer o teste passar
3. Refactor — limpe o código mantendo os testes verdes
Esse ciclo se repete para cada pequeno pedaço de funcionalidade.
// Fase Red: escrever um teste que falha
test('calculateDiscount aplica 10% para o código SAVE10', () => {
const result = calculateDiscount(100, 'SAVE10');
expect(result).toBe(90);
});
// Rodar esse teste falha: calculateDiscount não está definida// Fase Green: escrever código mínimo para passar
function calculateDiscount(price: number, code: string): number {
if (code === 'SAVE10') {
return price * 0.9;
}
return price;
}
// Agora o teste passa// Fase Refactor: limpar sem quebrar o teste
const DISCOUNT_CODES: Record<string, number> = {
SAVE10: 0.1,
SAVE20: 0.2,
SAVE50: 0.5,
};
function calculateDiscount(price: number, code: string): number {
const discount = DISCOUNT_CODES[code] || 0;
return price * (1 - discount);
}
// Os testes ainda passam: a refatoração não quebrou nadaBenefícios do TDD que afetam o QA
Código naturalmente testável:Código escrito com TDD tende a ter funções menores com inputs e outputs claros, mais fáceis de testar em todos os níveis.
Segurança contra regressão:Todo comportamento está protegido por um teste. Quando o QA encontra um bug, os desenvolvedores podem reproduzi-lo com um teste, corrigir e o teste previne a regressão.
Documentação pelos testes:Os testes TDD descrevem o que o código deve fazer em cenários específicos. O QA pode ler os testes para entender o comportamento esperado.
Detecção de bugs mais cedo:Problemas detectados ao escrever testes unitários são ordens de magnitude mais baratos de corrigir do que problemas encontrados em QA ou em produção.
Behavior-Driven Development (BDD)
BDD estende o TDD em direção à camada de negócio. Onde TDD foca em como o código funciona, BDD foca em qual comportamento é necessário.
Os três amigos: desenvolvedor, QA e product manager colaboram para definir o comportamento usando o formato Given/When/Then antes de escrever qualquer código.
Feature: Códigos de desconto
Scenario: Código de desconto válido reduz o preço
Given eu tenho um carrinho com itens totalizando R$100
When aplico o código de desconto "SAVE10"
Then o total deve ser R$90
And o valor do desconto deve ser R$10
Scenario: Código de desconto inválido mostra erro
Given eu tenho um carrinho com itens totalizando R$100
When aplico o código de desconto "INVALIDO"
Then devo ver "Código de desconto inválido"
And o total deve permanecer R$100
Scenario: Código de desconto expirado mostra erro
Given eu tenho um carrinho com itens totalizando R$100
When aplico o código de desconto "EXPIRADO20"
Then devo ver "Este código de desconto expirou"Como o QA pode aplicar a mentalidade TDD
Mesmo que você não esteja escrevendo testes unitários, pode aplicar a mentalidade TDD.
Escreva casos de teste antes de os testes manuais começarem
Em vez de testes exploratórios do zero, escreva os comportamentos esperados primeiro:
Feature: Reset de Senha
O que eu espero que seja verdade:
1. Digitar um email válido envia um email de reset em até 2 minutos
2. Digitar um email inválido mostra "Email não encontrado"
3. O link de reset expira após 24 horas
4. Usar um link expirado mostra "Link expirado" com opção de solicitar um novo
5. Após o reset bem-sucedido, a senha antiga não funciona mais
6. O link de reset só pode ser usado uma vezAgora você tem um plano de teste antes de começar a testar.
Desenvolvimento Orientado a Testes de Aceitação (ATDD)
Colabore com os desenvolvedores para escrever testes de aceitação antes de a feature ser construída:
// Escrito antes de a feature existir
test('checkout com cartão válido conclui a compra', async ({ page }) => {
// Configuração: usuário com itens no carrinho
// ...
// Executar checkout
await page.fill('[data-testid="card-number"]', '4242 4242 4242 4242');
await page.fill('[data-testid="card-expiry"]', '12/28');
await page.fill('[data-testid="card-cvc"]', '123');
await page.click('[data-testid="pay-now"]');
// Resultados esperados
await expect(page).toHaveURL('/order-confirmation');
await expect(page.getByTestId('order-number')).toBeVisible();
await expect(page.getByTestId('success-message')).toContainText('Pagamento realizado com sucesso');
});Esses testes falham até a feature ser construída. Quando passam, a feature está pronta.
Quando os desenvolvedores praticam TDD: o que o QA precisa saber
O que muda para o QA
Cobertura de testes unitários já existe:Os desenvolvedores já testaram casos extremos no nível do código. O QA pode focar em pontos de integração, fluxos de usuário e lógica de negócio, não em comportamento básico de funções.
Falhas de testes são significativas:Quando o CI de um time TDD quebra, é específico: "a função X retorna valor errado para o caso extremo Y," não "o app está quebrado em algum lugar."
Refatoração é mais segura:Com testes unitários abrangentes, o QA não precisa retestar funcionalidades básicas após refatoração: os testes já cobrem isso.
O que o QA ainda precisa fazer
Testes de integração:Testes unitários testam funções em isolamento. O QA testa como os componentes funcionam juntos: o banco de dados, a API, o frontend, o sistema de email.
Testes do ponto de vista do usuário:Desenvolvedores testam "o código funciona?" O QA testa "a feature faz sentido para usar?"
Descoberta de casos extremos:Testes exploratórios de QA encontram cenários que não foram especificados. TDD só cobre o que foi pensado ao escrever os testes.
Performance e confiabilidade:TDD não cobre tempos de resposta, usuários simultâneos ou o que acontece sob carga.
TDD prático para automação de testes
Ao construir seu framework de testes, aplique princípios TDD:
// Em vez de escrever o helper completo primeiro, escreva um teste para o que você quer que ele faça
test('helper de login deve redirecionar para o dashboard após login', async ({ page }) => {
await loginAs(page, 'member'); // Esta função ainda não existe
await expect(page).toHaveURL('/dashboard');
});
// Agora escreva a implementação mínima
async function loginAs(page: Page, role: 'admin' | 'member') {
const credentials = {
admin: { email: 'admin@test.com', password: 'AdminPass1' },
member: { email: 'member@test.com', password: 'MemberPass1' },
};
await page.goto('/login');
await page.fill('[data-testid="email"]', credentials[role].email);
await page.fill('[data-testid="password"]', credentials[role].password);
await page.click('[data-testid="submit"]');
await page.waitForURL('/dashboard');
}Isso previne over-engineering. Você constrói exatamente o que é necessário, e o teste confirma que funciona.
A pirâmide de testes no contexto TDD
TDD molda diretamente a pirâmide de testes:
/\
/E2E\ ← Automação QA (menos, mais lentos)
/------\
/ Integr.\ ← Testes de integração (moderados)
/----------\
/ Unit Tests \ ← Output do TDD (muitos, rápidos)
/--------------\TDD produz a base ampla de testes unitários. O QA constrói as camadas de integração e E2E em cima. Juntos formam uma pirâmide onde a maioria dos bugs é capturada barato no nível unitário, com um conjunto menor e focado de testes E2E mais caros.
Resumo
- Ciclo TDD: Red (teste que falha) → Green (fazer passar) → Refactor (limpar)
- TDD produz código naturalmente testável e bem estruturado
- BDD estende TDD em direção ao comportamento de negócio com cenários Given/When/Then
- ATDD: o QA escreve testes de aceitação antes do desenvolvimento começar; os testes falham até a feature ser construída
- Quando os desenvolvedores praticam TDD, o QA muda o foco para integração, fluxos de usuário e casos extremos
- Aplique a mentalidade TDD à automação de testes: escreva a interface de teste primeiro, depois implemente
TDD e QA são complementares, não concorrentes. TDD captura bugs no nível unitário cedo. O QA captura problemas de integração e experiência do usuário. Juntos produzem software que funciona corretamente em todos os níveis.
→ Veja também: Desenvolvimento Orientado a Testes: O Guia do Engenheiro QA | Testes Shift-Left: O que Significa e Como Praticar | A Pirâmide de Testes Explicada para Engenheiros QA