BDD (Behavior-Driven Development): Guia Completo para Equipes Ágeis

Testes Automatizados · 6 de julho de 2026

📖 9 min de leitura

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
    1. QA prepara perguntas
    2. Devs revisam história

    Reunião (60 minutos)

    1. PO apresenta user story (10 min)
    2. Discussão de requisitos (20 min)
    3. QA identifica cenários de teste (15 min)
    4. Devs identificam complexidades (10 min)
    5. Acordo sobre exemplos concretos (5 min)

    Output

    1. User story com critérios de aceitação claros
    2. Cenários BDD definidos
    3. 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:

  1. [ ] Notificação enviada 30 min após abandono
  2. [ ] Email inclui produtos abandonados
  3. [ ] Email inclui link para recuperação
  4. [ ] Não enviar se cliente já Comprou
  5. [ ] 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:

  1. Colaboração – Three Amigos regularmente
  2. Exemplos concretos – Ao invés de requisitos vagos
  3. Automação – Transforma cenários em testes executáveis
  4. Documentação viva – Features são especificação + teste
  5. 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.