Você construiu um cenário de teste sólido para seu endpoint de checkout. Ele encadeia três requisições, faz asserções em cada resposta e é aprovado toda vez que você clica em "Executar". Em seguida, seu pipeline precisa cobrir quarenta combinações de entrada, extrair os dados de um arquivo que seu líder de QA mantém e executar o mesmo cenário contra os ambientes de homologação (staging) e produção com credenciais diferentes. A execução "clique e execute" que funcionou no seu laptop não se traduz para isso, e você não quer clonar o cenário quarenta vezes.
Essa "última milha" é o que a linha de comando gerencia. Com o Apidog, você cria um cenário de teste uma única vez no construtor visual e, em seguida, o executa a partir de um terminal com o pacote apidog-cli. A flag que transforma um cenário em uma execução orientada a dados é -d, abreviação de --iteration-data. Ela recebe um arquivo CSV, um arquivo JSON ou um conjunto de dados que você armazenou em seu projeto Apidog, e executa o cenário uma vez por linha, vinculando os valores de cada linha às variáveis que suas requisições referenciam.
Como a flag -d lê um arquivo
O recurso inteiro reside em uma única opção. Aqui estão as formas longa e curta, diretamente de apidog run --help:
-d, --iteration-data <path|testDataId> Define os dados a serem usados para as iterações (JSON ou CSV)
Esse <path|testDataId> é o detalhe que a maioria das pessoas não percebe. O argumento é sobrecarregado. Passe um caminho e o CLI lê um arquivo local do disco. Passe um ID de dados de teste e o CLI puxa um conjunto de dados que você salvou em seu projeto Apidog. A mesma flag, duas fontes, e o executor (runner) descobre qual você forneceu.
A forma de arquivo local é o ponto de partida comum. Aponte-o para um arquivo relativo ao local onde você executa o comando:
apidog run --access-token $APIDOG_ACCESS_TOKEN \
-t 605067 -e 1629989 \
-d ./test-data/checkout-cases.csv -r cli
O CLI abre checkout-cases.csv, conta as linhas abaixo do cabeçalho e executa o cenário 605067 uma vez por linha. Em cada passagem, ele vincula as colunas às variáveis correspondentes em suas requisições, dispara o cenário e registra o resultado dessa iteração. Quarenta linhas, quarenta passagens, um cenário.
O formato segue o arquivo. A mesma flag aceita JSON sem nenhuma opção extra:
apidog run --access-token $APIDOG_ACCESS_TOKEN \
-t 605067 -e 1629989 \
-d ./test-data/checkout-cases.json -r cli
Você não precisa dizer ao CLI qual formato está usando. Ele lê a extensão e a estrutura do arquivo. Isso significa que você pode trocar um CSV por um array JSON no meio do projeto sem precisar alterar o comando, desde que os nomes das colunas e as chaves JSON correspondam às variáveis que seu cenário espera.
O que o CLI espera dentro de cada arquivo
CSV é o formato para casos planos e tabulares. A linha de cabeçalho nomeia suas variáveis. Cada linha abaixo dela é uma iteração. Aqui está um arquivo checkout-cases.csv real para um endpoint de desconto:
sku,quantity,coupon,expected_status,expected_total
DESK-01,1,SAVE10,200,89.10
DESK-01,0,SAVE10,422,0
CHAIR-09,3,,200,447.00
DESK-01,1,EXPIRED,410,0
GHOST-99,1,SAVE10,404,0
Cinco colunas se tornam cinco variáveis. Dentro do corpo da requisição, você escreve {{sku}} e {{quantity}}; nas asserções, você compara a resposta com {{expected_status}} e {{expected_total}}. O executor os vincula por linha. A célula coupon vazia na linha três se torna uma string vazia, que é exatamente o caso sem cupom que você deseja cobrir.
JSON é o formato quando seus casos carregam uma estrutura aninhada que se achata mal em colunas. O arquivo é um array de objetos, um objeto por iteração:
[
{
"label": "valid order, two items",
"order": {
"items": [
{ "sku": "DESK-01", "qty": 1 },
{ "sku": "CHAIR-09", "qty": 2 }
],
"shipping": { "country": "US", "method": "ground" }
},
"expected_status": 200
},
{
"label": "unshippable country",
"order": {
"items": [{ "sku": "DESK-01", "qty": 1 }],
"shipping": { "country": "ZZ", "method": "ground" }
},
"expected_status": 422
}
]
Dentro do cenário, você referencia {{order}} e {{expected_status}} da mesma forma, e o executor entrega os campos de cada objeto para a iteração. O campo label é para você. Ele aparece no relatório para que uma passagem falha mostre "país não enviável" em vez de "iteração 2", o que faz a diferença entre um diagnóstico de cinco segundos e um de cinco minutos.
Algumas regras evitam que esses arquivos causem problemas em sua CI:
- Mantenha os nomes dos cabeçalhos idênticos aos nomes das variáveis em seu cenário. Uma coluna chamada
qtynão será vinculada a uma requisição que lê{{quantity}}. Essa incompatibilidade é o motivo mais comum para uma execução orientada a dados passar localmente e produzir valores vazios no pipeline. - Coloque entre aspas qualquer campo CSV que contenha uma vírgula, ou mova esse arquivo para JSON. Um campo de texto livre com uma vírgula se divide em duas colunas e desloca todos os valores depois dela.
- Coloque o resultado esperado nos dados, não no cenário. A linha um espera 200, a linha quatro espera 410. Se você codificar a expectativa na asserção, estará de volta a um cenário por caso.
- Comite esses arquivos próximos à sua configuração de teste para que eles sejam versionados com o código que eles exercitam. O arquivo de dados é parte do teste, não um artefato solto.
Para o lado do JSONPath na escrita de asserções que leem esses valores vinculados, definindo asserções e extraindo variáveis de uma resposta JSON detalha a sintaxe.
Executando a partir de um conjunto de dados armazenado em vez de um arquivo
A segunda forma de -d é aquela que não aparece na maioria dos tutoriais. Em vez de um caminho, você passa um ID de dados de teste:
apidog run --access-token $APIDOG_ACCESS_TOKEN \
-t 605067 -e 1629989 \
-d 38291 -r cli
Agora o CLI busca o conjunto de dados com esse ID do seu projeto Apidog, em vez de ler um arquivo do disco do executor. Isso é útil quando os dados vivem com a equipe, não com o repositório. Seu líder de QA mantém a tabela de casos dentro do Apidog, edita-a no aplicativo, e cada execução de CI pega a versão atual sem que ninguém precise fazer um commit de um CSV.
A troca é onde reside sua fonte da verdade. Um CSV versionado fornece um conjunto de dados que pode ser comparado em pull requests e fixado ao commit que está sendo testado. Um ID de dados de teste armazenado fornece uma única tabela compartilhada que todos editam em um só lugar. Nenhuma das abordagens está errada. Escolha o arquivo versionado quando os dados devem se mover em sincronia com o código, e o ID armazenado quando os dados são de propriedade de pessoas que não mexem no repositório.
Executando offline a partir de um arquivo exportado
Há uma terceira maneira de alimentar o CLI, e ela muda a forma do comando inteiro. Você pode exportar um caso de teste do Apidog como um arquivo autocontido e executar esse arquivo diretamente, sem ID de cenário e sem uma viagem de rede para buscar o cenário:
apidog run ./checkout.apidog-cli.json -r cli,html
Aqui, o primeiro argumento é uma `file-source` (fonte de arquivo), o próprio caso de teste exportado, não uma flag. O CLI executa o que está no arquivo. Você ainda pode adicionar dados de iteração com `-d`:
apidog run ./checkout.apidog-cli.json -d ./checkout-cases.csv -r cli,junit
Isso é importante para duas situações. A primeira é um executor de CI isolado ou restrito que não consegue acessar a nuvem do Apidog para resolver um ID de cenário; o arquivo exportado contém tudo o que a execução precisa. A segunda é a reprodutibilidade: o arquivo exportado é um "snapshot" congelado do cenário no momento da exportação, então uma execução a partir dele não é afetada por alguém que edite o cenário no aplicativo posteriormente. Para a instalação e os mecanismos de primeira execução, o guia de instalação do Apidog CLI aborda a colocação do binário, e a referência completa do Apidog CLI documenta todas as flags em uma tabela.
Emparelhando -d com -n e sobrescrições de variáveis
Execuções orientadas a dados raramente viajam sozinhas. Três flags se emparelham constantemente com -d.
-n, --iteration-count define quantas vezes o cenário é executado. Quando você fornece um arquivo de dados, a contagem de linhas já impulsiona as iterações, então você geralmente omite -n e deixa o arquivo decidir. Você usa -n principalmente quando deseja executar a tabela mais de uma vez, ou quando está executando sem um arquivo de dados, como um teste de soak que repete um cenário fixo:
apidog run --access-token $APIDOG_ACCESS_TOKEN -t 605067 -e 1629989 -n 50 -r cli
--env-var e --global-var injetam pares key=value em tempo de execução sem tocar no ambiente do seu projeto. É assim que você mantém segredos e configurações por pipeline fora do cenário e do arquivo de dados. O arquivo de dados contém os casos de teste; as sobrescrições contêm as coisas que mudam a cada execução:
apidog run --access-token $APIDOG_ACCESS_TOKEN \
-t 605067 -e 1629989 \
-d ./test-data/checkout-cases.csv \
--env-var "base_url=https://staging.internal" \
--global-var "api_key=$RUNTIME_API_KEY" \
-r cli,junit
A divisão é intencional. Os dados de iteração são a parte da execução que é a mesma em todos os lugares: os casos que seu endpoint deve lidar. As sobrescrições de variáveis são a parte que muda por ambiente: o host, a chave, o locatário. Mantenha as credenciais em seu armazenamento secreto de CI e passe-as via --global-var de uma variável de ambiente, da forma como $RUNTIME_API_KEY faz acima. Nunca as insira no CSV, onde qualquer pessoa com acesso ao repositório pode lê-las.
Lendo resultados por iteração
Uma execução orientada a dados é útil apenas se você puder identificar qual linha falhou. As flags do reporter decidem o que você recebe de volta.
apidog run --access-token $APIDOG_ACCESS_TOKEN \
-t 605067 -e 1629989 \
-d ./test-data/checkout-cases.csv \
-r cli,junit --out-dir ./test-reports
-r cli imprime um resumo legível por iteração no terminal, que é o que você escaneia em um log de build. -r junit escreve um XML JUnit, o formato que quase todos os dashboards de CI analisam em uma árvore de aprovação/reprovação, então uma linha falha aparece como um teste nomeado com falha em vez de texto de log enterrado. Você também pode passar html e json; html fornece um relatório navegável para arquivar como um artefato de build, e json fornece uma saída estruturada bruta se você pós-processar os resultados. --out-dir controla onde os arquivos são armazenados para que você possa mantê-los como artefatos.
Por padrão, a execução para na primeira asserção quebrada. Para uma tabela de dados ampla, isso geralmente não é o ideal, porque você quer ver todas as linhas que falharam em uma única passagem, e não corrigir uma e reexecutar para encontrar a próxima. Altere o comportamento com --on-error:
apidog run --access-token $APIDOG_ACCESS_TOKEN \
-t 605067 -e 1629989 \
-d ./test-data/checkout-cases.csv \
--on-error continue \
-r cli,junit --out-dir ./test-reports
--on-error continue executa cada iteração mesmo quando as anteriores falham, para que um único relatório mostre que as linhas dois, sete e dezenove estão quebradas de uma só vez. A execução ainda termina com um código de saída diferente de zero se algo falhar, então ela continua sendo um verdadeiro portão. --on-error end é o padrão de falha rápida para uma verificação rápida de fumaça; ignore é para o raro passo conhecido como "flaky" que você não quer que atrapalhe a execução.
Depurando uma vinculação que silenciosamente não faz nada
O modo de falha que mais consome tempo em execuções orientadas a dados não é uma asserção vermelha. É uma execução verde que não testou nada, porque os dados nunca foram vinculados à requisição. A requisição foi disparada com valores vazios, o endpoint retornou um 200 para um payload vazio e a asserção, por acaso, passou. A cobertura parece boa; mas não está.
Quando uma execução orientada a dados se comporta de forma estranha, adicione --verbose:
apidog run --access-token $APIDOG_ACCESS_TOKEN \
-t 605067 -e 1629989 \
-d ./test-data/checkout-cases.csv \
--verbose -r cli
--verbose imprime a requisição e a resposta completas para cada iteração. Observe o corpo da requisição que o executor realmente enviou. Se você vir {{sku}} lá, não substituído, ou um valor em branco quando a célula do CSV não estava, a vinculação falhou. Três causas comuns, na ordem de quão frequentemente elas ocorrem:
- O nome da coluna e o nome da variável não correspondem. O cabeçalho do CSV é
product_skue a requisição lê{{sku}}. Renomeie um para que sejam idênticos. - Uma vírgula perdida dividiu uma linha CSV. Um campo de texto livre sem aspas deslocou cada coluna depois dele, então
expected_statusagora contém o que deveria estar na próxima coluna. Coloque o campo entre aspas ou mude o arquivo para JSON. - O caminho para o arquivo de dados está errado em relação ao diretório de trabalho na CI. Ele se resolve bem no seu laptop e silenciosamente não lê nada no pipeline. Use um caminho relativo à raiz do repositório que a etapa de checkout produz, e confirme se o arquivo existe em uma etapa antes da execução.
A regra geral: quando as iterações passam, mas você suspeita que não deveriam, leia uma requisição verbosa antes de confiar no verde. Um teste que é executado contra uma entrada vazia é pior do que nenhum teste, porque ele diz que tudo está bem enquanto o endpoint permanece sem ser testado.
Conectando-o à CI
A recompensa é que a tabela inteira é executada a cada alteração, sem que ninguém precise clicar em "Executar". Aqui está um trabalho do GitHub Actions que instala o CLI e executa um cenário orientado a CSV em cada pull request:
name: Data-driven API tests
on: [pull_request]
jobs:
api-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install Apidog CLI
run: npm install -g apidog-cli
- name: Run data-driven scenario
env:
APIDOG_ACCESS_TOKEN: ${{ secrets.APIDOG_ACCESS_TOKEN }}
run: |
apidog run --access-token $APIDOG_ACCESS_TOKEN \
-t 605067 -e 1629989 \
-d ./test-data/checkout-cases.csv \
--on-error continue \
-r cli,junit --out-dir ./test-reports
- name: Upload report
if: always()
uses: actions/upload-artifact@v4
with:
name: api-test-report
path: ./test-reports
O token vem de secrets.APIDOG_ACCESS_TOKEN, definido uma vez nas configurações do repositório. --on-error continue coleta todas as linhas que falham em um único relatório em vez de parar na primeira. O if: always() no upload mantém o relatório mesmo quando a execução falha, que é quando você mais deseja lê-lo. Troque o caminho do CSV por um arquivo JSON, ou por um ID de conjunto de dados armazenado, e nada mais muda.
Os mesmos três passos se aplicam a qualquer sistema de CI: instalar Node.js e o CLI, expor o token como uma variável de ambiente, chamar apidog run com -d. GitLab CI, Jenkins, CircleCI e os demais não precisam de uma reescrita dos seus testes por plataforma. Para um passo a passo mais aprofundado do lado do Actions, veja automação de testes de API no GitHub Actions, e para a superfície completa das flags do CLI em relação a reporters, tratamento de erros e TLS, o guia completo do Apidog CLI apresenta todas as opções.
Um fluxo de trabalho que escala sem aumentar o teste
Comece com um cenário e três linhas. Construa o cenário no aplicativo com referências de variáveis nas requisições e o resultado esperado nas asserções. Escreva um CSV com um caminho feliz, uma falha conhecida e um caso de limite. Execute-o localmente com -d até que todas as três iterações se comportem.
Em seguida, aumente os dados, não o cenário. Cada relatório de bug se torna uma nova linha com sua saída esperada correta. O bug se transforma em um caso de regressão permanente, e você nunca escreveu um novo teste; você adicionou uma linha a um arquivo. Ao longo de alguns meses, esse arquivo coleta as verdadeiras dificuldades que seu endpoint enfrenta em produção.
Finalmente, insira o comando apidog run -d na CI com --on-error continue e o relatório junit. Agora, uma mudança que quebra a linha do cupom expirado falha na build no momento em que é enviada, com uma iteração nomeada apontando diretamente para o caso quebrado. O cenário permanece uma coisa pequena e legível, não importa quão ampla a tabela se torne. Essa é a vantagem cumulativa: a cobertura cresce com a entrada de dados, e a manutenção permanece constante.
Se você ainda está decidindo se um executor de linha de comando como este se encaixa em sua pilha em vez de uma estrutura "code-first", a análise em qual ferramenta escolher para testes de API orientados a dados com CSV ou JSON compara as abordagens, e Apidog CLI vs Newman aborda o análogo mais próximo da linha de comando do mundo do Postman.
Perguntas Frequentes
A flag -d pode aceitar tanto um caminho de arquivo quanto um conjunto de dados armazenado? A flag -d aceita apenas um por execução: um caminho CSV ou JSON local, ou um ID de dados de teste que aponta para um conjunto de dados salvo em seu projeto Apidog. Você passa um único valor. Use o caminho do arquivo quando os dados devem ser versionados com seu repositório, e o ID armazenado quando uma tabela compartilhada vive no aplicativo e você não deseja commitar uma cópia.
Preciso informar ao CLI se meu arquivo é CSV ou JSON? Não. O executor lê o formato do próprio arquivo, então a mesma flag -d lida com ambos. Mantenha os nomes das suas colunas (CSV) ou chaves de objeto (JSON) correspondendo aos nomes das variáveis que seu cenário referencia, e você pode alternar os formatos sem mudar o comando.
O que acontece se eu usar -d e -n juntos? A contagem de linhas do arquivo de dados determina o número de iterações, então -n geralmente é desnecessário com -d. Recorra a -n quando quiser repetir uma execução sem um arquivo de dados, como um teste de soak, ou quando especificamente quiser executar a tabela inteira mais de uma vez.
Por que minha execução orientada a dados passou sem testar nada? A causa mais comum é uma vinculação que nunca aconteceu: um nome de coluna que não corresponde ao nome da variável, ou um caminho de arquivo incorreto na CI que não leu nada. Execute uma vez com --verbose e inspecione o corpo da requisição que o CLI enviou. Se você vir {{variáveis}} não substituídas ou valores em branco, corrija a incompatibilidade do nome ou o caminho antes de confiar no resultado verde.
Como mantenho as credenciais fora do meu arquivo de dados? Mantenha tokens e chaves completamente fora do CSV ou JSON. Passe-os em tempo de execução com --global-var ou --env-var do seu armazenamento secreto de CI, da mesma forma que você passaria --global-var "api_key=$RUNTIME_API_KEY". O arquivo de dados deve conter entradas de teste e resultados esperados, nada que autentique a execução.
Posso executar os mesmos dados em ambientes de homologação (staging) e produção? Sim. Mantenha o cenário e o arquivo de dados fixos e altere o alvo com -e. Aponte uma verificação de pull request para um ID de ambiente de homologação e um teste de fumaça pós-implantação para produção usando o mesmo cenário e os mesmos dados, apenas um valor -e diferente. Separar o ambiente dos dados é a razão principal pela qual isso funciona.
Conclusão
A flag -d é a essência da história orientada a dados para o Apidog CLI, e é mais flexível do que parece à primeira vista. Ela lê um arquivo CSV ou JSON local, ou um conjunto de dados armazenado em seu projeto por ID. Ela se combina com -n para repetições, com --env-var e --global-var para configurações por execução, e com --on-error continue para que uma única execução revele todas as linhas que falham. Execute-o a partir de um ID de cenário online ou de um arquivo exportado offline, e leia os resultados por iteração através dos reporters junit e cli.
Crie o cenário uma vez, descreva cada caso como uma linha e deixe o executor expandir sua cobertura toda vez que alguém adicionar uma linha ao arquivo. Baixe o Apidog, aponte apidog run para o seu primeiro arquivo de dados e transforme um único cenário em uma tabela de casos que é executada a cada push.
