Desafio Rust
Testando erros e pânicos
Enunciado
Implemente uma função raiz_quadrada(x: f64) -> Result<f64, String> que retorna Err para números negativos, e uma função divide(a: i32, b: i32) -> i32 que entra em pânico se b == 0. Escreva testes que cubram: sucesso da raiz, erro da raiz, e pânico na divisão usando #[should_panic].
Requisitos
raiz_quadradaretornaOkparax >= 0eErrparax < 0.dividedeve entrar em pânico seb == 0.- Os testes devem usar
assert_eq!pararaiz_quadradae#[should_panic]paradivide. - O teste de pânico deve verificar a mensagem de erro com
expected.
Código inicial
pub fn raiz_quadrada(x: f64) -> Result<f64, String> {
// implemente
}
pub fn divide(a: i32, b: i32) -> i32 {
// implemente
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn testa_raiz_ok() {
// escreva o teste
}
#[test]
fn testa_raiz_negativa() {
// escreva o teste
}
#[test]
#[should_panic(expected = "divisão por zero")]
fn testa_divisao_por_zero() {
// escreva o teste
}
}
fn main() {
println!("{:?}", raiz_quadrada(9.0));
println!("{:?}", raiz_quadrada(-1.0));
println!("{}", divide(10, 2));
}
Saída esperada
Ok(3.0)
Err("número negativo")
5
Ver dica
Para raiz_quadrada, use if x < 0.0 { Err(...) } else { Ok(x.sqrt()) }. Para divide, use assert!(b != 0, "divisão por zero") ou panic!.
Mostrar solução
pub fn raiz_quadrada(x: f64) -> Result<f64, String> {
if x < 0.0 {
Err("número negativo".to_string()) // retorna erro para negativos
} else {
Ok(x.sqrt()) // calcula a raiz quadrada
}
}
pub fn divide(a: i32, b: i32) -> i32 {
if b == 0 {
panic!("divisão por zero"); // entra em pânico se divisor for zero
}
a / b
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn testa_raiz_ok() {
assert_eq!(raiz_quadrada(9.0), Ok(3.0)); // 9.0 -> Ok(3.0)
}
#[test]
fn testa_raiz_negativa() {
assert_eq!(raiz_quadrada(-1.0), Err("número negativo".to_string()));
}
#[test]
#[should_panic(expected = "divisão por zero")]
fn testa_divisao_por_zero() {
divide(10, 0); // deve entrar em pânico
}
}
fn main() {
println!("{:?}", raiz_quadrada(9.0));
println!("{:?}", raiz_quadrada(-1.0));
println!("{}", divide(10, 2));
}
Passo a passo
raiz_quadradaverifica sexé negativo; se for, retornaErrcom mensagem.- Caso contrário, retorna
Ok(x.sqrt()). divideverifica seb == 0e chamapanic!com a mensagem "divisão por zero".- No teste
testa_raiz_ok, usamosassert_eq!para compararOk(3.0)com o resultado. - No teste
testa_raiz_negativa, comparamos comErr("número negativo".to_string()). - O teste
testa_divisao_por_zeroé anotado com#[should_panic(expected = "divisão por zero")], que verifica se a mensagem do pânico contém o texto esperado. - Se
divide(10, 0)não entrar em pânico, o teste falha.
Por que funciona
Result permite tratar erros de forma explícita, e os testes comparam o valor retornado com o esperado. Já #[should_panic] captura pânicos e verifica se ocorreram, opcionalmente checando a mensagem. Isso cobre tanto erros recuperáveis quanto irrecoveráveis.
Erros comuns
- Esquecer
expectedem#[should_panic]: o teste passa mesmo que o pânico tenha mensagem diferente. - Usar
assert_eq!para testar pânico: o pânico interrompe o teste antes da asserção. - Retornar
Errem vez depanic!emdivide: o testeshould_panicfalharia, pois não há pânico.
Outra forma de resolver
Poderia usar std::panic::catch_unwind para capturar o pânico e verificar a mensagem manualmente, mas #[should_panic] é mais idiomático e simples.
Saída esperada
Ok(3.0)
Err("número negativo")
5