<p><strong>Meta Description:</strong> Aprenda BDD: Gherkin, Cucumber, Behave, e como implementar desenvolvimento guiado por comportamento para equipes ágeis.</p>

<hr>
<h2>O Que é BDD?</h2>

<p>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.</p>

<h3>A História do BDD</h3>

<pre><code>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
</code></pre>

<hr>
<h2>Gherkin: A Linguagem de BDD</h2>

<h3>Estrutura Básica</h3>

<pre><code># language: pt
Funcionalidade: Título da funcionalidade
  Como um [ator]
  Quero [ação]
  Para [benefício]

<p>Contexto: [precondições]<br>    Dado [estado inicial]<br>    E [mais estados]</p>

<p>Cenário: [nome do cenário]<br>    Quando [ação]<br>    E [mais ações]<br>    Então [resultado esperado]<br>    E [mais resultados]</p>

<p>Cenário: [outro cenário]<br>    ...<br></code></pre></p>

<h3>Palavras-Chave Gherkin</h3>

<figure class="wp-block-table"><table>
<tr><th>Keyword</th><th>Uso</th></tr>
<tr><td><code>Funcionalidade</code> (Feature)</td><td>Agrupa cenários relacionados</td></tr>
<tr><td><code>Contexto</code> (Background)</td><td>Precondições comuns</td></tr>
<tr><td><code>Cenário</code> (Scenario)</td><td>Caso de uso específico</td></tr>
<tr><td><code>Dado</code> (Given)</td><td>Pré-condições</td></tr>
<tr><td><code>Quando</code> (When)</td><td>Ação/evento</td></tr>
<tr><td><code>Então</code> (Then)</td><td>Resultado esperado</td></tr>
<tr><td><code>E</code> (And)</td><td>Conjunção</td></tr>
<tr><td><code>Mas</code> (But)</td><td>Conjunção negativa</td></tr>
<tr><td><code>Esquema do Cenário</code></td><td>Cenário parametrizado</td></tr>
<tr><td><code> Exemplos</code> (Examples)</td><td>Dados de teste</td></tr>
</table></figure>

<h3>Exemplo Completo</h3>

<pre><code># 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

<p>Contexto:<br>    Dado que o sistema está operacional<br>    E o usuário "joao@exemplo.com" está cadastrado com senha "Senha@123"</p>

<p>Cenário: Login com credenciais válidas<br>    Quando eu acesso a página de login<br>    E preencho o campo email com "joao@exemplo.com"<br>    E preencho o campo senha com "Senha@123"<br>    E clico no botão "Entrar"<br>    Então sou redirecionado para o dashboard<br>    E uma mensagem de boas-vindas é exibida<br>    E meu nome "João Silva" aparece no cabeçalho</p>

<p>Cenário: Login com senha incorreta<br>    Quando eu acesso a página de login<br>    E preencho o campo email com "joao@exemplo.com"<br>    E preencho o campo senha com "senhaerrada"<br>    E clico no botão "Entrar"<br>    Então permaneço na página de login<br>    E uma mensagem de erro "Credenciais inválidas" é exibida<br>    E o campo senha está vazio para nova tentativa</p>

<p>Cenário: Login com email não cadastrado<br>    Quando eu acesso a página de login<br>    E preencho o campo email com "naoexiste@exemplo.com"<br>    E preencho o campo senha com "senha123"<br>    E clico no botão "Entrar"<br>    Então uma mensagem de erro "Usuário não encontrado" é exibida</p>

<p>Esquema do Cenário: Bloqueio após múltiplas tentativas<br>    Quando tento fazer login com email "" e senha ""<br>    E repito este login falho por  vezes<br>    Então minha conta fica bloqueada por  minutos<br>    E uma mensagem "Conta temporariamente bloqueada" é exibida</p>

<p>Exemplos:<br>      | email             | senha      | tentativas | minutos |<br>      | joao@exemplo.com  | errada1    | 3          | 30      |<br>      | maria@exemplo.com  | errada2    | 5          | 60      |<br></code></pre></p>

