---
title: "cargo-llvm-cov: Cobertura de Testes Rust na CI | Rust Brasil"
url: "https://rustlang.com.br/blog/cargo-llvm-cov-cobertura-testes-rust-ci-2026/"
markdown_url: "https://rustlang.com.br/blog/cargo-llvm-cov-cobertura-testes-rust-ci-2026.MD"
description: "Meça cobertura de testes em Rust com cargo-llvm-cov. Guia com HTML, LCOV, workspaces, features, nextest, exclusões, CI e interpretação dos resultados."
date: "2026-08-13"
author: "Equipe Rust Brasil"
---

# cargo-llvm-cov: Cobertura de Testes Rust na CI | Rust Brasil

Meça cobertura de testes em Rust com cargo-llvm-cov. Guia com HTML, LCOV, workspaces, features, nextest, exclusões, CI e interpretação dos resultados.


**Para medir cobertura de testes em Rust, instale `llvm-tools-preview` e `cargo-llvm-cov`, rode `cargo llvm-cov --html` e examine quais linhas, regiões e funções importantes continuam sem teste.** Na CI, gere LCOV ou Cobertura XML, publique o artefato e aplique um limite apenas depois de estabelecer uma baseline realista para o projeto.

O `cargo-llvm-cov` usa a instrumentação de cobertura do compilador e as ferramentas do LLVM. Ele funciona no ecossistema Cargo, entende bibliotecas, binários, testes de integração, features e workspaces, além de conversar com formatos aceitos por plataformas de qualidade. Isso o torna uma escolha prática para responder a uma pergunta que `cargo test` sozinho não resolve: **quais caminhos do código foram realmente exercitados?**

Este guia mostra a instalação, os relatórios HTML, LCOV e Cobertura, a integração com [cargo-nextest](/blog/cargo-nextest-testes-rust-2026/), o uso em workspaces, as exclusões legítimas, a configuração de CI e — principalmente — como interpretar cobertura sem transformar a porcentagem em meta vazia.

## Resposta rápida: comandos essenciais

| Objetivo | Comando |
|---|---|
| Instalar suporte do LLVM | `rustup component add llvm-tools-preview` |
| Instalar a ferramenta | `cargo install cargo-llvm-cov --locked` |
| Ver resumo no terminal | `cargo llvm-cov` |
| Gerar relatório HTML | `cargo llvm-cov --html` |
| Gerar e abrir o HTML | `cargo llvm-cov --open` |
| Cobrir workspace e features | `cargo llvm-cov --workspace --all-features` |
| Gerar LCOV | `cargo llvm-cov --lcov --output-path lcov.info` |
| Gerar Cobertura XML | `cargo llvm-cov --cobertura --output-path cobertura.xml` |
| Executar com nextest | `cargo llvm-cov nextest` |
| Limpar dados anteriores | `cargo llvm-cov clean --workspace` |

Consulte `cargo llvm-cov --help` na versão instalada antes de copiar uma configuração para um pipeline crítico. Flags e recursos podem evoluir; fixar a versão da ferramenta na CI melhora a reprodutibilidade.

## O que cobertura de testes mede

Cobertura registra quais partes do programa foram visitadas durante uma execução instrumentada. Dependendo do relatório, você verá métricas como:

- **linhas**: linhas de código executadas ao menos uma vez;
- **regiões**: trechos identificados pela instrumentação do compilador;
- **funções**: funções chamadas durante os testes;
- **branches**: alternativas de controle exercitadas, quando disponíveis no fluxo usado;
- **arquivos**: distribuição da cobertura por módulo ou crate.

Uma linha coberta não significa que o comportamento foi validado corretamente. Este teste cobre a função, mas não prova quase nada:

```rust
fn dividir(total: u64, partes: u64) -> Result<u64, &'static str> {
    if partes == 0 {
        return Err("divisão por zero");
    }
    Ok(total / partes)
}

#[test]
fn executa_divisao() {
    let _ = dividir(10, 2);
}
```

O caminho feliz foi executado, porém o teste não possui uma asserção e não cobre o erro. Uma versão melhor verifica os dois contratos:

```rust
#[test]
fn divide_valores_validos() {
    assert_eq!(dividir(10, 2), Ok(5));
}

#[test]
fn rejeita_zero_partes() {
    assert_eq!(dividir(10, 0), Err("divisão por zero"));
}
```

