Testes

Gherkin e Given-When-Then: especificação que vira teste

Gherkin é a linguagem por trás do BDD: um conjunto pequeno de palavras-chave que deixa um cenário de teste legível por qualquer pessoa — do Product Owner ao desenvolvedor — e, ao mesmo tempo, executável por ferramentas como Cucumber, Behave (Python), SpecFlow (.NET) ou Behat (PHP). É o ponto onde a especificação e o teste viram o mesmo documento.

As palavras-chave

Toda a gramática cabe em poucas palavras. O resto é texto livre que você escolhe:

  • Funcionalidade (Feature) — o agrupador; descreve a capacidade do sistema.
  • Cenário (Scenario) — um exemplo concreto de comportamento.
  • Dado (Given) — o contexto / pré-condição. O mundo antes da ação.
  • Quando (When) — a ação que dispara o comportamento. Uma só por cenário, idealmente.
  • Então (Then) — o resultado observável que se verifica.
  • E / Mas (And / But) — encadeiam passos do mesmo tipo, mantendo a leitura fluida.

A estrutura Given-When-Then

O coração do Gherkin é separar contexto → ação → resultado. Essa tríade força o autor a pensar em comportamento, não em telas:

# language: pt
Funcionalidade: Autenticação de usuário

  Cenário: Login com credenciais válidas
    Dado que estou na página de login
    E possuo uma conta com e-mail "ana@exemplo.com"
    Quando informo as credenciais corretas
    Então devo ver o painel inicial
    E devo ver a saudação "Olá, Ana"
Regra de ouro: Given não tem ação, When é uma ação só, Then não tem efeito colateral — só verifica. Se um cenário tem três "Quando", provavelmente são três cenários disfarçados.

Background: o contexto que se repete

Quando vários cenários compartilham os mesmos Given, o Background (Contexto) evita repetição — ele roda antes de cada cenário do arquivo:

  Contexto:
    Dado que estou logado como administrador
    E existe um produto "Caderno" no catálogo

Scenario Outline: um cenário, muitos dados

Para testar a mesma regra com várias entradas — o caso clássico de partição de equivalência e valor-limite — usa-se o Esquema do Cenário com uma tabela de Exemplos:

  Esquema do Cenário: Desconto por faixa de valor
    Dado um carrinho com <valor> reais
    Quando o cliente finaliza a compra
    Então o total cobrado deve ser <total> reais

    Exemplos:
      | valor | total |
      | 100   | 100   |
      | 101   | 90.9  |
      | 150   | 135   |

Cada linha da tabela vira um cenário independente. É a forma mais limpa de cobrir limites (o 100 que não ganha desconto e o 101 que ganha) sem copiar e colar.

Do texto ao código: step definitions

O Gherkin sozinho não testa nada — ele é "colado" ao sistema pelos step definitions: funções que casam com cada passo por expressão e executam a automação de verdade. Em Cucumber com JavaScript:

const { Given, When, Then } = require('@cucumber/cucumber');
const { expect } = require('@playwright/test');

Given('um carrinho com {int} reais', async function (valor) {
  this.carrinho = criarCarrinho(valor);
});

When('o cliente finaliza a compra', async function () {
  this.total = this.carrinho.finalizar();
});

Then('o total cobrado deve ser {float} reais', async function (esperado) {
  expect(this.total).toBeCloseTo(esperado, 2);
});

Repare que o mesmo step um carrinho com {int} reais serve a todas as linhas do Exemplos. Steps bem escritos são reutilizáveis — esse é o ganho de manutenção do BDD.

Declarativo > imperativo

O erro mais comum é escrever cenários imperativos, descrevendo cada clique. Eles quebram a cada ajuste de tela e ninguém do negócio consegue ler:

Imperativo (frágil)Declarativo (robusto)
Quando preencho o campo "email" com "ana@x.com"
E preencho o campo "senha" com "123"
E clico no botão "#btn-login"
Quando faço login com credenciais válidas

O "como preencher o formulário" pertence ao step definition (e ao Page Object), não ao Gherkin. O cenário descreve a intenção.

Anti-patterns para vigiar

  • Cenário-novela: dez passos cobrindo um fluxo inteiro. Um cenário = um comportamento.
  • Detalhe de UI no Then: verificar cor de botão ou CSS. Verifique resultado de negócio.
  • Acoplamento entre cenários: o cenário 2 depender do estado deixado pelo cenário 1. Cada um deve ser independente.
  • Gherkin sem conversa: escrever os .feature sozinho, depois da implementação. Aí é só relatório enfeitado — perde-se o valor de descoberta do BDD.

