Lição: 012: Testes em Rust
Os testes são uma parte essencial do processo de desenvolvimento de software, permitindo que os desenvolvedores garantam que seu código se comporta conforme o esperado. Rust oferece um poderoso e expressivo framework de teste embutido na linguagem. Nesta aula, exploraremos como escrever e executar testes em Rust, incluindo testes unitários, testes de integração e mais.
1. Testes Unitários
Testes unitários são a forma mais básica de teste. Eles se concentram em testar funções ou módulos individuais para verificar se funcionam corretamente. Em Rust, você pode escrever testes unitários no mesmo arquivo que o código que está testando. Veja um exemplo simples:
// src/lib.rs
pub fn adicionar(a: i32, b: i32) -> i32 {
a + b
}
#[cfg(test)]
mod testes {
use super::*;
#[test]
fn teste_adicionar() {
assert_eq!(adicionar(2, 3), 5);
assert_eq!(adicionar(-1, 1), 0);
assert_eq!(adicionar(0, 0), 0);
}
}
Explicação
- O atributo
#[cfg(test)]
informa ao compilador Rust para incluir este módulo apenas ao executar testes. - O atributo
#[test]
marca a função como uma função de teste. - Usamos
assert_eq!
para verificar se o valor esperado corresponde ao valor real retornado pela funçãoadicionar
.
2. Executando Testes
Para executar os testes definidos em seu projeto Rust, você pode usar o seguinte comando:
cargo test
Este comando irá compilar seu código (se necessário) e executar todos os testes, incluindo os testes unitários definidos nos módulos #[cfg(test)]
.
3. Testes de Integração
Testes de integração são usados para testar a interface pública de sua biblioteca. Ao contrário dos testes unitários, os testes de integração estão localizados em uma pasta separada chamada tests
. Aqui está um exemplo de um teste de integração:
Passo 1: Criar um Teste de Integração
Crie um novo arquivo no diretório tests
do seu projeto:
// tests/teste_de_integração.rs
use meu_crate::adicionar; // Substitua `meu_crate` pelo nome do seu crate.
#[test]
fn teste_adicionar() {
assert_eq!(adicionar(10, 5), 15);
assert_eq!(adicionar(-5, 5), 0);
}
#[test]
fn teste_adicionar_negativo() {
assert_eq!(adicionar(-10, -5), -15);
}
Passo 2: Executar Testes de Integração
Você pode executar os testes de integração da mesma forma que os testes unitários, usando cargo test
. Todos os testes encontrados no diretório tests
também serão detectados e executados automaticamente.
4. Assertivas
Os testes em Rust incluem várias macros para assertivas:
assert!(condição)
— Afirma que a condição é verdadeira.assert_eq!(esquerda, direita)
— Afirma que dois valores são iguais.assert_ne!(esquerda, direita)
— Afirma que dois valores não são iguais.
Essas assertivas ajudam a garantir que seu código se comporte corretamente em várias situações.
5. Testando para Panics
Você também pode testar condições que devem acionar panics usando o atributo #[should_panic]
. Por exemplo:
#[cfg(test)]
mod testes {
use super::*;
#[test]
#[should_panic(expected = "divisão por zero")]
fn teste_divisao_por_zero() {
dividir(5, 0);
}
fn dividir(a: i32, b: i32) -> i32 {
if b == 0 {
panic!("divisão por zero");
}
a / b
}
}
Explicação
Aqui, esperamos que ocorra um panic ao tentar dividir por zero. O parâmetro expected
permite especificar uma mensagem que deve corresponder à mensagem do panic.
6. Organização dos Testes
Para manter seus testes organizados, considere as seguintes técnicas:
- Agrupe testes relacionados usando módulos.
- Use nomes descritivos para as funções de teste.
- Crie funções utilitárias para evitar a duplicação de código entre os testes.
Conclusão
Os testes são uma parte crucial da escrita de aplicações robustas em Rust. Compreender como usar corretamente os testes unitários e de integração ajudará você a detectar erros mais cedo e garantir que seu código se comporte conforme o esperado. Use os exemplos fornecidos como ponto de partida para construir sua suíte de testes e explorar recursos mais avançados no framework de testes do Rust. Boas práticas de teste!