Portanto, cobertura é um **mapa de lacunas**, não um selo de correção. Combine-a com testes unitários, integração, property-based testing e análise das invariantes do domínio. O guia de [proptest e fuzzing em Rust](/blog/rust-proptest-fuzzing-property-based-testing-2026/) mostra como explorar entradas que exemplos manuais não antecipam.

## Instalando cargo-llvm-cov

Primeiro, confirme que o projeto usa uma toolchain gerenciada pelo `rustup`:

```bash
rustc --version
cargo --version
rustup show active-toolchain
```

Instale as ferramentas de cobertura distribuídas como componente do toolchain:

```bash
rustup component add llvm-tools-preview
```

Depois instale o subcomando Cargo:

```bash
cargo install cargo-llvm-cov --locked
cargo llvm-cov --version
```

O `--locked` pede que a instalação respeite o lockfile publicado pela ferramenta. Em CI, você pode fixar uma versão para evitar que uma release nova altere comportamento sem revisão:

```bash
cargo install cargo-llvm-cov --version X.Y.Z --locked
```

Substitua `X.Y.Z` pela versão homologada no repositório. Ferramentas como [`cargo-msrv`](/blog/cargo-msrv-versao-minima-rust-ci-2026/) tratam a compatibilidade do projeto com compiladores antigos; o versionamento de ferramentas de CI resolve outro problema: tornar a automação previsível.

## Primeiro relatório no terminal

Na raiz do projeto:

```bash
cargo llvm-cov
```

A ferramenta configura as flags de instrumentação, compila os targets necessários, executa os testes e imprime um resumo. O primeiro build é mais lento porque os artefatos instrumentados diferem de um build normal.

Se você mudou configurações ou suspeita de dados antigos, limpe a cobertura:

```bash
cargo llvm-cov clean --workspace
cargo llvm-cov
```

Evite comparar o tempo desse build com o tempo normal de produção. Instrumentação adiciona trabalho ao compilador e muda os artefatos. Para investigar tempo de compilação, use as técnicas do guia de [otimização de build em Rust](/blog/rust-tempo-compilacao-otimizar-build-2026/) e ferramentas como [sccache](/blog/sccache-rust-cache-compilacao-ci-2026/).

## Relatório HTML: onde a cobertura vira ação

O resumo informa que um crate tem, por exemplo, 78% de linhas cobertas. O relatório HTML mostra **quais** linhas ficaram de fora:

```bash
cargo llvm-cov --html
```

Para abrir automaticamente:

```bash
cargo llvm-cov --open
```

No relatório, procure primeiro por:

1. tratamento de erros nunca executado;
2. branches de autorização, validação e timeout;
3. conversões de tipos em fronteiras externas;
4. código de retry, rollback ou cleanup;
5. parsers com formatos inválidos;
6. estados de concorrência e cancelamento;
7. bugs corrigidos sem teste de regressão.

Não comece pelos arquivos com menor porcentagem. Um binário de exemplo com 20% pode ser irrelevante, enquanto uma função de autorização com 95% pode esconder justamente o branch mais perigoso.

### Exemplo: lendo uma lacuna

Considere uma função que classifica respostas de uma API:

```rust
#[derive(Debug, PartialEq)]
enum Acao {
    Sucesso,
    TentarNovamente,
    FalhaPermanente,
}

fn classificar(status: u16) -> Acao {
    match status {
        200..=299 => Acao::Sucesso,
        408 | 429 | 500..=599 => Acao::TentarNovamente,
        _ => Acao::FalhaPermanente,
    }
}
```

Se os testes cobrem apenas 200 e 404, a linha do retry pode aparecer descoberta. O teste que falta não deve existir “para subir a porcentagem”; ele documenta uma decisão operacional:

```rust
#[test]
fn permite_retry_em_rate_limit_e_erro_do_servidor() {
    assert_eq!(classificar(429), Acao::TentarNovamente);
    assert_eq!(classificar(503), Acao::TentarNovamente);
}
```

Esse é o melhor uso de cobertura: revelar uma regra importante que estava implícita.

## LCOV, Cobertura XML e JSON

O HTML é ótimo para pessoas. Plataformas de CI e serviços de análise normalmente consomem formatos de máquina.

### LCOV

```bash
cargo llvm-cov --lcov --output-path lcov.info
```

LCOV é aceito por várias plataformas de cobertura e extensões de editor. O arquivo `lcov.info` deve ser tratado como artefato gerado, não como conteúdo para versionar no Git, salvo se o projeto tiver uma razão específica.

### Cobertura XML

