A tela pode esconder o problema
Imagine que a interface impeça o usuário de digitar quantidade 0. À primeira vista, parece resolvido.
Mas e se alguém enviar essa mesma informação diretamente ao servidor?
Uma validação feita apenas na tela melhora a experiência do usuário, mas não garante que a regra esteja protegida em todas as entradas do sistema.
O caminho de um pedido
Quando uma dessas partes envia, interpreta ou grava algo de forma incorreta, podemos ter um problema de integração.
API: um ponto de comunicação entre partes
Interface de Programação de Aplicações (Application Programming Interface — API)
É uma forma organizada de um software disponibilizar operações e dados para que outra parte do sistema possa se comunicar com ele.
Na Cantina Horizonte, a interface usa endereços como:
GET /api/produtos
POST /api/pedidosGET e POST são métodos do protocolo HTTP. HTTP significa Hypertext Transfer Protocol, em português Protocolo de Transferência de Hipertexto. Aqui basta entender que esses métodos indicam tipos diferentes de operação.
Neste módulo, não vamos transformar essa etapa num curso de desenvolvimento de API. O servidor já está pronto. Nosso foco é testar a comunicação.
Uma ferramenta entra porque agora precisamos dela
Até aqui, a tela bastava para várias atividades. Agora queremos enviar requisições diretamente ao servidor, escolhendo exatamente os dados.
Bruno
É um cliente de API: um programa que permite montar requisições, enviá-las ao servidor e observar a resposta sem depender da interface visual da aplicação.
Assim podemos testar o servidor mesmo quando a tela bloqueia determinada entrada.
Prepare o laboratório
- Na pasta
qts/cantina-horizonte-v1, inicie a Cantina cominiciar_windows.batou com o comando indicado no README. - Confirme no navegador que
http://127.0.0.1:8000abriu. - Abra o Bruno. Se ainda não estiver instalado, use a página oficial: Download do Bruno →.
- No Bruno, crie uma coleção chamada Cantina Horizonte.
Vamos manter o servidor aberto enquanto enviamos as requisições.
Primeiro, uma requisição simples
No Bruno, crie uma requisição e envie:
GET http://127.0.0.1:8000/api/produtosO servidor deve responder com a lista de produtos.
O número 200 indica que a requisição foi atendida com sucesso. Ele é um código de status HTTP: um número que resume o resultado da requisição.
Agora crie um pedido sem usar a tela
Envie uma requisição POST para:
http://127.0.0.1:8000/api/pedidosNo corpo da requisição, envie:
{
"itens": [
{
"produto_id": 3,
"quantidade": 2
}
]
}Esse texto está no formato JSON, sigla de JavaScript Object Notation. É um formato textual muito usado para transportar dados entre sistemas.
Se o pedido for criado corretamente, a aplicação responde com código 201.
O código de status também faz parte do comportamento
| Código | Como usamos nesta aplicação |
|---|---|
| 200 | Operação atendida com sucesso, como consultar produtos. |
| 201 | Um novo pedido foi criado. |
| 400 | A requisição chegou com a estrutura esperada, mas viola uma regra tratada pela aplicação. |
| 404 | O recurso procurado não foi encontrado, como um produto inexistente. |
| 422 | O FastAPI pode usar esse código quando os dados recebidos não possuem a estrutura ou o tipo esperado. |
Não é necessário decorar todos os códigos HTTP existentes. Aqui estamos aprendendo a comparar o que a API deveria responder com o que realmente respondeu.
Teste uma regra que a tela poderia esconder
Envie quantidade 0 diretamente ao servidor:
{
"itens": [
{
"produto_id": 3,
"quantidade": 0
}
]
}Pela RF-03, o resultado esperado é rejeitar a operação.
Se você já corrigiu a função validar_quantidade durante as práticas anteriores, deve receber código 400. Se estiver com a versão original v1, o servidor pode aceitar o pedido. Nesse caso, você acabou de revelar o mesmo defeito sem passar pela interface.
Integração também significa verificar o efeito no banco
Uma resposta 201 não prova sozinha que tudo aconteceu corretamente.
Suponha que o Salgado tenha estoque 10 e você crie um pedido com quantidade 3. Depois da criação, esperamos encontrar estoque 7.
Pedido criado + estoque atualizado corretamente é uma evidência mais forte da integração do que olhar apenas a resposta da criação.
Um defeito que aparece só quando olhamos a sequência
Antes deste cenário, volte aos dados iniciais. Encerre o servidor com Ctrl+C, execute resetar_dados_windows.bat e inicie a Cantina novamente. O Sanduíche deve voltar ao estoque 8.
Agora envie um pedido com quantidade 10.
{
"itens": [
{
"produto_id": 4,
"quantidade": 10
}
]
}A quantidade 10 está dentro do limite máximo por item, mas ultrapassa o estoque disponível.
Pela RF-04, o pedido deveria ser rejeitado. Depois da tentativa, consulte os produtos novamente e observe o estoque.
O servidor protegeu a regra de estoque ou apenas aceitou os dados e atualizou o banco?
Contrato: combinar a forma da conversa
A interface pode enviar:
{ "quantidade": 2 }mas o servidor pode esperar:
{ "qtd": 2 }Mesmo que os dois lados estejam “funcionando”, eles não conseguem conversar porque não concordam sobre a estrutura.
Contrato da API
É o conjunto de combinações sobre como a comunicação deve acontecer: endereços, métodos, dados enviados, dados recebidos e respostas esperadas.
Teste de integração não precisa começar pelo sistema inteiro
Podemos testar apenas a conversa entre servidor e banco, ou entre uma regra e outra parte do sistema. Quanto menor o recorte necessário para responder à pergunta, mais fácil costuma ser localizar a origem do problema.
Isso retoma o que aprendemos na Etapa 7: níveis diferentes respondem perguntas diferentes.
Depois do manual, automatize uma verificação
Também podemos usar o pytest para chamar a API automaticamente. Um teste pode ter esta ideia:
def test_api_deve_rejeitar_quantidade_zero(client):
resposta = client.post(
"/api/pedidos",
json={"itens": [{"produto_id": 3, "quantidade": 0}]}
)
assert resposta.status_code == 400O objeto client representa um cliente de teste preparado para conversar com a aplicação. Vamos manter a configuração pronta quando transformarmos essa ideia em uma suíte de integração; o foco agora é perceber que o mesmo caso manual pode ser automatizado.
Um cuidado importante: banco de teste
Testes de integração podem criar pedidos, alterar estoque e mudar status. Por isso, não devemos executar experiências desse tipo em dados reais.
Ambiente de teste precisa ter dados controlados e poder ser restaurado. É por isso que a Cantina Horizonte possui um comando próprio para voltar aos dados iniciais.
Use o roteiro prático
Preparei uma sequência curta para executar no Bruno, começando por uma consulta simples e chegando aos cenários de quantidade e estoque.
Roteiro de API
Prática · não olhe apenas para a resposta
- liste os produtos e anote o estoque de um item;
- crie um pedido válido pela API;
- consulte os produtos novamente e confira o novo estoque;
- envie um produto inexistente e compare o código obtido com o esperado;
- teste quantidade 0;
- teste uma quantidade permitida pelo limite máximo, mas maior que o estoque;
- registre método, dados enviados, status recebido, resposta e resultado final.
Mas ainda existe uma parte que não testamos
Agora sabemos testar função, servidor, API, banco e integração.
Mesmo assim, o usuário não trabalha enviando JSON no Bruno. Ele clica, digita, muda quantidades e finaliza pela interface.
E se todas as partes passarem separadamente, mas o fluxo real do usuário ainda estiver errado?
Antes de seguir
Você deve conseguir explicar:
- o que significa API e por que testá-la diretamente;
- por que uma resposta de sucesso não basta para provar que a integração com o banco funcionou;
- o papel básico dos códigos 200, 201, 400, 404 e 422 nesta aplicação;
- por que testes de integração devem usar dados controlados;
- como uma regra pode funcionar em uma parte e falhar quando os componentes se comunicam.