如何在HUnit中比较Double类型的值?
在HUnit中比较Double/Real类型值的方法
HUnit默认的assertEqual使用严格的Eq实例比较,对Double这类浮点数来说过于苛刻——你得写全精确到多位的小数才能通过测试。下面是几种实用的解决方法,包括如何结合Data.AEq的-==操作符:
1. 自定义近似断言函数
直接基于Data.AEq的-==封装一个适合HUnit的断言函数,既保留近似比较的能力,又能输出清晰的错误提示:
首先导入必要的库:
import Test.HUnit import Data.AEq
然后编写自定义断言:
assertApproxEqual :: (Show a, AEq a) => String -> a -> a -> Assertion assertApproxEqual msg expected actual | expected -== actual = return () | otherwise = assertFailure $ unlines [ msg , "Expected: " ++ show expected , "Actual: " ++ show actual ]
接下来修改你的测试用例,把assertEqual替换成这个自定义函数,expectedResult就可以用简洁的近似值了:
test1 :: Test test1 = TestCase (assertApproxEqual "Test linearApproximation" expectedResult actualResult) where points = [(1, 2), (2, 3)] actualResult = linearApproximation (1, 10) 0.95 points expectedResult = Linear [Just 1.0,Just 1.95,Just 2.9,Just 3.85,Just 4.8,Just 5.75,Just 6.7,Just 7.65,Just 8.6,Just 9.55] [Just 2.0,Just 2.95,Just 3.9,Just 4.85,Just 5.8,Just 6.75,Just 7.7,Just 8.65,Just 9.6,Just 10.55]
2. 直接用assertBool结合-==
如果不想额外封装函数,可以直接用HUnit的assertBool,把近似比较逻辑作为判断条件:
test1 :: Test test1 = TestCase $ assertBool "linearApproximation result doesn't match expected (approx)" (expectedResult -== actualResult) where points = [(1, 2), (2, 3)] actualResult = linearApproximation (1, 10) 0.95 points expectedResult = Linear [Just 1.0,Just 1.95,Just 2.9,Just 3.85,Just 4.8,Just 5.75,Just 6.7,Just 7.65,Just 8.6,Just 9.55] [Just 2.0,Just 2.95,Just 3.9,Just 4.85,Just 5.8,Just 6.75,Just 7.7,Just 8.65,Just 9.6,Just 10.55]
这种方式的缺点是错误提示比较简洁,如果需要更详细的差异信息,还是自定义断言更友好。
3. 给自定义类型实现AEq实例
如果你的Linear类型还没有AEq实例,需要先实现它才能让-==生效。示例如下:
data Linear = Linear [Maybe Double] [Maybe Double] deriving (Show) instance AEq Linear where -- 逐元素比较两个Linear结构的内容 Linear xs ys -== Linear xs' ys' = all (uncurry (-==)) (zip xs xs') && all (uncurry (-==)) (zip ys ys')
Maybe Double已经有默认的AEq实例(Nothing只和Nothing相等,Just x和Just y用x -== y比较),所以直接逐元素遍历比较即可。
内容的提问来源于stack exchange,提问作者student422
相关产品推荐
相关产品推荐

