O Que é BDD?
Behavior-Driven Development (BDD) é uma evolução do TDD que foca na colaboração entre desenvolvedores, QA e negócios. BDD usa linguagem natural (Gherkin) para descrever comportamentos de software, tornando requisitos mais acessíveis a todos.
A História do BDD
2003: Dan North cria "JBehave" (Java)
2006: Ruby implementation "Cucumber" (Aslak Hellesøy)
2008: GoBehave para Python
2012: Cucumber-JVM
Hoje: Gherkin é padrão indústria
Gherkin: A Linguagem de BDD
Estrutura Básica
# language: pt
Funcionalidade: Título da funcionalidade
Como um [ator]
Quero [ação]
Para [benefício]
Contexto: [precondições]
Dado [estado inicial]
E [mais estados]
Cenário: [nome do cenário]
Quando [ação]
E [mais ações]
Então [resultado esperado]
E [mais resultados]
Cenário: [outro cenário]
...
Palavras-Chave Gherkin
| Keyword | Uso |
|---|---|
Funcionalidade (Feature) |
Agrupa cenários relacionados |
Contexto (Background) |
Precondições comuns |
Cenário (Scenario) |
Caso de uso específico |
Dado (Given) |
Pré-condições |
Quando (When) |
Ação/evento |
Então (Then) |
Resultado esperado |
E (And) |
Conjunção |
Mas (But) |
Conjunção negativa |
Esquema do Cenário |
Cenário parametrizado |
Exemplos (Examples) |
Dados de teste |
Exemplo Completo
# language: pt
Funcionalidade: Login de Usuário
Como um usuário registrado no sistema
Quero fazer login com minhas credenciais
Para acessar minha conta e visualizar meus dados
Contexto:
Dado que o sistema está operacional
E o usuário "joao@exemplo.com" está cadastrado com senha "Senha@123"
Cenário: Login com credenciais válidas
Quando eu acesso a página de login
E preencho o campo email com "joao@exemplo.com"
E preencho o campo senha com "Senha@123"
E clico no botão "Entrar"
Então sou redirecionado para o dashboard
E uma mensagem de boas-vindas é exibida
E meu nome "João Silva" aparece no cabeçalho
Cenário: Login com senha incorreta
Quando eu acesso a página de login
E preencho o campo email com "joao@exemplo.com"
E preencho o campo senha com "senhaerrada"
E clico no botão "Entrar"
Então permaneço na página de login
E uma mensagem de erro "Credenciais inválidas" é exibida
E o campo senha está vazio para nova tentativa
Cenário: Login com email não cadastrado
Quando eu acesso a página de login
E preencho o campo email com "naoexiste@exemplo.com"
E preencho o campo senha com "senha123"
E clico no botão "Entrar"
Então uma mensagem de erro "Usuário não encontrado" é exibida
Esquema do Cenário: Bloqueio após múltiplas tentativas
Quando tento fazer login com email "" e senha ""
E repito este login falho por vezes
Então minha conta fica bloqueada por minutos
E uma mensagem "Conta temporariamente bloqueada" é exibida
Exemplos:
| email | senha | tentativas | minutos |
| joao@exemplo.com | errada1 | 3 | 30 |
| maria@exemplo.com | errada2 | 5 | 60 |
Cucumber: Implementando BDD
Cucumber Architecture
.feature files (Gherkin)
↓
Cucumber Parser
↓
Step Definitions (Glue Code)
↓
Step Definitions (Java/JS/Python/Ruby)
↓
Application Under Test
Cucumber com Java (Spring Boot)
Dependências
io.cucumber
cucumber-java
7.14.0
test
io.cucumber
cucumber-spring
7.14.0
test
io.cucumber
cucumber-junit-platform-engine
7.14.0
test
Feature File
# src/test/resources/features/carrinho.feature
Funcionalidade: Carrinho de Compras
Como um cliente do e-commerce
Quero adicionar e remover produtos do carrinho
Para finalizar minha compra
Contexto:
Dado que estou logado como "cliente@teste.com"
E o produto "Camiseta Azul" custa R$ 49,90
E o produto "Calça Jeans" custa R$ 129,90
E o produto "Tênis" custa R$ 199,90
Cenário: Adicionar produto ao carrinho
Quando adiciono "Camiseta Azul" ao carrinho
Então o carrinho deve conter 1 item
E o total deve ser R$ 49,90
Cenário: Adicionar múltiplos produtos
Quando adiciono "Camiseta Azul" ao carrinho
E adiciono "Calça Jeans" ao carrinho
E adiciono "Tênis" ao carrinho
Então o carrinho deve conter 3 itens
E o total deve ser R$ 379,70
Cenário: Remover produto do carrinho
Dado que tenho "Camiseta Azul" e "Calça Jeans" no carrinho
Quando removo "Camiseta Azul" do carrinho
Então o carrinho deve conter 1 item
E o total deve ser R$ 129,90
Step Definitions
package steps;
import io.cucumber.java.pt.*;
import org.springframework.beans.factory.annotation.Autowired;
import static org.junit.jupiter.api.Assertions.*;
class CarrinhoSteps {
@Autowired
private CarrinhoService carrinhoService;
@Autowired
private TestContext testContext;
private Carrinho carrinho;
@Dado("que estou logado como {string}")
public void que_estou_logado_como(String email) {
testContext.setUsuario(email);
carrinho = new Carrinho();
}
@Dado("o produto {string} custa R$ {double}")
public void produto_custa(String nome, double preco) {
// Setup de produto no banco de dados de teste
}
@Quando("adiciono {string} ao carrinho")
public void adiciono_produto_ao_carrinho(String produto) {
carrinho.adicionar(new Item(produto, obterPreco(produto)));
}
@Então("o carrinho deve conter {int} item")
public void carrinho_deve_conter_itens(int quantidade) {
assertEquals(quantidade, carrinho.getItens().size());
}
@Então("o total deve ser R$ {double}")
public void total_deve_ser(double total) {
assertEquals(total, carrinho.getTotal(), 0.01);
}
}
Cucumber com Python (Behave)
Instalação
pip install behave
Feature File
# features/carrinho.feature
Funcionalidade: Carrinho de Compras
Como um cliente do e-commerce
Quero adicionar produtos ao carrinho
Para visualizar o total da compra
Cenário: Adicionar produto ao carrinho
Dado que o produto "Camiseta" custa 50.00
Quando adiciono o produto ao carrinho
Então o total deve ser 50.00
Step Definitions
# features/steps/carrinho_steps.py
from behave import given, when, then
from carrinho import Carrinho
@given('o produto "{nome}" custa {preco}')
def step_impl(context, nome, preco):
if not hasattr(context, 'produtos'):
context.produtos = {}
context.produtos[nome] = float(preco.replace('.', '').replace(',', '.'))
@when('adiciono o produto ao carrinho')
def step_impl(context):
if not hasattr(context, 'carrinho'):
context.carrinho = Carrinho()
for nome, preco in context.produtos.items():
context.carrinho.adicionar(nome, preco)
@then('o total deve ser {total}')
def step_impl(context, total):
esperado = float(total.replace('.', '').replace(',', '.'))
assert context.carrinho.total == esperado,
f"Esperado {esperado}, got {context.carrinho.total}"
Runner
# features/environment.py
def before_all(context):
context.produtos = {}
context.carrinho = None
def after_scenario(context, scenario):
# Cleanup
context.produtos = {}
context.carrinho = None
BDD em Equipes Ágeis
O Ciclo BDD Completo
┌──────────────────────────────────────────────┐
│ │
▼ │
┌───────┐ ┌─────────┐ ┌──────────┐ ┌─────┴───┐
│DISCUSS│───▶│EXAMPLES │───▶│AUTOMATE │───▶│IMPLEMENT│
│ () │ │ (O) │ │ (o) │ │ (.) │
└───────┘ └─────────┘ └──────────┘ └─────────┘
▲ │
│ │
└──────────────────────────────────────────────┘
(Feedback)
Reunião de Three Amigos
A reunião de Three Amigos junta desenvolvedores, QA e product owner para discutir requisitos.
# Agenda da Reunião Three Amigos
Preparação (1 dia antes)
- PO compartilha user stories
- QA prepara perguntas
- Devs revisam história
Reunião (60 minutos)
- PO apresenta user story (10 min)
- Discussão de requisitos (20 min)
- QA identifica cenários de teste (15 min)
- Devs identificam complexidades (10 min)
- Acordo sobre exemplos concretos (5 min)
Output
- User story com critérios de aceitação claros
- Cenários BDD definidos
- Incertezas documentadas
Exemplo: User Story com BDD
User Story: RS-123 - Carrinho Abandonado
Como
Vendedor do e-commerce
Eu quero
Receber notificação quando cliente abandonar carrinho
Para que
Possa entrar em contato e recuperar a venda
Critérios de Aceitação:
- [ ] Notificação enviada 30 min após abandono
- [ ] Email inclui produtos abandonados
- [ ] Email inclui link para recuperação
- [ ] Não enviar se cliente já Comprou
- [ ] Rate limit de 1 email por cliente por dia
Cenários BDD:
Funcionalidade: Carrinho Abandonado
Cenário: Notificação enviada após 30 minutos
Dado que o cliente adicionou produtos ao carrinho
E saiu do site sem Comprar
Quando passam 30 minutos
Então um email de recuperação é enviado
Cenário: Email inclui produtos abandonados
Dado que o cliente abandonou o carrinho com:
| Produto | Quantidade |
| Camiseta | 2 |
| Calça Jeans | 1 |
Quando o email de recuperação é enviado
Então o email lista todos os produtos abandonados
Cenário: Não enviar se cliente Comprou
Dado que o cliente abandonou o carrinho
Mas depois finalizou a compra
Quando passam 30 minutos
Então nenhum email é enviado
Boas Práticas em BDD
1. Feature Files Bem Estruturados
# BOM: Cenários focados e descritivos
Funcionalidade: Cálculo de Frete
Cenário: Frete para SP capital
Dado que o produto custa R$ 100
Quando o cliente é de "SP" e "São Paulo"
Então o frete é R$ 15,90
# RUIM: Cenário muito genérico
Funcionalidade: Frete
Cenário: Teste de frete
Dado que tenho um produto
Quando calculo o frete
Então deve funcionar
2. Step Definitions Reutilizáveis
# Defina steps genéricos
@given('que o produto "{nome}" custa R$ {preco}')
def step_produto(context, nome, preco):
context.produtos[nome] = float(preco)
@when('eu adiciono "{nome}" ao carrinho')
def step_adicionar(context, nome):
context.carrinho.adicionar(nome, context.produtos[nome])
3. Page Objects para Web
# pages/login_page.py
class LoginPage:
def __init__(self, driver):
self.driver = driver
@property
def email_field(self):
return self.driver.find_element(By.ID, 'email')
@property
def password_field(self):
return self.driver.find_element(By.ID, 'password')
@property
def login_button(self):
return self.driver.find_element(By.ID, 'login-button')
def login(self, email, password):
self.email_field.send_keys(email)
self.password_field.send_keys(password)
self.login_button.click()
Integração com CI/CD
# GitHub Actions - BDD Tests
name: BDD Tests
on: [push, pull_request]
jobs:
bdd-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dependencies
run: |
pip install behave selenium webdriver-manager
- name: Run BDD tests
run: behave --format=json --outfile=reports/behave.json
- name: Upload reports
uses: actions/upload-artifact@v4
with:
name: cucumber-reports
path: reports/
Conclusão
BDD é uma metodologia poderosa que une equipes através de linguagem comum. As chaves para sucesso são:
- Colaboração – Three Amigos regularmente
- Exemplos concretos – Ao invés de requisitos vagos
- Automação – Transforma cenários em testes executáveis
- Documentação viva – Features são especificação + teste
- Feedback rápido – Ciclos curtos de desenvolvimento
FAQ
P: BDD substitui TDD?
R: Não. BDD usa TDD internamente. BDD foca em colaboração, TDD em técnica.
P: Como começar com BDD?
R: Comece com Three Amigos para definir cenários, depois implemente com Cucumber/Behave.
P: Quantos cenários por feature?
R: O suficiente para cobrir comportamento. Evite redundância, use Examples para variações.
P: BDD funciona para qualquer projeto?
R: Melhor para projetos com requisitos claros e colaboração entre negocio e TI.
