O que são testes de fluxo e encadeamento de requests
Em testes de API, nem sempre faz sentido validar endpoints de forma isolada. Muitos comportamentos só aparecem quando você executa uma sequência de chamadas que dependem umas das outras, como: criar um recurso, usar o ID retornado para consultar detalhes, atualizar esse mesmo recurso e, por fim, removê-lo. Esse tipo de validação é chamado aqui de teste de fluxo (ou teste de jornada), e o encadeamento de requests é a técnica de fazer uma request “alimentar” a próxima com dados extraídos da resposta, como tokens, IDs, códigos de confirmação, links, timestamps e outros valores dinâmicos.
O objetivo do encadeamento não é apenas “fazer funcionar”, mas tornar o teste confiável e repetível: cada execução deve conseguir criar seus próprios dados, capturar o que precisa e seguir o fluxo sem depender de valores fixos copiados manualmente. Isso evita flakiness (testes instáveis), reduz retrabalho e aproxima o teste automatizado do uso real da API por um cliente.
Quando encadear requests é indispensável
Você deve considerar encadeamento sempre que houver dependência de estado entre endpoints. Exemplos comuns: login que retorna token e precisa ser usado em chamadas subsequentes; criação de entidade que retorna um ID e esse ID é necessário para GET/PUT/DELETE; criação de pedido que depende de um usuário existente; upload que retorna uma URL ou um identificador de arquivo; fluxos de pagamento que retornam um “paymentId” e depois exigem captura/estorno usando esse mesmo identificador.
Além disso, encadeamento é útil para validar regras de negócio que atravessam endpoints, como: “um pedido recém-criado deve aparecer na listagem”, “após cancelar, o status deve mudar e não permitir novas alterações”, “após atualizar, o GET deve refletir os novos campos”.
Estratégia geral: capturar e reutilizar valores dinâmicos
O padrão mais comum é: executar uma request que produz um valor dinâmico (por exemplo, token ou ID), extrair esse valor da resposta e armazená-lo em uma variável; em seguida, referenciar essa variável nas próximas requests (URL, headers, query params ou body). Esse padrão se repete em praticamente qualquer fluxo.
Continue em nosso aplicativo
Você poderá ouvir o audiobook com a tela desligada, ganhar gratuitamente o certificado deste curso e ainda ter acesso a outros 5.000 cursos online gratuitos.
ou continue lendo abaixo...Baixar o aplicativo
Na prática, você vai trabalhar com três pontos: (1) onde capturar o valor (normalmente na aba Tests da request que recebe a resposta), (2) onde armazenar (variável de coleção ou de ambiente, conforme a necessidade de compartilhamento e duração), e (3) onde consumir (nas requests seguintes, usando a sintaxe de variável do Postman).
Passo a passo prático: fluxo completo com captura de token e reutilização de IDs
O exemplo a seguir descreve um fluxo típico de QA: autenticar, criar um usuário, criar um pedido para esse usuário, consultar o pedido, atualizar o pedido e cancelar/remover. Adapte os endpoints e campos ao seu projeto, mas mantenha a lógica de encadeamento.
Passo 1: Request de autenticação e captura do token
Crie uma request de login, por exemplo: POST /auth/login. No body, envie credenciais válidas. A resposta costuma trazer um token (JWT ou similar) em algum campo como access_token, token ou data.token. O primeiro passo do encadeamento é capturar esse valor e armazenar em uma variável para ser usada no header Authorization das próximas requests.
Na aba Tests da request de login, extraia o token do JSON e salve em uma variável. Exemplo:
const json = pm.response.json();const token = json.access_token || json.token || json.data?.token;pm.test("Token retornado", function () { pm.expect(token, "token").to.be.a("string").and.not.empty;});pm.collectionVariables.set("access_token", token);Agora, nas requests seguintes, configure o header Authorization para usar esse token. Exemplo de valor: Bearer {{access_token}}. Se a sua API usar outro header (por exemplo, X-Auth-Token), aplique o mesmo princípio: o valor dinâmico vem da variável.
Passo 2: Criar usuário e capturar userId
Crie uma request POST /users para criar um usuário. O body deve conter dados válidos e, idealmente, únicos por execução (por exemplo, email com timestamp). O ponto central aqui é capturar o ID retornado na resposta, pois ele será usado para criar um pedido e para consultar/alterar o usuário.
Exemplo de captura do ID na aba Tests:
const json = pm.response.json();const userId = json.id || json.userId || json.data?.id;pm.test("UserId retornado", function () { pm.expect(userId, "userId").to.exist;});pm.collectionVariables.set("user_id", String(userId));Em seguida, crie uma request GET /users/{{user_id}} para validar que o recurso criado pode ser consultado. Note que o encadeamento aqui é direto: a URL depende do valor capturado anteriormente.
Passo 3: Criar pedido usando o userId capturado
Agora crie uma request POST /orders cujo body referencie o usuário criado. Muitas APIs exigem algo como userId no body, ou um relacionamento em um campo específico. Exemplo de body (ajuste ao seu contrato):
{ "userId": "{{user_id}}", "items": [ { "sku": "ABC-123", "qty": 1 } ]}Após criar o pedido, capture o orderId retornado. Exemplo:
const json = pm.response.json();const orderId = json.id || json.orderId || json.data?.id;pm.test("OrderId retornado", function () { pm.expect(orderId, "orderId").to.exist;});pm.collectionVariables.set("order_id", String(orderId));Com isso, você pode encadear GET /orders/{{order_id}} para validar persistência e consistência do recurso.
Passo 4: Atualizar pedido e validar efeito no GET
Crie uma request PUT ou PATCH /orders/{{order_id}} para atualizar algum campo (por exemplo, endereço, observação, status permitido). O encadeamento garante que você está atualizando exatamente o pedido criado na execução atual, e não um ID fixo que pode não existir no ambiente.
Depois do update, faça um GET /orders/{{order_id}} e valide que o campo foi realmente alterado. Esse padrão (mutação seguida de leitura) é uma das formas mais eficazes de detectar problemas de persistência, cache indevido, validação parcial e inconsistência de dados.
Passo 5: Cancelar/remover e validar comportamento esperado
Finalize o fluxo com uma request de cancelamento (por exemplo, POST /orders/{{order_id}}/cancel) ou remoção (DELETE /orders/{{order_id}}). Em seguida, valide o comportamento esperado: o GET pode retornar 404, ou pode retornar o recurso com status “CANCELLED”, dependendo da regra de negócio. O importante é que o teste reflita o contrato real do sistema e que o encadeamento use o mesmo order_id capturado.
Encadeamento controlado: como executar a sequência automaticamente
Capturar e reutilizar variáveis resolve a dependência de dados, mas ainda falta garantir que as requests rodem na ordem certa sem intervenção manual. Para isso, você pode controlar o fluxo de execução dentro da Collection Runner (ou Newman) usando a função de navegação entre requests. A ideia é: ao final de uma request, você define qual será a próxima request a ser executada, criando um “roteiro” do fluxo.
Um padrão comum é usar pm.execution.setNextRequest para avançar para a próxima etapa somente quando os pré-requisitos foram atendidos. Exemplo: após login, ir para “Create User”; após criar usuário, ir para “Create Order”; e assim por diante. Exemplo de script (na aba Tests do login):
pm.test("Login OK", function () { pm.expect(pm.response.code).to.be.oneOf([200, 201]);});pm.execution.setNextRequest("Create User");Na request “Create User”, você faria algo similar apontando para “Create Order”, e assim sucessivamente. Esse controle é especialmente útil quando você quer que uma execução falhe cedo (fail fast) e não continue gerando ruído em requests que dependem de dados não criados.
Boas práticas para captura de tokens
Tokens podem expirar, podem variar de formato e podem vir em locais diferentes (body, header Set-Cookie, ou ambos). Para manter o fluxo robusto, siga práticas como: validar que o token existe e é string não vazia; armazenar o token em uma variável com nome claro (por exemplo, access_token); e padronizar o consumo do token em todas as requests (por exemplo, sempre via header Authorization). Se a API retornar expiresIn, você pode armazenar também esse valor para diagnosticar falhas por expiração durante execuções longas.
Se o token vier em cookie (Set-Cookie), você pode capturar o cookie do jar do Postman ou ler headers, mas muitas vezes o Postman já gerencia cookies automaticamente. Ainda assim, em testes de fluxo, é útil registrar explicitamente o que está sendo usado para autenticar, para evitar que um teste passe “por acaso” devido a um cookie persistido de uma execução anterior.
Boas práticas para captura e reutilização de IDs
IDs podem ser numéricos, strings, UUIDs, ou até compostos. Ao salvar o ID, converta para string para evitar surpresas ao interpolar em URL e body. Também é útil salvar IDs com nomes específicos do domínio, como user_id, order_id, payment_id, evitando nomes genéricos como id, que podem ser sobrescritos em fluxos maiores.
Quando a resposta retorna múltiplos IDs (por exemplo, id do pedido e id do usuário dentro do pedido), seja explícito sobre qual você está capturando. Se o ID estiver aninhado, use acesso seguro (optional chaining) para evitar erro de script quando o formato mudar ou quando a resposta for de erro.
Tratamento de falhas no meio do fluxo
Em fluxos encadeados, uma falha no início pode invalidar todas as etapas seguintes. Para reduzir ruído, você pode: (1) validar status code e campos essenciais antes de salvar variáveis; (2) só chamar setNextRequest para a próxima etapa se os testes críticos passarem; (3) quando houver erro, direcionar para uma request de “cleanup” (limpeza) ou encerrar o fluxo.
Exemplo: se a criação do usuário falhar, não faz sentido tentar criar pedido. Você pode interromper o fluxo definindo a próxima request como null:
if (pm.response.code !== 201) { pm.execution.setNextRequest(null);}Outra abordagem é criar uma request “Diagnostics” que registra detalhes do erro e encerra. Isso ajuda a padronizar a análise quando o fluxo roda em CI via Newman.
Encadeamento com listas: capturar um ID de dentro de um array
Nem sempre o ID vem direto no topo do JSON. Em listagens, você pode precisar selecionar um item específico. Exemplo: GET /orders pode retornar um array em data. Você pode escolher o primeiro item, ou filtrar por algum critério (status, sku, userId). O importante é tornar a seleção determinística para evitar instabilidade.
Exemplo de captura do primeiro ID de uma lista:
const json = pm.response.json();const list = json.data || json;pm.test("Lista de pedidos não vazia", function () { pm.expect(list).to.be.an("array").and.not.empty;});pm.collectionVariables.set("order_id", String(list[0].id));Exemplo filtrando por userId:
const json = pm.response.json();const list = json.data || [];const userId = pm.collectionVariables.get("user_id");const match = list.find(o => String(o.userId) === String(userId));pm.test("Pedido do usuário encontrado", function () { pm.expect(match).to.exist;});if (match) { pm.collectionVariables.set("order_id", String(match.id));}Reutilização de IDs entre etapas e isolamento de cenários
Em suites maiores, você pode ter múltiplos fluxos rodando na mesma collection: “fluxo feliz”, “fluxo de erro”, “fluxo de cancelamento”, “fluxo de atualização”. Para evitar colisões, mantenha variáveis separadas por cenário quando necessário (por exemplo, order_id_happy e order_id_cancel). Outra prática é limpar variáveis ao final de um fluxo (setar vazio ou unset) para reduzir o risco de uma request usar um valor antigo quando uma etapa falhou e não atualizou a variável.
Exemplo de limpeza ao final do fluxo (na última request):
pm.collectionVariables.unset("order_id");pm.collectionVariables.unset("user_id");Encadeamento com dados derivados: capturar e reutilizar valores calculados
Nem todo valor reutilizado precisa vir diretamente da resposta. Às vezes você precisa derivar algo: por exemplo, capturar createdAt e calcular uma data limite para uma query, ou capturar um número de versão (etag/version) e enviar no próximo update para controle de concorrência otimista. O encadeamento, nesse caso, envolve capturar, transformar e armazenar.
Exemplo: capturar version e usar no próximo update:
const json = pm.response.json();const version = json.version || json.data?.version;pm.test("Version retornada", function () { pm.expect(version).to.exist;});pm.collectionVariables.set("order_version", String(version));Na request de update, você enviaria "version": "{{order_version}}" ou um header como If-Match, conforme o contrato.
Checklist de implementação do fluxo no Postman
- Nomeie as requests na collection com o prefixo da ordem do fluxo (por exemplo, 01 Login, 02 Create User, 03 Create Order) para facilitar leitura e manutenção.
- Em cada etapa que produz dados, capture apenas o necessário (token, IDs, versões) e valide que o valor existe antes de salvar.
- Use variáveis com nomes explícitos (access_token, user_id, order_id) para evitar sobrescrita acidental.
- Após mutações (POST/PUT/PATCH/DELETE), valide o efeito com uma request de leitura (GET) quando fizer sentido para o domínio.
- Controle a ordem no Runner com setNextRequest quando o fluxo precisar ser determinístico e “fail fast”.
- Limpe variáveis ao final do fluxo ou ao detectar falhas críticas, reduzindo dependência de estado residual.