Testes em Rust: frameworks e ferramentas
Rust é uma linguagem de programação de sistemas que dá enorme ênfase à confiabilidade e segurança do código. O sistema de testes integrado permite que desenvolvedores escrevam testes unitários, testes de integração e testes de documentação sem instalar bibliotecas adicionais. No entanto, para cenários complexos — parametrização, geração de dados aleatórios ou mocking — a comunidade Rust criou frameworks poderosos. Neste artigo, vamos explorar as principais ferramentas de teste em Rust.
Módulo integrado test
Rust vem com o módulo integrado test, que é ativado através do atributo #[test]. Para executar os testes, usa-se o comando cargo test. Exemplo de um teste unitário simples:
// src/lib.rspub fn add(a: i32, b: i32) -> i32 { a + b}
#[cfg(test)]mod tests { use super::*;
#[test] fn test_add() { assert_eq!(add(2, 2), 4); }
#[test] fn test_add_negative() { assert_eq!(add(-1, 1), 0); }}Principais recursos do módulo integrado:
- Atributos:
#[test],#[ignore],#[should_panic]. - Macros de asserção:
assert!,assert_eq!,assert_ne!. - Testes de integração: localizados na pasta
tests/e testam a API pública. - Testes de documentação: exemplos de código em comentários doc, verificados via
cargo test.
Para a maioria dos projetos, isso é suficiente. Mas quando é necessária parametrização, geração de dados aleatórios ou mocking, frameworks especializados entram em ação.
Framework rstest — testes parametrizados
A biblioteca rstest fornece um mecanismo poderoso de parametrização de testes, semelhante ao pytest em Python. Ela permite definir vários conjuntos de dados de entrada e resultados esperados sem duplicação de código.
Instalação:
[dev-dependencies]rstest = "0.22"Exemplo de teste parametrizado:
use rstest::rstest;
#[rstest]#[case(1, 2, 3)]#[case(0, 0, 0)]#[case(-1, 1, 0)]fn test_add(#[case] a: i32, #[case] b: i32, #[case] expected: i32) { assert_eq!(add(a, b), expected);}Recursos do rstest:
- Parametrização via
#[case]. - Geração de dados aleatórios via
#[random]. - Fixtures contextuais via
#[fixture]. - Suporte para testes assíncronos.
Este framework é especialmente útil ao testar funções matemáticas, parsers ou algoritmos onde é necessário verificar muitos casos de borda.
Property-based testing com proptest
Property-based testing (teste baseado em propriedades) é um método onde você descreve invariantes (propriedades) que devem ser verdadeiras para todos os possíveis dados de entrada. A biblioteca proptest gera dados de entrada aleatórios e verifica essas propriedades.
Instalação:
[dev-dependencies]proptest = "1.5"Exemplo: verificar que a ordenação mantém o comprimento e todos os elementos:
use proptest::prelude::*;
proptest! { #[test] fn test_sort_keeps_elements(mut vec: Vec<i32>) { let original_len = vec.len(); let mut sorted = vec.clone(); sorted.sort(); assert_eq!(sorted.len(), original_len); for item in &vec { assert!(sorted.contains(item)); } }}Vantagens do proptest:
- Geração automática de milhares de cenários aleatórios.
- Minimização (shrink) — quando um teste falha, a biblioteca tenta reduzir o caso de falha ao mínimo.
Também na biblioteca
Contêineres de Injeção de Dependência em Rust: visão geral e implementação com o exemplo «dicy»
Agendador de tarefas em Node.js: node-cron, node-schedule e Bull
Agendador de Tarefas Swift para iOS/macOS: EventKit e DispatchSource
Migrações de banco de dados em Kotlin: Visão geral de ferramentas e abordagens