Does HUnit have some way of doing approximate equalities? Clearly, this fails:
test1 = TestCase (assertEqual "Should equal" (get_scores) [(0.3, 0.3), (0.6, 0.36), (1.0, 0.3399999)])
For floating point approximate comparison, there's a library with some nice utils:
Since this question was first asked, the HUnit-approx
package has been released.
It uses an implicit variable, epsilon
, and an approximate equality operator, ~?~
, instead of ~=?
.
A short example:
tweak :: Float -> Float
tweak x = x * 1.0001
egApproxTest = let ?epsilon = 0.01 in
[ "strictEqual" ~: 0 ~=? tweak 0,
"approxEqual" ~: 2 ~?~ tweak 2 ]
Note: I don't know if there's a correct/official/accepted way to do this.
Here's the source code for assertEqual
:
assertEqual :: (Eq a, Show a) => String -- ^ The message prefix
-> a -- ^ The expected value
-> a -- ^ The actual value
-> Assertion
assertEqual preface expected actual =
unless (actual == expected) (assertFailure msg)
where msg = (if null preface then "" else preface ++ "\n") ++
"expected: " ++ show expected ++ "\n but got: " ++ show actual
Based on that and on JUnit's function for testing double equality , we could create our own in the same style:
import Control.Monad (unless)
assertEquals :: String -- ^ The message prefix
-> Double -- ^ The maximum difference between expected and actual
-> Double -- ^ The expected value
-> Double -- ^ The actual value
-> Assertion
assertEquals preface delta expected actual =
unless (abs (expected - actual) < delta) (assertFailure msg)
where msg = ... same as above ...
For my purposes, this helper function worked well enough:
assertFloatEqual text a b =
assertEqual text (take 6 (show a)) (take 6 (show b))
I made my data type an instance of equal with code there to use 2 decimal places. Here is an example using a cartesian point:
data Point = Point { x_axis :: Double, y_axis :: Double, z_axis :: Double }
deriving (Show)
In order to avoid double rounding errors and trig errors which cause the same point, and thus CornerPoints, to be /=
due to tiny differences, give it a range of .01
, and still allow the points to be equal.
axisEqual :: (Eq a, Num a, Ord a, Fractional a) => a -> a -> Bool
axisEqual a b
| (abs (a - b)) <= 0.011 = True
| otherwise = False
instance Eq Point where
Point x y z == Point xa ya za
| (axisEqual x xa) && (axisEqual y ya) &&(axisEqual z za) = True
| otherwise = False
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.