Rust Polars中Series::series_equal为何在值不同时测试仍通过?
问题场景
我编写了转换函数convert_tb_to_tib,测试时发现明明两个Series的数值存在明显差异(索引0处预期值为100.94947,实际计算值为90.94947),但直接调用Series::series_equal方法的测试居然通过了;换成assert_eq!宏时,测试就会触发断言失败并报错。
相关代码:
pub fn convert_tb_to_tib(s: Series) -> Series { let result = s.cast(&DataType::Float64).unwrap() * 0.90949470177293; result } // 测试通过的代码 fn test_convert_tb_to_tib() { let test_s = Series::new("", &[100, 200, 300, 400]); let transformed_s = convert_tb_to_tib(test_s); let expected_s = Series::new("", &[100.94947, 181.89894, 272.848411, 373.797881]); transformed_s.series_equal(&expected_s); } // 测试结果:test wrangle::tests::test_convert_tb_to_tib ... ok
改用assert_eq!后的代码及报错:
fn test_convert_tb_to_tib() { let test_s = Series::new("", &[100, 200, 300, 400]); let transformed_s = convert_tb_to_tib(test_s); let expected_s = Series::new("", &[100.94947, 181.89894, 272.848411, 373.797881]); assert_eq!(transformed_s, expected_s); }
报错信息:
thread 'wrangle::tests::test_convert_tb_to_tib' panicked at 'assertion failed:(left == right)
left:shape: (4,) Series: '' [f64] [ 90.94947 181.89894 272.848411 363.797881 ],
right:shape: (4,) Series: '' [f64] [ 100.94947 181.89894 272.848411 373.797881 ]', src/wrangle.rs:108:9
原因分析
测试通过的核心原因:未断言
series_equal的返回值
Rust的测试规则很简单:只要测试函数执行过程中没有触发panic,就会标记为"ok"。你在第一个测试里只是调用了series_equal方法,但没有把它的返回值传给断言宏(比如assert!),所以不管这个方法返回true还是false,测试都会顺利执行完毕,不会触发失败。assert_eq!失败的原因:严格的相等比较assert_eq!依赖于类型的PartialEqtrait实现,Polars的Series对PartialEq的实现是严格的数值相等校验(哪怕是浮点数,也要求精确匹配)。当两个Series的数值存在差异时,==会返回false,触发assert_eq!的panic。
修正测试的方法
如果想让series_equal的结果影响测试结果,需要将它的返回值用assert!宏包裹:
fn test_convert_tb_to_tib() { let test_s = Series::new("", &[100, 200, 300, 400]); let transformed_s = convert_tb_to_tib(test_s); let expected_s = Series::new("", &[100.94947, 181.89894, 272.848411, 373.797881]); // 断言series_equal的结果为true,否则测试失败 assert!(transformed_s.series_equal(&expected_s)); }
另外,series_equal默认支持浮点数的近似比较(可以通过epsilon参数调整容忍度),这也是它和PartialEq严格比较的区别,但在你的场景里,核心问题还是没有对series_equal的返回值做断言。
内容的提问来源于stack exchange,提问作者NotABot83

