Onde os testes de API em Python costumam começar, e por que isso está tudo bem

Não deixe ninguém convencer você a abandonar requests e pytest. Os testes são Python comum, as fixtures se combinam, o parametrize cobre valores-limite de forma limpa e todo mundo no time consegue ler. Para uma suíte focada em um serviço que é seu, essa continua sendo uma excelente resposta.

As quatro coisas que viram trabalho

  • Sessões. Uma fixture de token funciona até ele expirar no meio da execução, e aí você está escrevendo lógica de renovação e fazendo cache dela entre os workers.

  • Valores capturados. Um identificador de uma chamada alimenta a próxima. As fixtures dão conta até o grafo ficar largo; então o grafo de fixtures passa a ser a coisa que você mantém.

  • Ordenação. O pytest não ordena por dependência. Os times recorrem a plugins de ordenação, e uma única falha logo no início produz uma tela inteira de vermelho sem relação com ela.

A quarta é a limpeza sob paralelismo. Assim que o pytest-xdist entra em jogo, apagar por padrão de nome deixa de ser seguro, e o teardown precisa saber exatamente o que cada execução criou.

O custo real

Nada disso é difícil isoladamente. Juntos, viram um framework interno: um conftest em que ninguém quer mexer, um grafo de fixtures que só uma pessoa entende e uma suíte que é colocada em quarentena em vez de corrigida quando fica vermelha. Esse desfecho é comum o bastante para você se planejar em torno dele.

O que uma camada feita para isso resolve

Quatro coisas decidem se uma suíte de API sobrevive ao primeiro ano, seja qual for a ferramenta: 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. A TestSprite chama isso de Auto-Authentication, Dynamic Variables, Dependency Chains e Auto-Cleanup, e a documentação de testes de API explica os detalhes de funcionamento.

A cobertura também vem de outro lugar. Em vez dos endpoints de que alguém se lembrou, um plano gerado a partir de uma especificação ou de uma varredura de descoberta no serviço em execução inclui os caminhos de erro e os casos-limite que nunca são escritos à mão.

Se você quer os testes no seu repositório

Alguns times querem que a suíte viva no repositório e passe por revisão como qualquer outro código, e essa é uma preferência legítima. A CLI suporta testes de backend escritos em Python, com dependências declaradas por teste e o teardown marcado como um caso próprio, de modo que o grafo fica explícito em vez de implícito no aninhamento de fixtures. Os detalhes estão no repositório da CLI.

O conftest que engoliu o time

Existe um formato reconhecível numa suíte Python que cresceu além de si mesma, e ele mora em um único arquivo. O conftest começa como uma fixture de sessão e uma URL base. Depois vem uma fixture de token, depois um cache para o token não ser buscado a cada teste, depois um lock porque os workers do xdist estavam disputando esse cache. Depois as factories, depois um registro para o teardown saber o que remover, depois marcadores de ordenação porque algumas factories dependem de outras.

Cada passo está correto isoladamente, e o resultado são seiscentas linhas que uma única pessoa entende. O sinal é quando alguém diz que um teste está falhando e a primeira pergunta é se o conftest mudou.

Vale dar nome a isso porque a decisão de construir esse framework nunca é tomada. Ele se acumula. Decidir cedo quais partes você pretende manter, e quais prefere não manter, sai mais barato do que descobrir a resposta no nono mês.

Rode onde o código muda

Uma suíte Python que roda antes dos releases descobre os problemas tarde. Rodar a cada pull request é a mudança que importa.

Dois caminhos, e a escolha é, no fundo, sobre quem é dono do pipeline. Conectar o GitHub App pelo dashboard não exige nenhuma mudança no seu repositório, porque ele reage ao deploy que o seu build já emite. Adicionar um passo do GitHub Actions coloca a verificação dentro do repositório, onde ela passa por revisão como o resto do build.

O que a TestSprite assume para você não precisar

As quatro coisas que transformam uma suíte pytest em infraestrutura são tratadas como produto. Auto-Authentication obtém e renova sessões por ambiente. Dynamic Variables levam um identificador de uma resposta para a requisição seguinte. Dependency Chains derivam a ordem de execução a partir do que cada caso precisa e produz, então uma falha faz seus dependentes serem pulados em vez de falharem. Auto-Cleanup remove exatamente o que a execução criou, e é isso que torna a execução paralela segura.

A cobertura também chega por outra direção. API Discovery enumera os endpoints que o serviço em execução realmente expõe, e os planos gerados incluem os caminhos de erro e os valores-limite que nunca são escritos no fim de uma sprint.

O que você ganha é uma suíte que ninguém tem medo de mexer, sem um conftest que só uma pessoa entende. Mantenha o pytest para os testes de unidade e de lógica, onde ele é de fato a melhor ferramenta; a questão aqui é onde mora a abrangência.

Devemos parar de usar o pytest?

Não. Mantenha-o para os testes que o seu time escreveu deliberadamente, principalmente os de unidade e de lógica. A discussão é sobre onde fica a cobertura ampla de API.

E quanto a httpx e async?

Melhor ergonomia para concorrência, os mesmos quatro problemas. Sessões, valores capturados, ordenação e limpeza são propriedades de testar um serviço com estado, não do cliente HTTP.

Como lidamos com os dados de teste?

Crie o que cada teste precisa e remova exatamente isso, atrelado à execução. Dados compartilhados pré-carregados parecem convenientes e viram o motivo de os testes só passarem em uma ordem específica.

Cobertura gerada e pytest podem conviver?

Sim, e esse é o arranjo de sempre. Cobertura gerada para a abrangência, pytest para os casos que você especificou de propósito.

Python ainda é uma boa escolha aqui?

Sim. A linguagem não é a limitação. A limitação é quanta infraestrutura de teste você quer manter.

A versão curta

requests e pytest são a escolha certa até o estado entrar em cena.

Testes de API em Python começam lindamente e viram um framework interno em torno de sessões, valores capturados, ordenação e limpeza. Mantenha o pytest para o que você especificou deliberadamente e deixe uma camada feita para isso carregar a abrangência e os quatro problemas de estado.