<hr>
<h2>Cucumber: Implementando BDD</h2>

<h3>Cucumber Architecture</h3>

<pre><code>.feature files (Gherkin)
        ↓
   Cucumber Parser
        ↓
   Step Definitions (Glue Code)
        ↓
   Step Definitions (Java/JS/Python/Ruby)
        ↓
   Application Under Test
</code></pre>

<h3>Cucumber com Java (Spring Boot)</h3>

<h4>Dependências</h4>

<pre><code>
    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

</code></pre>

<h4>Feature File</h4>

<pre><code># 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

<p>Contexto:<br>    Dado que estou logado como "cliente@teste.com"<br>    E o produto "Camiseta Azul" custa R$ 49,90<br>    E o produto "Calça Jeans" custa R$ 129,90<br>    E o produto "Tênis" custa R$ 199,90</p>

<p>Cenário: Adicionar produto ao carrinho<br>    Quando adiciono "Camiseta Azul" ao carrinho<br>    Então o carrinho deve conter 1 item<br>    E o total deve ser R$ 49,90</p>

<p>Cenário: Adicionar múltiplos produtos<br>    Quando adiciono "Camiseta Azul" ao carrinho<br>    E adiciono "Calça Jeans" ao carrinho<br>    E adiciono "Tênis" ao carrinho<br>    Então o carrinho deve conter 3 itens<br>    E o total deve ser R$ 379,70</p>

<p>Cenário: Remover produto do carrinho<br>    Dado que tenho "Camiseta Azul" e "Calça Jeans" no carrinho<br>    Quando removo "Camiseta Azul" do carrinho<br>    Então o carrinho deve conter 1 item<br>    E o total deve ser R$ 129,90<br></code></pre></p>

<h4>Step Definitions</h4>

<pre><code>package steps;

<p>import io.cucumber.java.pt.*;<br>import org.springframework.beans.factory.annotation.Autowired;<br>import static org.junit.jupiter.api.Assertions.*;</p>