Conclusão

Gherkin é simples de propósito: a restrição de vocabulário é o que mantém o cenário legível para todos e estável no tempo. Dominar Given-When-Then, Background e Scenario Outline — e saber escrever de forma declarativa — é o que transforma uma suíte de BDD em documentação viva em vez de mais um conjunto de testes frágeis.

Gherkin is the language behind BDD: a small set of keywords that makes a test scenario readable by anyone, from the Product Owner to the developer, and at the same time executable by tools like Cucumber, Behave (Python), SpecFlow (.NET), or Behat (PHP). It's the point where the specification and the test become the same document.

The keywords

The whole grammar fits in a few words. The rest is free text that you choose:

  • Feature — the grouping; describes a capability of the system.
  • Scenario — a concrete example of behavior.
  • Given — the context / precondition. The world before the action.
  • When — the action that triggers the behavior. Just one per scenario, ideally.
  • Then — the observable outcome that gets verified.
  • And / But — chain steps of the same type, keeping the reading fluid.

The Given-When-Then structure

The heart of Gherkin is separating context → action → outcome. This triad forces the author to think about behavior, not screens:

# language: en
Feature: User authentication

  Scenario: Login with valid credentials
    Given I am on the login page
    And I have an account with the email "ana@example.com"
    When I enter the correct credentials
    Then I should see the dashboard
    And I should see the greeting "Hello, Ana"
Golden rule: Given has no action, When is a single action, Then has no side effects, it only verifies. If a scenario has three "When"s, it's probably three scenarios in disguise.

Background: the context that repeats

When several scenarios share the same Givens, the Background avoids repetition; it runs before each scenario in the file:

  Background:
    Given I am logged in as an administrator
    And a product "Notebook" exists in the catalog

Scenario Outline: one scenario, lots of data

To test the same rule with several inputs (the classic case of equivalence partitioning and boundary values), use the Scenario Outline with an Examples table:

  Scenario Outline: Discount by order value
    Given a cart with <value> dollars
    When the customer checks out
    Then the total charged should be <total> dollars

    Examples:
      | value | total |
      | 100   | 100   |
      | 101   | 90.9  |
      | 150   | 135   |

Each row of the table becomes an independent scenario. It's the cleanest way to cover boundaries (the 100 that gets no discount and the 101 that does) without copy and paste.

From text to code: step definitions

Gherkin alone tests nothing; it gets "glued" to the system by step definitions: functions that match each step by expression and run the actual automation. In Cucumber with JavaScript:

const { Given, When, Then } = require('@cucumber/cucumber');
const { expect } = require('@playwright/test');

Given('a cart with {int} dollars', async function (value) {
  this.cart = createCart(value);
});

When('the customer checks out', async function () {
  this.total = this.cart.checkout();
});

Then('the total charged should be {float} dollars', async function (expected) {
  expect(this.total).toBeCloseTo(expected, 2);
});

Notice that the same step a cart with {int} dollars serves every row of the Examples. Well-written steps are reusable, and that's BDD's maintenance payoff.

Declarative > imperative

The most common mistake is writing imperative scenarios that describe every click. They break with every screen tweak and nobody on the business side can read them:

Imperative (brittle)Declarative (robust)
When I fill in the "email" field with "ana@x.com"
And I fill in the "password" field with "123"
And I click the "#btn-login" button
When I log in with valid credentials

The "how to fill in the form" belongs to the step definition (and to the Page Object), not to Gherkin. The scenario describes the intent.

Anti-patterns to watch for

  • Soap-opera scenario: ten steps covering an entire flow. One scenario = one behavior.
  • UI detail in the Then: verifying a button's color or CSS. Verify a business outcome.
  • Coupling between scenarios: scenario 2 depending on the state left by scenario 1. Each one must be independent.
  • Gherkin without conversation: writing the .feature files alone, after the implementation. That's just a dressed-up report, and you lose the discovery value of BDD.

Conclusion

Gherkin is simple on purpose: the vocabulary restriction is what keeps the scenario readable for everyone and stable over time. Mastering Given-When-Then, Background, and Scenario Outline, and knowing how to write declaratively, is what turns a BDD suite into living documentation instead of one more set of brittle tests.

Leia também

Voltar ao blog