```bash
cargo llvm-cov --cobertura --output-path cobertura.xml
```

O formato Cobertura XML aparece em integrações com sistemas de CI, dashboards e ferramentas que exibem cobertura por arquivo ou pull request.

### JSON

```bash
cargo llvm-cov --json --output-path cobertura.json
```

JSON é útil quando a equipe precisa de uma validação própria, como comparar apenas crates publicadas ou calcular uma métrica de um conjunto selecionado de diretórios.

Escolha um formato por consumidor. Gerar HTML, LCOV, XML e JSON em toda pull request sem que ninguém use os arquivos só aumenta tempo e armazenamento.

## Workspaces, pacotes, features e targets

Em um projeto simples, `cargo llvm-cov` costuma bastar. Em workspaces, a cobertura depende de uma decisão explícita sobre escopo.

### Workspace inteiro

```bash
cargo llvm-cov --workspace
```

### Todas as features

```bash
cargo llvm-cov --workspace --all-features
```

### Todos os targets relevantes

```bash
cargo llvm-cov --workspace --all-targets
```

### Um pacote específico

```bash
cargo llvm-cov -p dominio
```

Não aplique `--all-features` automaticamente quando o projeto possui backends mutuamente exclusivos. Uma biblioteca pode oferecer `rustls` e `native-tls`, por exemplo, sem suportar as duas features juntas. Nesse caso, use uma matriz:

```text
--no-default-features
--features rustls
--no-default-features --features native-tls
```

O mesmo raciocínio vale para targets. Código específico de Windows não será coberto em um runner Linux. Você pode manter jobs por sistema operacional ou declarar honestamente que a métrica principal cobre apenas o target de produção.

Para entender como features se combinam, consulte o guia de [compilação condicional em Rust](/blog/compilacao-condicional-rust-cfg-features/). Para organizar vários crates sem esconder o contrato entre eles, veja [Cargo workspaces e monorepos](/blog/cargo-workspaces-monorepos-rust-2026/).

## cargo-llvm-cov com cargo-nextest

O [cargo-nextest](/blog/cargo-nextest-testes-rust-2026/) executa testes com melhor paralelismo, perfis, retries e particionamento. O `cargo-llvm-cov` possui integração para usar esse runner mantendo a instrumentação:

```bash
cargo llvm-cov nextest
```

Em um workspace:

```bash
cargo llvm-cov nextest --workspace --all-features
```

Essa combinação é útil em repositórios com suíte grande. Antes de adotá-la, compare a seleção de testes com o comando já usado pela equipe. Um perfil do nextest que ignora testes lentos ou marca casos como flaky pode produzir cobertura diferente do `cargo test` completo.

Uma estratégia comum separa responsabilidades:

| Job | Comando | Objetivo |
|---|---|---|
| Feedback rápido | `cargo nextest run` | Informar falhas cedo |
| Cobertura | `cargo llvm-cov nextest --workspace` | Gerar métrica e artefato |
| Testes especiais | comandos dedicados | Doctests, integração externa ou targets específicos |

Não duplique toda a suíte sem medir o custo. Em alguns projetos, o próprio job de cobertura já pode cumprir a validação principal; em outros, é melhor manter um job rápido independente.

## Excluindo arquivos sem maquiar o resultado

Projetos reais contêm código que não deve dominar a métrica:

- arquivos gerados;
- bindings produzidos por ferramentas;
- migrations incorporadas;
- exemplos didáticos;
- binários administrativos;
- código específico de um target testado em outro runner;
- adaptadores triviais sem lógica de domínio.

O `cargo-llvm-cov` permite ignorar arquivos por expressão regular. Um exemplo conceitual:

```bash
cargo llvm-cov \
  --workspace \
  --ignore-filename-regex '(^|/)(generated|migrations|examples)/'
```

Teste a expressão no repositório e confira a lista final. Uma regex ampla pode esconder `src/generated_policy.rs` junto com arquivos realmente gerados.

Uma exclusão legítima deve responder a três perguntas no README ou na configuração da CI:

1. por que esse código não entra na métrica;
2. como ele é validado de outra forma;
3. quem revisa a exceção quando a estrutura muda.

Excluir `src/` inteiro para atingir 90% obviamente destrói o valor da ferramenta. Mais sutil — e igualmente ruim — é excluir módulos difíceis apenas porque reduziram a porcentagem.

## Cobertura em GitHub Actions

Um workflow básico pode gerar LCOV e guardar o relatório HTML como artefato:

