Testes em Rust: frameworks e ferramentas para código de qualidade

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Testes em Rust: de testes unitários a property-based testing



Rust é uma das poucas linguagens onde o sistema de tipos e propriedade já na etapa de compilação exclui classes inteiras de erros (condições de corrida, ponteiros pendentes, dupla liberação de memória). No entanto, erros lógicos, tratamento incorreto de casos extremos e lógica de negócio incorreta permanecem. Para identificá-los, o ecossistema Rust desenvolveu um conjunto poderoso de ferramentas de teste — desde o executor de testes integrado até frameworks avançados para geração de dados de teste.



Ferramentas integradas: cargo test



A ferramenta básica de teste está integrada diretamente no compilador e no gerenciador de pacotes. Para criar testes, basta adicionar um módulo com o atributo #[cfg(test)] e marcar funções com o atributo #[test].



// src/lib.rspub fn add(left: u64, right: u64) -> u64 {    left + right}

#[cfg(test)]mod tests { use super::*;

#[test] fn test_add() { let result = add(2, 2); assert_eq!(result, 4); }

#[test] fn test_add_negative() { // u64 não suporta números negativos — isso é um erro de compilação // Mas se a função aceitasse i64: // assert_eq!(add(-2, 2), 0); }}


Execução: cargo test. A flag -- --nocapture exibe println! dos testes. A flag -- --test-threads=1 desativa a execução paralela.



Testes de integração



Testes de integração estão localizados na pasta tests/ no nível raiz do projeto. Cada arquivo é um crate separado que pode testar a API pública da biblioteca.



// tests/integration_test.rsuse my_library::add;

#[test]fn test_integration() { assert_eq!(add(10, 20), 30);}


Para testar crates binários (com main.rs), pode-se usar assert_cmd — ele executa o binário como um processo externo e verifica stdout/stderr.



Property-based testing: proptest e quickcheck



Em vez de escrever dezenas de casos de teste manualmente, o property-based testing gera milhares de dados de entrada aleatórios e verifica invariantes. Dois frameworks principais:



  • proptest — moderno, flexível, com suporte a estratégias, filtragem e redução de exemplos (shrink).
  • quickcheck — mais antigo, inspirado no Haskell QuickCheck, mais simples, mas menos poderoso.


Exemplo com proptest:



use proptest::prelude::*;

fn reverse_string(s: &str) -> String { s.chars().rev().collect()}

proptest! { #[test] fn test_reverse_twice(s in ".*") { let reversed = reverse_string(&s); let double_reversed = reverse_string(&reversed); assert_eq!(s, double_reversed); }

#[test] fn test_reverse_length(s in ".*") { let reversed = reverse_string(&s); assert_eq!(s.len(), reversed.len()); }}


Se o teste falhar, proptest encontra o contraexemplo mínimo (shrinking).



Teste de código assíncrono: tokio-test



Para funções assíncronas que trabalham com tokio, testes comuns não são adequados — é necessário um runtime assíncrono. tokio-test fornece a macro #[tokio::test].



use tokio::time::{sleep, Duration};

async fn delayed_add(a: u32, b: u32) -> u32 { sleep(Duration::from_millis(10)).await; a + b}

#[tokio::test]async fn test_delayed_add() { let result = delayed_add(3, 5).await; assert_eq!(result, 8);}


Também é possível usar futures-test para trabalhar com futures e async-std.



Mocks e stubs: mockall e mockito



Para isolar testes de dependências externas (BD, API, sistema de arquivos

Recommendations