<p>class CarrinhoSteps {</p>

<p>@Autowired<br>    private CarrinhoService carrinhoService;</p>

<p>@Autowired<br>    private TestContext testContext;</p>

<p>private Carrinho carrinho;</p>

<p>@Dado("que estou logado como {string}")<br>    public void que_estou_logado_como(String email) {<br>        testContext.setUsuario(email);<br>        carrinho = new Carrinho();<br>    }</p>

<p>@Dado("o produto {string} custa R$ {double}")<br>    public void produto_custa(String nome, double preco) {<br>        // Setup de produto no banco de dados de teste<br>    }</p>

<p>@Quando("adiciono {string} ao carrinho")<br>    public void adiciono_produto_ao_carrinho(String produto) {<br>        carrinho.adicionar(new Item(produto, obterPreco(produto)));<br>    }</p>

<p>@Então("o carrinho deve conter {int} item")<br>    public void carrinho_deve_conter_itens(int quantidade) {<br>        assertEquals(quantidade, carrinho.getItens().size());<br>    }</p>

<p>@Então("o total deve ser R$ {double}")<br>    public void total_deve_ser(double total) {<br>        assertEquals(total, carrinho.getTotal(), 0.01);<br>    }<br>}<br></code></pre></p>

<h3>Cucumber com Python (Behave)</h3>

<h4>Instalação</h4>

<pre><code>pip install behave
</code></pre>

<h4>Feature File</h4>

<pre><code># features/carrinho.feature
Funcionalidade: Carrinho de Compras
  Como um cliente do e-commerce
  Quero adicionar produtos ao carrinho
  Para visualizar o total da compra

<p>Cenário: Adicionar produto ao carrinho<br>    Dado que o produto "Camiseta" custa 50.00<br>    Quando adiciono o produto ao carrinho<br>    Então o total deve ser 50.00<br></code></pre></p>

<h4>Step Definitions</h4>

<pre><code># features/steps/carrinho_steps.py
from behave import given, when, then
from carrinho import Carrinho

<p>@given('o produto "{nome}" custa {preco}')<br>def step_impl(context, nome, preco):<br>    if not hasattr(context, 'produtos'):<br>        context.produtos = {}<br>    context.produtos[nome] = float(preco.replace('.', '').replace(',', '.'))</p>

<p>@when('adiciono o produto ao carrinho')<br>def step_impl(context):<br>    if not hasattr(context, 'carrinho'):<br>        context.carrinho = Carrinho()</p>

<p>for nome, preco in context.produtos.items():<br>        context.carrinho.adicionar(nome, preco)</p>

<p>@then('o total deve ser {total}')<br>def step_impl(context, total):<br>    esperado = float(total.replace('.', '').replace(',', '.'))<br>    assert context.carrinho.total == esperado, <br>        f"Esperado {esperado}, got {context.carrinho.total}"<br></code></pre></p>

<h4>Runner</h4>

<pre><code># features/environment.py
def before_all(context):
    context.produtos = {}
    context.carrinho = None

<p>def after_scenario(context, scenario):<br>    # Cleanup<br>    context.produtos = {}<br>    context.carrinho = None<br></code></pre></p>

<hr>
<h2>BDD em Equipes Ágeis</h2>

<h3>O Ciclo BDD Completo</h3>

<pre><code>   ┌──────────────────────────────────────────────┐
   │                                              │
   ▼                                              │
┌───────┐    ┌─────────┐    ┌──────────┐    ┌─────┴───┐
│DISCUSS│───▶│EXAMPLES │───▶│AUTOMATE │───▶│IMPLEMENT│
│   ()  │    │   (O)   │    │   (o)   │    │   (.)   │
└───────┘    └─────────┘    └──────────┘    └─────────┘
    ▲                                              │
    │                                              │
    └──────────────────────────────────────────────┘
                    (Feedback)
</code></pre>

<h3>Reunião de Three Amigos</h3>

<p>A reunião de Three Amigos junta desenvolvedores, QA e product owner para discutir requisitos.</p>

<pre><code># Agenda da Reunião Three Amigos

<h2>Preparação (1 dia antes)</h2>
<ul><li>PO compartilha user stories</li><ol><li>QA prepara perguntas</li>
<li>Devs revisam história</li>
</ol>
<h2>Reunião (60 minutos)</h2><ol><li>PO apresenta user story (10 min)</li>
<li>Discussão de requisitos (20 min)</li>
<li>QA identifica cenários de teste (15 min)</li>
<li>Devs identificam complexidades (10 min)</li>
<li>Acordo sobre exemplos concretos (5 min)</li>
</ol>
<h2>Output</h2><ol><li>User story com critérios de aceitação claros</li>
<li>Cenários BDD definidos</li>
<li>Incertezas documentadas</li>
</ol></code></pre>

<h3>Exemplo: User Story com BDD</h3>

<pre><code><h2>User Story: RS-123 - Carrinho Abandonado</h2>

<h3>Como</h3>
  Vendedor do e-commerce

<h3>Eu quero</h3>
  Receber notificação quando cliente abandonar carrinho

<h3>Para que</h3>
  Possa entrar em contato e recuperar a venda

<h3>Critérios de Aceitação:</h3><ol><li>[ ] Notificação enviada 30 min após abandono</li>
<li>[ ] Email inclui produtos abandonados</li>
<li>[ ] Email inclui link para recuperação</li>
<li>[ ] Não enviar se cliente já Comprou</li>
<li>[ ] Rate limit de 1 email por cliente por dia</li></ol></ul>

<h3>Cenários BDD:</h3>
</code></pre>

<pre><code>Funcionalidade: Carrinho Abandonado

<p>Cenário: Notificação enviada após 30 minutos<br>    Dado que o cliente adicionou produtos ao carrinho<br>    E saiu do site sem Comprar<br>    Quando passam 30 minutos<br>    Então um email de recuperação é enviado</p>

<p>Cenário: Email inclui produtos abandonados<br>    Dado que o cliente abandonou o carrinho com:<br>      | Produto       | Quantidade |<br>      | Camiseta     | 2         |<br>      | Calça Jeans  | 1         |<br>    Quando o email de recuperação é enviado<br>    Então o email lista todos os produtos abandonados</p>

<p>Cenário: Não enviar se cliente Comprou<br>    Dado que o cliente abandonou o carrinho<br>    Mas depois finalizou a compra<br>    Quando passam 30 minutos<br>    Então nenhum email é enviado<br></code></pre></p>

<hr>
<h2>Boas Práticas em BDD</h2>

<h3>1. Feature Files Bem Estruturados</h3>

<pre><code># 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

<p># RUIM: Cenário muito genérico<br>Funcionalidade: Frete<br>  Cenário: Teste de frete<br>    Dado que tenho um produto<br>    Quando calculo o frete<br>    Então deve funcionar<br></code></pre></p>

<h3>2. Step Definitions Reutilizáveis</h3>

<pre><code># Defina steps genéricos
@given('que o produto "{nome}" custa R$ {preco}')
def step_produto(context, nome, preco):
    context.produtos[nome] = float(preco)

<p>@when('eu adiciono "{nome}" ao carrinho')<br>def step_adicionar(context, nome):<br>    context.carrinho.adicionar(nome, context.produtos[nome])<br></code></pre></p>

<h3>3. Page Objects para Web</h3>

<pre><code># pages/login_page.py
class LoginPage:
    def __init__(self, driver):
        self.driver = driver

<p>@property<br>    def email_field(self):<br>        return self.driver.find_element(By.ID, 'email')</p>

<p>@property<br>    def password_field(self):<br>        return self.driver.find_element(By.ID, 'password')</p>

<p>@property<br>    def login_button(self):<br>        return self.driver.find_element(By.ID, 'login-button')</p>

<p>def login(self, email, password):<br>        self.email_field.send_keys(email)<br>        self.password_field.send_keys(password)<br>        self.login_button.click()<br></code></pre></p>

<hr>
<h2>Integração com CI/CD</h2>

<pre><code># GitHub Actions - BDD Tests
name: BDD Tests

<p>on: [push, pull_request]</p>

<p>jobs:<br>  bdd-tests:<br>    runs-on: ubuntu-latest</p>

<p>steps:<br>      - uses: actions/checkout@v4</p>

<p>- name: Setup Python<br>        uses: actions/setup-python@v5<br>        with:<br>          python-version: '3.11'</p>

<p>- name: Install dependencies<br>        run: |<br>          pip install behave selenium webdriver-manager</p>

<p>- name: Run BDD tests<br>        run: behave --format=json --outfile=reports/behave.json</p>

<p>- name: Upload reports<br>        uses: actions/upload-artifact@v4<br>        with:<br>          name: cucumber-reports<br>          path: reports/<br></code></pre></p>

<hr>
<h2>Conclusão</h2>

<p>BDD é uma metodologia poderosa que une equipes através de linguagem comum. As chaves para sucesso são:<br><ol><li><strong>Colaboração</strong> - Three Amigos regularmente</li><br><li><strong>Exemplos concretos</strong> - Ao invés de requisitos vagos</li><br><li><strong>Automação</strong> - Transforma cenários em testes executáveis</li><br><li><strong>Documentação viva</strong> - Features são especificação + teste</li><br><li><strong>Feedback rápido</strong> - Ciclos curtos de desenvolvimento</li><br></ol><br><hr><br><h3>FAQ</h3></p>

<p><strong>P: BDD substitui TDD?</strong>  <br>R: Não. BDD usa TDD internamente. BDD foca em colaboração, TDD em técnica.</p>

<p><strong>P: Como começar com BDD?</strong>  <br>R: Comece com Three Amigos para definir cenários, depois implemente com Cucumber/Behave.</p>

<p><strong>P: Quantos cenários por feature?</strong>  <br>R: O suficiente para cobrir comportamento. Evite redundância, use Examples para variações.</p>

<p><strong>P: BDD funciona para qualquer projeto?</strong>  <br>R: Melhor para projetos com requisitos claros e colaboração entre negocio e TI.</p>