Skip to content

Instantly share code, notes, and snippets.

@joaovictorino
Last active October 5, 2023 04:41
Show Gist options
  • Save joaovictorino/2a9f693fe15c52f47a7702d3dd56a850 to your computer and use it in GitHub Desktop.
Save joaovictorino/2a9f693fe15c52f47a7702d3dd56a850 to your computer and use it in GitHub Desktop.
Incluindo BDD nos testes de API

Incluindo BDD nos testes de API

Vamos colocar BDD em nossos testes de integração de API.
Para isso vamos utilizar o Cucumber, então instale no projeto web, executando o comando abaixo na pasta "web"

npm install @cucumber/cucumber@9.5.1 cucumber-tsflow@4.1.1 ts-node@10.9.1 -D

Agora vamos criar o arquivo de configuração do Cucumber, portanto na raiz do projeto, crie o arquivo "cucumber.js" com o conteúdo abaixo

let common = [
    'features/**/*.feature',
    '--require-module ts-node/register',
    '--require features/steps/**/*.step.ts',
    '--format progress-bar',
  ].join(' ');
  
  module.exports = {
    default: common
  };

Altere o arquivo "package.json" dentro de script, incluindo a instrução de execução do Cucumber, conforme abaixo

"test": "jest && npm run test:cucumber",
"test:cucumber": "cucumber-js -p default"

Vamos alterar a configuração de duas variáveis no arquivo "tsconfig.json", conforme abaixo

"experimentalDecorators": true,
"module": "commonjs"

Depois de toda a configuração feita, crie uma pasta na raiz do projeto com o nome de "features" e crie o arquivo "transferir.feature" com o conteúdo abaixo

# language: pt
Funcionalidade: Transferir valores entre contas
    Validar a transferência de valores entre contas

    Cenário: Transferir valores com sucesso entre duas contas
        Dada conta "<origem>" com saldo <saldoOrigem> e a conta "<destino>" com saldo <saldoDestino>
        Quando a conta "<origem>" transferir <valor> para a conta "<destino>"
        Então o saldo da conta "<origem>" deve ser <resultadoOrigem> e a conta "<destino>" <resultadoDestino>

    Exemplos:
        | origem    | destino   | valor   | saldoOrigem | saldoDestino  | resultadoOrigem   | resultadoDestino |
        | 987654    | 321654    | 1000.00 | 2000.00     | 100.00        | 1000.00           | 1100.00          |
        | 222222    | 555555    | 2500.00 | 20000.00    | 0.00          | 17500.00          | 2500.00          |

Agora crie uma pasta "steps" dentro da pasta "features" e crie o arquivo "transferir.step.ts" que irá unir nosso texto na linguagem Gherkin com o código Typescript da nossa aplicação

import { createMocks } from "node-mocks-http";
import { binding, given, when, then } from "cucumber-tsflow";
import contas from "../../pages/api/contas/index";
import transferir from "../../pages/api/contas/transferir";
import consultar from "../../pages/api/contas/[numero]";
import assert from "assert";
import { setTimeout } from 'timers/promises';

@binding()
class Transferir {

  @given("conta {string} com saldo {float} e a conta {string} com saldo {float}")
  public async dadaDuasContas(numeroOrigem: string, saldoOrigem: number, numeroDestino: string, saldoDestino: number) {    
    const mockOrigem = createMocks({
      method: "POST",
      url: "api/contas/",
      body: {
          numero: numeroOrigem,
          saldo: saldoOrigem
      }
    });

    await contas(mockOrigem.req, mockOrigem.res);
    assert.equal(201, mockOrigem.res.statusCode);

    const mockDestino = createMocks({
      method: "POST",
      url: "api/contas/",
      body: {
          numero: numeroDestino,
          saldo: saldoDestino
      }
    });

    await contas(mockDestino.req, mockDestino.res);
    assert.equal(201, mockDestino.res.statusCode);
  }

  @when("a conta {string} transferir {float} para a conta {string}")
  public async quandoTransferirValores(numeroOrigem: string, valor: number, numeroDestino: string) {
    const { req, res } = createMocks({
      method: "POST",
      url: "api/contas/transferir",
      body: {
          origem: numeroOrigem,
          destino: numeroDestino,
          valor: valor
      }
    });

    await transferir(req, res);
    assert.equal(200, res.statusCode);
  }

  @then("o saldo da conta {string} deve ser {float} e a conta {string} {float}")
  public async entaoSaldoDeveSer(numeroOrigem: string, resultadoOrigem: number, numeroDestino: string, resultadoDestino: number) {
    await setTimeout(10);

    const mockOrigem = createMocks({
      method: "GET",
      url: "api/contas/",
      query: {
          numero: numeroOrigem,
      }
    });

    await consultar(mockOrigem.req, mockOrigem.res);
    assert.equal(200, mockOrigem.res.statusCode);

    const mockDestino = createMocks({
      method: "GET",
      url: "api/contas/",
      query: {
          numero: numeroDestino,
      }
    });

    await consultar(mockDestino.req, mockDestino.res);
    assert.equal(200, mockDestino.res.statusCode);

    assert.equal(resultadoOrigem, mockOrigem.res._getJSONData().saldo);
    assert.equal(resultadoDestino, mockDestino.res._getJSONData().saldo);
  }
}

export default Transferir;

Chegou a hora de testar se tudo deu certo, execute o comando abaixo na raiz do projeto

npm run test:cucumber

Se tudo ocorrer bem, os três cenários serão executados com sucesso.
Agora também podemos voltar para a raiz da workspace e executar todos os testes dos dois projeto com um único comando

npm run test --workspaces
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment