O teste de API REST começa pela semântica dos códigos de status
REST atribui significado aos códigos de status, e os clientes dependem desse significado. Vale a pena escrever asserções explícitas em vez de presumir.
201 com um location na criação, não 200 com um corpo e mais nada.
404 para inexistente, 403 para proibido. Retornar 404 para um recurso proibido é uma escolha deliberada que alguns times fazem; retornar 403 para um recurso que não existe é só um bug.
422 ou 400 para entrada inválida, de forma consistente. Escolha um e verifique se todos os endpoints seguem o mesmo.
Nunca 200 com um erro dentro do corpo. É comum, e obriga todo cliente a escrever um tratamento especial.
Idempotência
PUT e DELETE deveriam ser idempotentes. Chamar qualquer um dos dois duas vezes deve deixar o mesmo estado e não gerar erro na segunda chamada. É fácil errar isso e é fácil verificar: chame duas vezes e faça a asserção.
O mesmo vale para um segundo DELETE retornar 404 em vez de 500. Clientes fazem retry, e um endpoint que não suporta retry transforma uma oscilação de rede em uma falha visível para o usuário.
As convenções que o seu serviço afirma seguir
| Paginação | Percorrer a coleção inteira devolve a contagem que ela mesma informa? Erro de um item nos limites de página é extremamente comum. |
| Filtros e ordenação | Um filtro desconhecido é rejeitado ou ignorado em silêncio? Ignorar em silêncio devolve dados errados como se estivessem certos. |
| Atualização parcial | O PATCH altera só o que foi enviado ou, sem avisar, deixa o resto nulo? |
A verificação por trás de todas elas
Faça asserções sobre o corpo, não só sobre o status. Um 200 com uma lista vazia onde deveria haver um registro passa em toda asserção de status já escrita. Esse hábito sozinho encontra mais defeitos reais em teste de API REST do que qualquer verificação de convenção.
Os quatro problemas
Quatro coisas decidem se uma suíte de API sobrevive ao primeiro ano: sessões que expiram, valores que só existem em tempo de execução, chamadas que dependem umas das outras e registros que ninguém limpa. O TestSprite trata disso como Auto-Authentication, Dynamic Variables, Dependency Chains e Auto-Cleanup, descritos na documentação de teste de API.
As convenções que vale a pena colocar no papel primeiro
Antes de testar se a sua API segue as próprias convenções, alguém precisa dizer quais são elas — e a maioria dos times descobre nesse exercício que discorda entre si.
Quatro perguntas resolvem a maior parte disso. Que status uma criação retorna, e ela inclui um location? Um recurso inexistente é 404 ou 403 quando quem chamou não teria permissão de vê-lo de qualquer forma? Um parâmetro de query desconhecido é rejeitado ou ignorado? O PATCH trata um campo ausente como inalterado ou como null?
Nenhuma dessas perguntas tem uma resposta universalmente certa, e todas são escolhas das quais os seus clientes dependem. Escrever as quatro respostas leva vinte minutos e transforma a intenção vaga de ser RESTful em algo sobre o qual você consegue de fato fazer asserções — que é o pré-requisito para qualquer uma delas ser testada.
Conseguir cobertura sem precisar escrever tudo
Os planos gerados cobrem categorias funcionais, de schema, de autorização, de tratamento de erros e de limites a partir de uma especificação ou de uma rodada de descoberta, o que já inclui, por padrão, a maior parte das verificações de convenção acima.
Terminal
npm install -g @testsprite/testsprite-cli
testsprite setup
Se você preferir não instalar nada, o dashboard faz a mesma coisa. Tudo o mais que a linha de comando faz está no repositório do CLI.
Se o pipeline é de outro time, o GitHub App é o caminho de menor resistência: é um webhook, não muda nada no seu repositório e dispara quando o seu build informa que a nova versão está no ar. Se você prefere a verificação visível dentro do repositório, um passo do GitHub Actions faz isso.
Como o TestSprite verifica as convenções
Os planos gerados cobrem categorias funcionais, de schema, de autorização, de tratamento de erros e de limites contra o serviço em execução, o que inclui a maior parte das verificações de convenção acima: semântica de status por operação, rejeição de entrada inválida, comportamento diante de um recurso inexistente e paginação cujas contas fecham.
O Auto-Authentication mantém as sessões vivas durante toda a execução, as Dynamic Variables levam valores de uma chamada para outra, as Dependency Chains derivam a ordem de execução do que cada caso precisa e produz, e o Auto-Cleanup remove exatamente o que aquela execução criou. Esse último importa mais em REST do que as pessoas imaginam, porque verificar idempotência significa chamar de propósito a mesma operação destrutiva duas vezes.
O que você ganha são as suas próprias convenções verificadas a cada mudança, em vez de documentadas e na base da torcida — é isso que impede um endpoint de retornar 200 em silêncio onde todos os outros retornam 201.
Pureza REST importa para os testes?
Só onde os clientes dependem dela. Teste as convenções que o seu serviço afirma seguir, não as que um livro-texto prescreve.
Como testar HATEOAS?
Se você retorna links, verifique se eles resolvem e apontam para onde dizem apontar. Se não retorna, pule essa parte; pouquíssimos serviços realmente implementam isso.
E o GraphQL?
As convenções são completamente outras. Os códigos de status carregam muito menos significado e os erros chegam no corpo por design, então a maior parte das verificações acima não se transfere.
Vale verificar os cabeçalhos de resposta?
O content type, sempre. Cabeçalhos de cache e de rate limit, se os clientes agirem com base neles — algo que vale a pena saber antes de fazer asserções sobre eles.
Vale a pena testar versionamento?
Sim, se você mantém mais de uma versão. Verifique se uma versão antiga continua se comportando como antes, porque essa é a promessa que um número de versão faz.
Teste as promessas que a sua API faz.
O teste de API REST deve verificar as convenções que o seu serviço afirma seguir: semântica de status, idempotência, totais de paginação e se filtros desconhecidos são rejeitados. Por baixo de todas elas, faça asserções sobre o corpo, não apenas sobre o status.