```yaml
name: coverage

on:
  pull_request:
  push:
    branches: [main]

jobs:
  llvm-cov:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Instalar Rust e ferramentas LLVM
        uses: dtolnay/rust-toolchain@stable
        with:
          components: llvm-tools-preview

      - name: Instalar cargo-llvm-cov
        run: cargo install cargo-llvm-cov --locked

      - name: Gerar LCOV
        run: cargo llvm-cov --workspace --all-features --lcov --output-path lcov.info

      - name: Gerar HTML
        run: cargo llvm-cov --workspace --all-features --html

      - name: Publicar artefatos
        uses: actions/upload-artifact@v4
        with:
          name: cobertura-rust
          path: |
            lcov.info
            target/llvm-cov/html/
```

Ajuste o caminho do HTML conforme a saída informada pela versão instalada. Antes de exigir `--all-features`, confirme que essa combinação é suportada.

Em Gitea Actions, a estrutura é semelhante quando o runner oferece compatibilidade com essas actions. Se não houver action de upload disponível, salve o relatório pelo mecanismo de artefatos adotado pela instalação. O guia de [CI/CD em Rust](/artigos/ci-cd-rust/) ajuda a encaixar cobertura com `fmt`, Clippy, testes e auditoria de dependências.

## Como definir um limite mínimo

Ferramentas de cobertura conseguem falhar o job quando o resultado fica abaixo de um limite. A pergunta mais difícil não é “como configurar?”, e sim “qual limite representa qualidade para este projeto?”.

Um processo saudável:

1. gere a baseline atual sem bloquear merges;
2. remova arquivos gerados da métrica com justificativa;
3. identifique módulos críticos e lacunas reais;
4. adicione testes de regressão durante algumas semanas;
5. estabeleça um limite ligeiramente abaixo da baseline estável;
6. aumente o limite gradualmente quando isso acompanhar testes úteis.

Exemplo: se a cobertura oscila entre 73% e 76%, começar com um gate de 70% impede uma queda grande sem forçar testes artificiais. Um gate de 90% criado de um dia para o outro tende a gerar asserts irrelevantes, exclusões agressivas ou testes acoplados à implementação.

Também vale separar metas:

- biblioteca de regras de negócio: cobertura alta e foco em branches;
- adaptador HTTP: integração dos contratos importantes;
- CLI pequena: testes end-to-end dos comandos;
- bindings gerados: excluídos, mas validados pelo gerador e por testes de fronteira;
- `unsafe`: testes, Miri e revisão especializada, não apenas porcentagem.

Para código `unsafe`, use também o guia de [Miri e undefined behavior em Rust](/blog/miri-rust-undefined-behavior-2026/). Cobertura informa que uma linha executou; Miri procura determinadas violações do modelo de memória durante a execução interpretada. As ferramentas respondem a perguntas diferentes.

## Erros comuns com cargo-llvm-cov

### Confundir cobertura alta com testes bons

Um teste pode executar muitas linhas sem verificar resultados. Revise asserts, propriedades e falhas esperadas, não apenas o dashboard.

### Medir só o caminho feliz

APIs, parsers, filas e serviços falham. Dê prioridade a timeout, cancelamento, retry, entrada inválida, permissões e indisponibilidade de dependências.

### Misturar dados de execuções antigas

Quando o relatório parece incoerente, limpe os dados:

```bash
cargo llvm-cov clean --workspace
```

Depois gere novamente com a mesma toolchain, features e targets.

### Usar uma matriz diferente da produção

Cobrir features que ninguém usa e ignorar o backend de produção produz um número bonito e pouco útil. Documente a combinação canônica.

### Exigir 100%

Alguns caminhos são defensivos, dependem do sistema operacional ou representam falhas difíceis de simular. Testá-los pode valer a pena, mas 100% não deve ser um dogma. O custo de manutenção também conta.

### Publicar o relatório com dados sensíveis

Nomes de arquivos, caminhos, código-fonte renderizado e estrutura interna podem aparecer em artefatos. Em repositórios privados, mantenha relatórios com acesso compatível e revise integrações externas antes do upload.

### Rodar cobertura em toda combinação possível

Uma matriz de três sistemas, quatro feature sets e vários targets pode multiplicar a conta da CI. Comece pela configuração de produção e adicione variações quando elas cobrem contratos reais.

## Checklist de adoção

