TDD em Rust: desenvolvimento orientado a testes para código confiável

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

Por que TDD em Rust não é chato, mas sim vantajoso?

\n\n

Você já escreveu um código que funcionava "mais ou menos certo" e depois encontrou um bug no lugar mais inesperado? Conhecido. Desenvolvimento Orientado a Testes (TDD) é um método que vira o processo habitual de cabeça para baixo. Em vez de primeiro escrever o código e depois adivinhar se funciona, você primeiro escreve um teste que deve falhar e, em seguida, escreve exatamente a quantidade de código necessária para o teste passar.

\n\n

Rust é uma linguagem que já no nível do compilador protege você de toda uma classe de erros (adeus segfaults e condições de corrida!). Mas mesmo o compilador não garante que sua lógica esteja correta. TDD em Rust adiciona a essa segurança mais uma camada: você não apenas escreve código, mas documenta o comportamento esperado diretamente nos testes. E isso é incrivelmente legal.

\n\n

Neste artigo, vamos explorar TDD em Rust com exemplos práticos. Você verá como escrever testes antes da implementação, como executá-los com cargo test e como refatorar o código sem medo de quebrar algo. Vamos lá!

\n\n

O que é TDD e por que Rust é ideal para ele?

\n\n

TDD significa Test-Driven Development (Desenvolvimento Orientado a Testes). O ciclo é simples e elegante:

\n\n
    \n
  1. Vermelho — escrevemos um teste que descreve uma nova funcionalidade. Executamos — o teste falha (lógico, o código ainda não existe).
  2. \n
  3. Verde — escrevemos o código mínimo para o teste passar. Não pensamos em beleza, apenas em passar no teste.
  4. \n
  5. Refatoração — melhoramos o código sem alterar seu comportamento. Os testes permanecem verdes.
  6. \n
\n\n

Rust é ideal para TDD por várias razões:

\n
    \n
  • Sistema de teste integrado — cargo test funciona pronto para uso, sem necessidade de frameworks externos.
  • \n
  • Tipagem forte — o compilador detecta erros de tipo, e os testes detectam erros lógicos. Juntos, são imbatíveis.
  • \n
  • Propriedade e empréstimo — os testes ajudam a garantir que você está trabalhando corretamente com a memória, sem criar cópias desnecessárias.
  • \n
  • Comunidade e documentação — a comunidade Rust promove ativamente os testes, com muitos exemplos disponíveis.
  • \n
\n\n

Configuração do projeto para TDD

\n\n

Vamos criar um novo projeto:

\n
cargo new tdd_rust_example\ncd tdd_rust_example
\n\n

Por padrão, cargo new cria um arquivo src/main.rs com um programa simples. Vamos escrever uma biblioteca, então renomeie-o para src/lib.rs (ou simplesmente exclua main.rs e crie lib.rs). Em Cargo.toml não é necessário alterar nada — os testes já estão incluídos.

\n\n

A propósito, se você estiver escrevendo apenas uma biblioteca (sem um arquivo executável), use cargo new --lib.

\n\n

Primeiro teste: vermelho

\n\n

Imagine que queremos escrever uma função que soma dois números. Pelo TDD, primeiro escrevemos o teste. Abra src/lib.rs e adicione:

\n\n
#[cfg(test)]\nmod tests {\n    #[test]\n    fn test_add() {\n        let result = add(2, 3);\n        assert_eq!(result, 5);\n    }\n}
\n\n

Execute:

\n
cargo test
\n\n

Você verá um erro de compilação — a função add não está definida. Isso é normal. Estamos na zona vermelha.

\n\n

Verde: implementação mínima

\n\n

Agora vamos escrever exatamente a quantidade de código necessária para o teste passar. Adicione a função add acima do módulo de teste:

\n\n
fn add(a: i32, b: i32) -> i32 {\n    a + b\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    \n    #[test]\n    fn test_add() {\n        let result = add(2, 3);\n        assert_eq!(result, 5);\n    }\n}
\n\n

Observe o use super::*; — isso importa tudo do módulo pai (nosso código) para o módulo de teste.

\n\n

Execute cargo test novamente. Verde! O teste passa. Fizemos o mínimo — retornamos a soma. Parece

Blogs

Book Recommendations