Rustlings advanced_errs2测试是否不够严谨
#[test] fn test_empty() { let res = "".parse::<Climate>(); assert_eq!(res, Err(ParseClimateError::Empty)); assert_eq!(res.unwrap_err().to_string(), "empty input"); }
#[test] fn test_short() { let res = "Boston,1991".parse::<Climate>(); assert_eq!(res, Err(ParseClimateError::BadLen)); assert_eq!(res.unwrap_err().to_string(), "incorrect number of fields"); } 应该在加一个测试,测试的res为 "Boston",原因如下:
如果写的模式匹配是这样的:
fn from_str(s: &str) -> Result<Self, Self::Err> { let v: Vec<_> = s.split(',').collect(); let (city, year, temp) = match &v[..] { [some_str] => return Err(ParseClimateError::Empty), //some_str 可能是"" 或 "Boston" …… }; …… } 考虑以上匹配,如果按照原来的测试,给定的字符串是"",应该返回Empty 错误,但是如果给定的字符串是"Boston",那么也会匹配成功,但是应该返回的是BadLen错误
我采取了不一样的处理方法,将字符串长度进行了单独处理,因此我觉得目前的测试案例已经比较完善,Empty的处理优先级应该是最高。因此在最开始进行处理会更好?
fn from_str(s: &str) -> Result<Self, Self::Err> {
if s.len() == 0 {
return Err(ParseClimateError::Empty);
}
let v: Vec<_> = s.split(',').collect();
let (city, year, temp) = match &v[..] {
["", ..] => return Err(ParseClimateError::NoCity),
[city, year, temp] => (city.to_string(), year, temp),
_ => return Err(ParseClimateError::BadLen),
};
let year: u32 = year.parse()?;
let temp: f32 = temp.parse()?;
Ok(Climate { city, year, temp })
}
//match这样写 也可以通过测试
let (city, year, temp) = match &v[..] {
[_] => return Err(ParseClimateError::Empty),
["",_,_]=> return Err(ParseClimateError::NoCity),
[city, year, temp] =>(city.to_string(), year, temp),
_ => return Err(ParseClimateError::BadLen),
};
//如果你加一个这样的测试
#[test]
fn test_only_city(){
let res = "Paris".parse::<Climate>();
assert_eq!(res, Err(ParseClimateError::BadLen));
assert_eq!(res.unwrap_err().to_string(), "incorrect number of fields");
}
会测试失败
---- test::test_only_city stdout ----
thread 'test::test_only_city' panicked at 'assertion failed: `(left == right)`
left: `Err(Empty)`,
right: `Err(BadLen)`', src\main.rs:153:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
//我的match这样写的 ,加了那个测试也会成功 ,你的那个也会成功
let (city, year, temp) = match &v[..] {
[""] => return Err(ParseClimateError::Empty),
["",_,_]=> return Err(ParseClimateError::NoCity),
[city, year, temp] =>(city.to_string(), year, temp),
_ => return Err(ParseClimateError::BadLen),
};
//所以第一个的match那样写应该有问题,但是不加那个测试就不会出问题 PS:这也是今天下午群里的人提出来的问题,我测试了一下,果真如此
//这是写的那个 from_str
fn from_str(s: &str) -> Result<Self, Self::Err> {
let v: Vec<_> = s.split(',').collect();
let (city, year, temp) = match &v[..] {
[""] => return Err(ParseClimateError::Empty),
["",_,_]=> return Err(ParseClimateError::NoCity),
[city, year, temp] =>(city.to_string(), year, temp),
_ => return Err(ParseClimateError::BadLen),
};
let year: u32 = year.parse()?;
let temp: f32 = temp.parse()?;
Ok(Climate { city, year, temp })
}