Introdução
Neste laboratório, exploraremos a importância dos testes no desenvolvimento de software utilizando Rust e como escrever diferentes tipos de testes, como testes unitários e testes de integração. Também aprenderemos sobre a organização de testes em projetos Rust e como executá-los usando o comando cargo test. Além disso, discutiremos os potenciais problemas que podem surgir ao executar testes concorrentemente e forneceremos um exemplo para ilustrar isso.
Nota: Se o laboratório não especificar um nome de arquivo, você pode usar qualquer nome de arquivo que desejar. Por exemplo, você pode usar
main.rs, compilar e executá-lo comrustc main.rs && ./main.
Testes
Como sabemos, os testes são essenciais para qualquer software! Rust possui suporte de primeira classe para testes unitários e de integração (consulte este capítulo no TRPL).
A partir dos capítulos de testes vinculados acima, vemos como escrever testes unitários e testes de integração. Organizacionalmente, podemos colocar testes unitários nos módulos que testam e testes de integração em seu próprio diretório tests/:
foo
├── Cargo.toml
├── src
│ └── main.rs
│ └── lib.rs
└── tests
├── my_test.rs
└── my_other_test.rs
Cada arquivo em tests é um teste de integração separado (veja aqui), ou seja, um teste que visa testar sua biblioteca como se estivesse sendo chamada de um crate dependente.
O capítulo de Testes detalha os três estilos de teste diferentes: Unitário, Documentação e Integração.
O cargo fornece naturalmente uma maneira fácil de executar todos os seus testes!
$ cargo test
Você deve ver uma saída como esta:
[objeto Objeto]
Você também pode executar testes cujos nomes correspondem a um padrão:
$ cargo test test_foo
[objeto Objeto]
Um aviso importante: o Cargo pode executar vários testes simultaneamente, portanto, certifique-se de que eles não entrem em conflito uns com os outros.
Um exemplo de como essa concorrência pode causar problemas é se dois testes escreverem em um arquivo, como abaixo:
#[cfg(test)]
mod tests {
// Importar os módulos necessários
use std::fs::OpenOptions;
use std::io::Write;
// Este teste escreve em um arquivo
#[test]
fn test_file() {
// Abre o arquivo ferris.txt ou cria um se ele não existir.
let mut file = OpenOptions::new()
.append(true)
.create(true)
.open("ferris.txt")
.expect("Falha ao abrir ferris.txt");
// Imprime "Ferris" 5 vezes.
for _ in 0..5 {
file.write_all("Ferris\n".as_bytes())
.expect("Não foi possível escrever em ferris.txt");
}
}
// Este teste tenta escrever no mesmo arquivo
#[test]
fn test_file_also() {
// Abre o arquivo ferris.txt ou cria um se ele não existir.
let mut file = OpenOptions::new()
.append(true)
.create(true)
.open("ferris.txt")
.expect("Falha ao abrir ferris.txt");
// Imprime "Corro" 5 vezes.
for _ in 0..5 {
file.write_all("Corro\n".as_bytes())
.expect("Não foi possível escrever em ferris.txt");
}
}
}
Embora a intenção seja obter o seguinte:
$ cat ferris.txt
Ferris
Ferris
Ferris
Ferris
Ferris
Corro
Corro
Corro
Corro
Corro
O que realmente é colocado em ferris.txt é isto:
$ cargo test test_foo
Corro
Ferris
Corro
Ferris
Corro
Ferris
Corro
Ferris
Corro
Ferris
Resumo
Parabéns! Você concluiu o laboratório de Testes. Você pode praticar mais laboratórios no LabEx para aprimorar suas habilidades.