Locust descreve usuários virtuais em Python e mede como um sistema reage à carga. Um bom cenário representa jornadas reais e tem objetivo definido, como encontrar o ponto em que a latência ultrapassa um limite, não apenas produzir o maior número possível de requisições.

Criar um locustfile

python -m pip install locust
from locust import HttpUser, between, task


class Leitor(HttpUser):
    wait_time = between(1, 3)

    @task(3)
    def listar_posts(self) -> None:
        self.client.get("/api/posts", name="GET /api/posts")

    @task
    def abrir_post(self) -> None:
        self.client.get("/api/posts/python", name="GET /api/posts/:slug")

Pesos aproximam a frequência das ações, e wait_time evita um loop irreal sem pausas. Agrupar URLs dinâmicas com name mantém métricas úteis.

Executar com segurança

Comece com poucos usuários e aumente gradualmente. Em CI, o modo headless facilita limites reproduzíveis. Observe percentis de latência, taxa de falhas, throughput e recursos do servidor e também da máquina geradora.

Nunca aponte para produção sem autorização explícita, janela combinada, limites e botão de parada. Remova dados pessoais, use contas próprias para teste e valide o cenário funcionalmente antes da carga.

O artigo de segurança de APIs Python ajuda a revisar riscos, e o guia de métricas com Prometheus mostra observabilidade do servidor.

A documentação oficial do Locust, consultada em 22 de julho de 2026, cobre HttpUser, tarefas, execução headless e carga distribuída. Registre configuração, versão, dados e ambiente para que o resultado possa ser comparado depois.

Definir objetivo e perfil de carga

Comece com uma hipótese verificável: a busca deve sustentar 80 requisições por segundo durante dez minutos, com p95 abaixo de 400 ms e menos de 1% de erros. Isso define jornada, duração e aprovação. Diferencie carga, que verifica volume previsto; estresse, que procura o limite; e resistência, que mantém tráfego para revelar vazamentos ou filas crescentes. Registre commit, infraestrutura, massa de dados e configuração do gerador.

Modelar estado e dados

Jornadas reais exigem autenticação ou dados prévios. on_start prepara cada usuário virtual:

class Comprador(HttpUser):
    wait_time = between(2, 5)

    def on_start(self) -> None:
        resposta = self.client.post(
            "/api/login",
            json={"email": "[email protected]", "senha": "segredo-de-teste"},
            name="POST /api/login",
        )
        resposta.raise_for_status()
        self.token = resposta.json()["token"]

    @task
    def consultar_carrinho(self) -> None:
        self.client.get(
            "/api/carrinho",
            headers={"Authorization": f"Bearer {self.token}"},
            name="GET /api/carrinho",
        )

Use credenciais exclusivas de teste e forneça segredos por variável de ambiente. Não compartilhe uma conta entre milhares de usuários se sessões reais são independentes. Prepare identificadores suficientes e restaure o banco quando o cenário altera estado.

Validar sucesso funcional

Uma API pode responder 200 com corpo incompleto. catch_response classifica o resultado conforme o contrato:

@task
def buscar(self) -> None:
    with self.client.get(
        "/api/busca?q=python",
        name="GET /api/busca",
        catch_response=True,
    ) as resposta:
        if resposta.status_code != 200:
            resposta.failure(f"HTTP {resposta.status_code}")
        elif "itens" not in resposta.json():
            resposta.failure("resposta sem itens")

Mantenha a validação barata para o gerador não virar o gargalo. Regras detalhadas pertencem a testes funcionais; sob carga, verifique apenas o necessário para distinguir sucesso real.

Executar headless com rampa

locust -f locustfile.py \
  --headless \
  --host https://api.staging.example \
  --users 100 \
  --spawn-rate 5 \
  --run-time 10m \
  --csv resultados

--users significa usuários simultâneos, não requisições por segundo. A taxa depende também da espera e da latência. --spawn-rate controla a rampa, não o patamar. Faça antes um ensaio pequeno para conferir autenticação, agrupamento e limpeza. Em CI, aplique limites explícitos e preserve o CSV como evidência.

Interpretar percentis e gargalos

A mediana descreve a requisição central; p95 e p99 mostram a cauda lenta. Leia-os com throughput, falhas e números por endpoint. Correlacione o mesmo intervalo com CPU, memória, conexões, filas e banco. Se o throughput para de crescer enquanto a CPU do gerador satura, o limite pode estar no cliente.

Crie uma linha de base, mude uma variável e repita. Aquecimento de cache, autoscaling e coleta de lixo formam fases distintas. Um relatório confiável preserva a cronologia, não apenas um número favorável.

Distribuir e repetir

Locust coordena um mestre e vários workers quando uma máquina não basta. Todos devem executar a mesma versão e ter relógios sincronizados. Separe geradores da infraestrutura avaliada para não disputar recursos. Monitore sua CPU e confirme que DNS, balanceadores e limites de rede reproduzem o caminho desejado.

Antes do teste, documente autorização, destino, dados, limites e parada de emergência. Durante a execução, observe serviço e geradores. Depois, guarde configuração, commit, horários, CSV e incidentes. O resultado precisa levar a uma decisão: aceitar o limite, investigar um endpoint, ajustar capacidade ou repetir com outra hipótese. Ele fornece evidência sobre condições registradas, não garantia de ausência de falhas.

Evitar conclusões enganosas

Não misture endpoints rápidos e lentos em uma média. Analise cada operação e sua participação na jornada. Confirme se falhas de autenticação, limites de taxa ou cache reduziram artificialmente o trabalho do servidor. Milhares de respostas 401 rápidas não medem a capacidade da operação protegida.

Repita a execução para separar variação normal de regressão. Informe repetições, intervalo observado e mudanças entre elas. Se o ambiente compartilhado recebeu outro tráfego, registre a limitação. Transparência vale mais que falsa precisão.