- [ ] instalar `llvm-tools-preview` e `cargo-llvm-cov`;
- [ ] gerar um relatório HTML local;
- [ ] identificar a combinação canônica de features e targets;
- [ ] decidir se o escopo é pacote ou workspace;
- [ ] excluir somente código gerado ou irrelevante, com justificativa;
- [ ] verificar tratamento de erros e branches críticos;
- [ ] integrar `cargo-nextest` se ele já for o runner do projeto;
- [ ] escolher LCOV, Cobertura ou JSON conforme o consumidor;
- [ ] publicar o relatório como artefato protegido;
- [ ] registrar a baseline antes de criar um gate;
- [ ] aplicar um limite que evite regressão sem incentivar testes vazios;
- [ ] revisar a métrica quando features, targets ou crates mudarem.

## cargo-llvm-cov em projetos de portfólio e carreira

Cobertura agrega valor ao portfólio quando conta uma história de engenharia. Em vez de colocar apenas um badge “85%”, explique no README:

- qual comando reproduz o relatório;
- quais features entram na medição;
- por que certos arquivos foram excluídos;
- quais módulos críticos possuem testes de erro;
- como a CI impede uma regressão relevante.

Um projeto Axum, por exemplo, pode testar regras de domínio sem servidor, handlers com requests controladas e persistência com uma base isolada. Combine esse desenho com o guia de [Axum em Rust](/ecossistema/axum/), [SQLx](/ecossistema/sqlx/) e [testes em Rust](/tutoriais/testes-rust/). O resultado demonstra muito mais maturidade do que uma API CRUD sem estratégia de validação.

Em entrevistas, uma resposta forte para “como você avalia a qualidade dos testes?” não se limita à porcentagem. Ela menciona cobertura como detector de lacunas, testes de regressão, branches de erro, property-based testing, estabilidade da suíte, tempo de feedback e revisão do que foi excluído.

Esse repertório é relevante para backend, infraestrutura, sistemas embarcados e manutenção de bibliotecas. Consulte as [vagas Rust](/vagas/), o diretório de [empresas que usam Rust](/empresas/) e o [plano de estudos sênior](/carreira/plano-estudos-senior/) para conectar ferramentas de qualidade ao desenvolvimento profissional.

## Perguntas frequentes

### Como medir cobertura de testes em Rust?

Instale `llvm-tools-preview` com `rustup component add llvm-tools-preview`, instale `cargo-llvm-cov` e execute `cargo llvm-cov`. Para investigar os arquivos visualmente, use `cargo llvm-cov --html` ou `cargo llvm-cov --open`.

### Como gerar relatório HTML?

Use `cargo llvm-cov --html`. A opção `--open` gera e abre o relatório. Navegue pelos módulos e procure branches de erro, validações e regressões importantes, em vez de olhar somente o total.

### Funciona com workspaces?

Sim. Use `--workspace`, selecione pacotes com `-p` e combine features e targets conforme o contrato do repositório. Não use `--all-features` se as features forem mutuamente exclusivas.

### Funciona com cargo-nextest?

Sim. Execute `cargo llvm-cov nextest`. Confirme que o perfil do nextest executa a mesma seleção de testes que você deseja representar no relatório.

### Qual porcentagem de cobertura é boa?

Não existe um valor universal. Muitos times começam com uma baseline e um gate entre 70% e 85%, mas a qualidade depende do que está coberto. Um branch crítico de autorização sem teste é mais importante do que dezenas de getters cobertos.

## Conclusão

O `cargo-llvm-cov` transforma cobertura em uma parte reproduzível do fluxo Cargo. Ele instrumenta o projeto com suporte do LLVM, executa a suíte e produz relatórios que funcionam tanto para pessoas — HTML — quanto para automações — LCOV, Cobertura e JSON.

O melhor fluxo é: **gere o HTML localmente, defina o escopo real de features e targets, investigue caminhos críticos descobertos, publique um artefato na CI e só então crie um limite mínimo baseado na baseline**. Cobertura deve orientar perguntas melhores sobre os testes, não substituir a análise de comportamento.

Para continuar, combine este guia com [cargo-nextest](/blog/cargo-nextest-testes-rust-2026/), [Criterion para benchmarks](/ecossistema/criterion/), [proptest e fuzzing](/blog/rust-proptest-fuzzing-property-based-testing-2026/) e [Miri para código unsafe](/blog/miri-rust-undefined-behavior-2026/). Juntas, essas ferramentas cobrem velocidade de feedback, regressões funcionais, performance e segurança de memória — sem reduzir qualidade a um único número.
