O cargo-nextest é a escolha mais prática para executar suítes Rust grandes com melhor isolamento, paralelismo, filtros e relatórios de CI. Instale com cargo install cargo-nextest --locked, rode cargo nextest run na raiz do projeto e mantenha cargo test --doc se a base possui doctests. A migração deve ser gradual: compare a seleção e os resultados dos dois runners antes de trocar o comando obrigatório do pipeline.
O nextest não torna um teste individual magicamente mais rápido. O ganho vem da forma como a suíte é organizada e executada: cada teste roda em seu próprio processo, o scheduler distribui trabalho entre CPUs, falhas ficam isoladas e a configuração permite tratar testes lentos, retries e geração de relatórios sem encher o workflow de shell.
Este guia mostra como usar cargo-nextest em 2026 no computador e na CI, com filtros, perfis, JUnit, timeouts e uma estratégia segura para sair do cargo test. Se você ainda está estruturando a qualidade do projeto, comece pelo guia de testes em Rust e consulte também as ferramentas essenciais do Cargo.
O que é cargo-nextest
O Cargo já oferece um runner integrado por meio de cargo test. Ele compila os targets de teste, encontra funções marcadas com #[test] e executa os binários gerados. Para muitos projetos, isso é suficiente e continua sendo o ponto de partida correto.
O cargo-nextest trabalha sobre os artefatos de teste produzidos pelo Cargo, mas substitui a etapa de execução por um runner especializado. Entre os recursos mais úteis estão:
- execução de cada teste em um processo separado;
- agendamento paralelo da suíte;
- filtros por nome, pacote, binário e plataforma;
- retries configuráveis para casos realmente transitórios;
- detecção e encerramento de testes lentos;
- perfis diferentes para desenvolvimento e CI;
- geração de relatório JUnit;
- saída que destaca falhas sem misturar todo o log da suíte;
- particionamento da execução para pipelines distribuídos.
O isolamento por processo merece atenção. Se um teste aborta, vaza estado global ou interfere no ambiente, a falha tende a ficar contida naquele processo. Isso não elimina problemas de concorrência em recursos compartilhados — banco, porta TCP, arquivo temporário ou serviço externo —, mas reduz o acoplamento existente quando vários testes vivem no mesmo processo.
cargo test vs cargo nextest
A decisão não precisa ser ideológica. Use cada ferramenta pelo papel que resolve melhor.
| Critério | cargo test | cargo nextest |
|---|---|---|
| Disponibilidade | Incluído no Cargo | Instalação adicional |
| Execução padrão | Runner oficial do Rust | Runner especializado |
| Isolamento | Testes do binário compartilham processo | Um processo por teste |
| Filtros | Nome e opções do test harness | Expressões por teste, pacote, binário e plataforma |
| Retries | Exigem lógica externa | Configuráveis por perfil e override |
| JUnit | Exige ferramenta complementar | Suporte de relatório pelo perfil |
| Doctests | Executados por cargo test --doc | Devem ser tratados separadamente no fluxo comum |
| Melhor encaixe | Projetos simples e compatibilidade universal | Workspaces, suítes grandes e CI estruturada |
A diferença mais importante é operacional. cargo test está disponível em qualquer instalação padrão e deve continuar passando. O nextest melhora a experiência de execução, principalmente quando o projeto tem muitos crates, testes de integração ou necessidade de relatórios consumidos pelo servidor de CI.
Como instalar cargo-nextest
Quem já instalou Rust pelo rustup pode compilar a ferramenta a partir do ecossistema Cargo:
cargo install cargo-nextest --locked
cargo nextest --version
--locked pede que a instalação respeite o lockfile publicado pelo pacote. Em máquinas de desenvolvimento isso oferece um caminho simples, embora a compilação inicial possa demorar.
Em CI, compilar a ferramenta em todo job desperdiça tempo. Prefira uma ação ou instalador dedicado, um cache confiável ou uma imagem interna que fixe a versão esperada. O objetivo é evitar que o runner mude sem revisão e, ao mesmo tempo, não transformar cada pipeline em uma compilação de ferramenta.
Depois da instalação, entre em um projeto Rust:
cargo nextest list
cargo nextest run
O primeiro comando lista o conjunto descoberto. O segundo compila o necessário e executa a suíte. Em um workspace, o nextest usa os metadados do Cargo para reconhecer packages e targets.
Primeiro fluxo recomendado
Antes de alterar a CI, estabeleça uma linha de base:
cargo test --workspace
cargo nextest list
cargo nextest run --workspace
cargo test --doc --workspace
Compare:
- quais packages foram compilados;
- quantos testes foram selecionados;
- quais variáveis de ambiente são necessárias;
- se algum teste depende de ordem ou estado global;
- se existem doctests relevantes;
- se a suíte abre portas ou compartilha banco de dados;
- se o resultado é igual em execução local e na CI.
Um teste que passa somente porque outro rodou antes possui dependência implícita. A execução isolada do nextest costuma revelar esse tipo de fragilidade. Corrija o setup do teste em vez de forçar uma ordem global.
Como executar um teste específico
Para uma busca rápida por nome, use uma expressão test():
cargo nextest run -E 'test(login_com_token_expirado)'
Confira a seleção antes de gastar tempo com a execução:
cargo nextest list -E 'test(login_com_token_expirado)'
Também é possível selecionar um package:
cargo nextest run -E 'package(api)'
Ou combinar critérios:
cargo nextest run -E 'package(api) and test(auth)'
Para excluir uma parte conhecida da suíte:
cargo nextest run -E 'not test(e2e_)'
As expressões são mais precisas do que encadear vários grep no pipeline. Elas também ajudam a documentar a intenção: “testes do package API relacionados a autenticação” é uma seleção compreensível por quem revisa o workflow.
Os nomes e predicados disponíveis devem ser conferidos na versão instalada, especialmente quando o filtro depende de plataforma, binário ou tipo de target. Use cargo nextest list como verificação, não apenas como comando de curiosidade.
Configurando .config/nextest.toml
A configuração do projeto fica normalmente em .config/nextest.toml. Um ponto de partida para CI:
[profile.ci]
retries = 0
fail-fast = false
slow-timeout = { period = "60s", terminate-after = 2 }
[profile.ci.junit]
path = "target/nextest/ci/junit.xml"
A execução passa a informar o perfil:
cargo nextest run --profile ci
Esse exemplo toma decisões conservadoras:
- sem retries globais, para não esconder falhas reais;
- fail-fast desativado, para coletar mais falhas em uma única rodada;
- um teste que ultrapassa o período é marcado como lento e pode ser encerrado após repetições do limite;
- o relatório JUnit é salvo dentro de
target/nextest/.
No desenvolvimento local, o perfil padrão pode continuar mais simples:
cargo nextest run
Evite copiar uma configuração enorme antes de entender a suíte. Comece com um perfil de CI, observe os problemas e adicione overrides somente para categorias que realmente exigem tratamento diferente.
Retries sem esconder testes flaky
Retry é útil quando a falha é transitória e a equipe já entende sua causa: uma integração controlada pode sofrer uma indisponibilidade curta, por exemplo. Ele é perigoso quando vira maquiagem para teste não determinístico.
Uma política saudável:
- mantenha
retries = 0como padrão; - identifique o teste flaky e abra uma correção;
- aplique retry somente ao conjunto necessário;
- registre a tentativa repetida nos artefatos da CI;
- remova a exceção quando a causa for corrigida.
Um override conceitual pode selecionar testes por expressão e mudar o comportamento apenas para eles:
[[profile.ci.overrides]]
filter = 'test(integracao_servico_legado)'
retries = 2
Valide a sintaxe com a versão usada no projeto. Mais importante: nunca use dezenas de tentativas para transformar instabilidade em “verde”. O pipeline perde credibilidade quando uma regressão pode falhar várias vezes e ainda ser aceita.
Para técnicas que ajudam a encontrar entradas inesperadas de forma determinística, veja property-based testing e fuzzing em Rust.
Testes lentos, timeouts e concorrência
Uma suíte pode ficar presa por deadlock, espera de rede, processo filho ou timeout ausente. O slow-timeout torna esse comportamento visível e permite encerrar testes que ultrapassam a política do projeto.
Antes de reduzir o limite agressivamente, meça. Um teste de integração que sobe PostgreSQL e executa migrações possui custo diferente de um teste unitário de parser. O ideal é separar categorias e criar infraestrutura previsível.
Se vários testes usam o mesmo recurso, considere:
- um banco ou schema independente por teste;
- portas dinâmicas em vez de números fixos;
- diretórios criados com bibliotecas de arquivos temporários;
- fixtures imutáveis;
- locks apenas ao redor do recurso que não pode ser isolado;
- redução intencional da concorrência para um grupo específico.
Não confunda “o runner executa em paralelo” com “todos os testes devem acessar a mesma instância simultaneamente”. A suíte precisa declarar e controlar seus recursos.
cargo-nextest no GitHub Actions
Um job enxuto pode instalar a toolchain, o nextest e executar os perfis do projeto:
name: Testes Rust
on:
push:
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- uses: taiki-e/install-action@nextest
- name: Executar suíte
run: cargo nextest run --workspace --profile ci
- name: Executar doctests
run: cargo test --doc --workspace
- name: Publicar relatório
if: always()
uses: actions/upload-artifact@v4
with:
name: nextest-junit
path: target/nextest/ci/junit.xml
A etapa if: always() preserva o relatório mesmo quando um teste falha. Isso facilita investigar a causa pelo artefato da execução.
Fixe versões de actions conforme a política de segurança da organização. Em ambientes mais rigorosos, use hashes de commit auditados em vez de somente tags. O guia de CI/CD para Rust cobre também formatação, Clippy, cache e builds para diferentes targets.
Como usar na Gitea Actions e em outras CIs
O conceito não depende do GitHub Actions. Em Gitea Actions, GitLab CI, Jenkins ou outro executor Linux, você precisa de quatro passos:
- disponibilizar a toolchain Rust;
- restaurar caches adequados;
- instalar uma versão conhecida do nextest;
- executar
cargo nextest run --profile cie guardar os relatórios.
Um shell genérico seria:
set -euo pipefail
cargo nextest --version
cargo nextest run --workspace --profile ci
cargo test --doc --workspace
O comando de instalação deve ficar na preparação da imagem ou em etapa cacheada. Não baixe um binário sem verificar origem, versão e integridade. Ferramentas de teste também fazem parte da segurança da cadeia de dependências Rust.
Particionando uma suíte grande
Quando um único runner não é suficiente, o nextest pode participar de uma estratégia de particionamento. A ideia é distribuir conjuntos diferentes de testes entre jobs, sem simplesmente executar a suíte inteira várias vezes.
Existem duas abordagens comuns:
- por package ou domínio: API, worker, biblioteca e testes end-to-end em jobs separados;
- por partição calculada: o runner divide a lista para diferentes índices do matrix.
Antes de distribuir, reduza o custo de compilação. Vários jobs podem repetir o mesmo build e consumir mais tempo total do que um job maior. Cache, artefatos compilados, arquitetura do workspace e duração de cada teste influenciam a decisão.
Para a maioria dos projetos, comece com um único job paralelo. Particione somente quando os dados da CI mostrarem que a etapa de execução — e não a compilação — domina o tempo.
Armadilhas comuns na migração
Esquecer os doctests
Se o projeto usa exemplos em documentação como testes, mantenha:
cargo test --doc --workspace
Uma pipeline que troca cargo test por nextest sem revisar doctests pode deixar de validar exemplos públicos da biblioteca.
Testes dependentes de ordem
A ordem não deve preparar estado para o teste seguinte. Cada teste precisa criar e limpar sua fixture ou usar dados isolados.
Estado compartilhado no sistema operacional
Variáveis de ambiente, diretório atual, portas e arquivos podem gerar disputa. O processo separado não resolve um banco compartilhado com a mesma chave primária.
Retries globais
Aplicar retries a toda a suíte aumenta custo e mascara regressões. Restrinja exceções e acompanhe-as como dívida técnica.
Instalação flutuante na CI
Instalar “a versão mais recente” em cada execução pode mudar o pipeline sem alteração no repositório. Fixe a versão ou controle a imagem usada.
Filtros que não selecionam o esperado
Sempre confira com cargo nextest list -E '...'. Um filtro silenciosamente estreito pode deixar testes importantes fora do job.
Estratégia de adoção em cinco etapas
Use este roteiro para uma migração reversível:
- Instale localmente e rode
cargo nextest list. - Compare com
cargo testem todo o workspace. - Corrija testes acoplados, recursos compartilhados e dependências de ordem.
- Adicione um job não bloqueante na CI durante alguns dias ou ciclos de pull request.
- Promova o job a obrigatório, mantendo doctests e qualquer verificação não coberta.
Depois da migração, registre os comandos no README ou no guia de contribuição:
cargo fmt --check
cargo clippy --workspace --all-targets -- -D warnings
cargo nextest run --workspace
cargo test --doc --workspace
Essa sequência dá à equipe um contrato claro. Para entender os diagnósticos no editor antes de chegar à CI, configure o rust-analyzer.
cargo-nextest ajuda na carreira?
Saber instalar uma ferramenta não é, sozinho, um diferencial forte. O valor profissional está em demonstrar que você entende confiabilidade de pipeline: testes isolados, relatórios úteis, investigação de flakiness, controle de recursos, cache e feedback rápido para pull requests.
Em um portfólio, você pode mostrar isso com:
- uma suíte unitária e de integração bem separada;
.config/nextest.tomlpequena e comentada;- relatório JUnit publicado pela CI;
- doctests mantidos;
- README com comandos reproduzíveis;
- uma decisão documentada sobre retries e timeouts.
Esse tipo de maturidade é relevante para vagas Rust backend, infraestrutura, sistemas e bibliotecas. O guia de portfólio GitHub para Rust ajuda a apresentar essas escolhas sem transformar o repositório em uma coleção de badges.
Quem também trabalha com Go pode comparar a filosofia com o runner nativo da linguagem e as práticas reunidas no guia de testes em Go. A ferramenta muda, mas isolamento, determinismo e feedback rápido continuam sendo os objetivos.
Checklist de produção
Antes de tornar o nextest obrigatório, confirme:
cargo test --workspacee nextest produzem resultados compatíveis;- doctests possuem uma etapa própria;
- o arquivo
.config/nextest.tomlestá versionado; - o perfil de CI não aplica retries globais sem justificativa;
- filtros foram validados com
cargo nextest list; - testes lentos têm timeout coerente com sua categoria;
- bancos, portas e arquivos são isolados;
- a versão do runner é controlada;
- o relatório JUnit é preservado mesmo quando há falha;
- a equipe conhece o comando local equivalente ao pipeline.
Conclusão
O cargo-nextest vale a adoção quando a suíte Rust já pede mais controle do que o runner padrão oferece. Seu maior benefício não é um número universal de velocidade, mas uma execução mais estruturada: processos isolados, agendamento paralelo, filtros expressivos, perfis de CI, timeouts, retries seletivos e relatórios consumíveis.
Comece sem ruptura. Rode o nextest ao lado do cargo test, encontre testes dependentes de ordem, mantenha os doctests e promova o novo job somente depois que os resultados forem previsíveis. Assim, a ferramenta melhora o feedback da equipe sem esconder falhas nem criar uma pipeline que apenas uma pessoa sabe operar.
Para continuar, revise as boas práticas de testes em Rust, configure a pipeline de CI/CD e use o Criterion quando a pergunta for benchmark de performance — um problema diferente da execução funcional da suíte.
Perguntas frequentes
O que é cargo-nextest?
É um test runner para Rust que usa os testes compilados pelo Cargo e oferece execução isolada por processo, paralelismo, filtros, perfis, retries, timeouts e relatórios para CI.
cargo-nextest substitui cargo test?
Ele pode executar a maior parte da suíte, mas cargo test continua sendo a referência padrão. Mantenha cargo test --doc para doctests e valide a equivalência antes de trocar o comando obrigatório.
Como instalar cargo-nextest?
Execute cargo install cargo-nextest --locked e confirme com cargo nextest --version. Na CI, prefira um instalador controlado ou uma imagem que evite recompilar a ferramenta a cada job.
Como executar apenas um teste no nextest?
Use cargo nextest run -E 'test(nome)'. Para verificar o conjunto selecionado sem executá-lo, rode cargo nextest list -E 'test(nome)'.
Como configurar retries no cargo-nextest?
Defina retries no perfil ou em overrides de .config/nextest.toml. Restrinja-os a falhas transitórias conhecidas e remova a exceção quando a causa do teste flaky for corrigida.