Testes em Rust: unit, integration, e2e do A ao Z

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
Here is the translated HTML blog article in Brazilian Portuguese:

Introdução: Por que Testar em Rust é a Base para Código Confiável



Rust é uma linguagem de programação de sistemas conhecida por sua segurança de memória e desempenho. No entanto, mesmo o compilador mais rigoroso não garante que seu programa faça exatamente o que é necessário. É aqui que os testes entram em cena. Em Rust, o suporte nativo a testes está entre os melhores das linguagens modernas. Você pode escrever testes unitários, testes de integração e testes e2e (ponta a ponta) sem precisar de bibliotecas de terceiros.



Neste artigo, vamos detalhar todos os três níveis de teste com exemplos práticos. Você aprenderá como escrever testes, como executá-los usando cargo test e como organizar a infraestrutura de teste para projetos grandes.



1. Testes Unitários em Rust: Testando Funções e Módulos



Testes unitários verificam a operação de funções ou métodos individuais de forma isolada. Em Rust, é comum colocar testes unitários diretamente no arquivo de código fonte, dentro de um módulo tests com o atributo #[cfg(test)]. Isso permite que os testes acessem funções privadas do módulo.



1.1. Seu Primeiro Teste Unitário



Vamos criar uma biblioteca de cálculo simples e escrever testes para ela.



// src/lib.rspub fn add(a: i32, b: i32) -> i32 {    a + b}

pub fn divide(a: f64, b: f64) -> Result<f64, String> { if b == 0.0 { Err(String::from("Division by zero")) } else { Ok(a / b) }}

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

#[test] fn test_add() { assert_eq!(add(2, 3), 5); }

#[test] fn test_divide_success() { let result = divide(10.0, 2.0).unwrap(); assert_eq!(result, 5.0); }

#[test] fn test_divide_by_zero() { let result = divide(10.0, 0.0); assert!(result.is_err()); assert_eq!(result.unwrap_err(), "Division by zero"); }}


Execute os testes com o comando cargo test. Você verá marcas verdes se todos os testes passarem.



1.2. Atributos de Teste



  • #[test] — indica que a função é um teste.
  • #[should_panic] — o teste é considerado aprovado se a função entrar em pânico.
  • #[ignore] — desabilita temporariamente o teste.


#[test]#[should_panic(expected = "panic message")]fn test_panic() {    panic!("panic message");}

#[test]#[ignore = "Test disabled until bug #42 is fixed"]fn test_expensive() { // Long-running test}


2. Testes de Integração: Verificando a Interação entre Componentes



Testes de integração verificam a operação de múltiplos módulos ou dependências externas juntos. Em Rust, eles são colocados em um diretório separado tests/ na raiz do projeto. Cada arquivo nesta pasta é uma crate de teste separada que só enxerga a API pública da sua biblioteca.



2.1. Estrutura dos Testes de Integração



Crie uma pasta tests/ e um arquivo tests/integration_test.rs:



// tests/integration_test.rsuse my_crate::add; // Nome da sua crate

#[test]fn test_add_integration() { // Verifica se a função funciona como parte da biblioteca let result = add(10, 20); assert_eq!(result, 30);}

#[test]fn test_divide_integration() { // Teste com múltiplas chamadas let a = 100.0; let b = 4.0; let result = my_crate::divide(a, b).unwrap(); assert!(result > 0.0); assert_eq!(result, 25.0);}


2.2. Módulos Compartilhados para Testes de Integração



Se você precisar reutilizar código entre testes de integração, crie um arquivo tests/common/mod.rs. Isso não será tratado como um arquivo de teste, mas você poderá importá-lo de outros testes.



// tests/common/mod.rspub fn setu                

Blogs

Book Recommendations