Existe uma maneira mais limpa de testar funções que usam funções que exigem entrada do usuário no Rust?
Estou escrevendo umBiblioteca de perguntas da CLI para o meu primeiro projeto Rust, pois provavelmente o utilizarei de qualquer maneira e não consigo encontrar uma maneira limpa de testar oterminal
método do padrão do construtor, que usando a configuração obtém entrada do usuário e retorna uma resposta.
pub fn confirm(&mut self) -> Answer {
self.yes_no();
self.build_prompt();
let prompt = self.prompt.clone();
let valid_responses = self.valid_responses.clone().unwrap();
loop {
let stdio = io::stdin();
let input = stdio.lock();
let output = io::stdout();
if let Ok(response) = prompt_user(input, output, &prompt) {
for key in valid_responses.keys() {
if *response.trim().to_lowercase() == *key {
return valid_responses.get(key).unwrap().clone();
}
}
self.build_clarification();
}
}
}
Procurando uma solução que eu descobriInjeção de dependência o que me permitiu escrever testes para a função que solicita a entrada do usuário usandoCursor
. Não me permite alterar a entrada do usuário para aconfirm()
função para cada teste deQuestion::new("Continue?").confirm()
no entanto, tentei usar a compilação condicional e criei o seguinte.
#[cfg(not(test))]
fn prompt_user<R, W>(mut reader: R, mut writer: W, question: &str) -> Result<String, std::io::Error>
where
R: BufRead,
W: Write,
{
write!(&mut writer, "{}", question)?;
let mut s = String::new();
reader.read_line(&mut s)?;
Ok(s)
}
#[cfg(test)]
fn prompt_user<R, W>(mut reader: R, mut writer: W, question: &str) -> Result<String, std::io::Error>
where
R: BufRead,
W: Write,
{
use tests;
Ok(unsafe { tests::test_response.to_string() })
}
E notests
módulo eu uso uma variável global:
pub static mut test_response: &str = "";
#[test]
fn simple_confirm() {
unsafe { test_response = "y" };
let answer = Question::new("Continue?").confirm();
assert_eq!(Answer::YES, answer);
}
Isso funciona desde que eu execute apenas testes com um único thread, mas também não me permita mais testar a função real de entrada do usuário. Não é realmente um problema para uma caixa tão pequena, mas é muito confusa. Não vi nenhuma solução para fazer isso em nenhuma biblioteca de teste disponível.