{-# LANGUAGE ImplicitParams, CPP #-} #if __GLASGOW_HASKELL__ >= 707 {-# LANGUAGE Safe #-} -- Test.HUnit is not Safe in 7.6 and below #endif ----------------------------------------------------------------------------- -- | -- Module : Test.HUnit.Approx -- Copyright : (C) 2014 Richard Eisenberg -- License : BSD-style (see LICENSE) -- Maintainer : Richard Eisenberg (eir@cis.upenn.edu) -- Stability : intended to be stable -- Portability : not portable (uses implicit parameters) -- -- This module exports combinators to allow approximate equality of -- floating-point values in HUnit tests. ----------------------------------------------------------------------------- module Test.HUnit.Approx ( -- * Assertions assertApproxEqual, (@~?), (@?~), -- * Tests (~~?), (~?~) ) where import Test.HUnit import Control.Monad ( unless ) -- | Asserts that the specified actual value is approximately equal to the -- expected value. The output message will contain the prefix, the expected -- value, the actual value, and the maximum margin of error. -- -- If the prefix is the empty string (i.e., @\"\"@), then the prefix is omitted -- and only the expected and actual values are output. assertApproxEqual :: (Ord a, Num a, Show a) => String -- ^ The message prefix -> a -- ^ Maximum allowable margin of error -> a -- ^ The expected value -> a -- ^ The actual value -> Assertion assertApproxEqual preface epsilon expected actual = unless (abs (actual - expected) <= epsilon) (assertFailure msg) where msg = (if null preface then "" else preface ++ "\n") ++ "expected: " ++ show expected ++ "\n but got: " ++ show actual ++ "\n (maximum margin of error: " ++ show epsilon ++ ")" -- | Asserts that the specified actual value is approximately equal to the -- expected value (with the expected value on the right-hand side). The margin -- of error is specified with the implicit parameter @epsilon@. (@?~) :: (Ord a, Num a, Show a, ?epsilon :: a) => a -- ^ The actual value -> a -- ^ The expected value -> Assertion x @?~ y = assertApproxEqual "" ?epsilon y x infix 1 @?~ -- | Asserts that the specified actual value is approximately equal to the -- expected value (with the expected value on the left-hand side). The margin -- of error is specified with the implicit parameter @epsilon@. (@~?) :: (Ord a, Num a, Show a, ?epsilon :: a) => a -- ^ The expected value -> a -- ^ The actual value -> Assertion x @~? y = assertApproxEqual "" ?epsilon x y infix 1 @~? -- | Shorthand for a test case that asserts approximate equality (with the -- expected value on the left-hand side, and the actual value on the -- right-hand side). (~~?) :: (Ord a, Num a, Show a, ?epsilon :: a) => a -- ^ The expected value -> a -- ^ The actual value -> Test expected ~~? actual = TestCase (expected @~? actual) infix 1 ~~? -- | Shorthand for a test case that asserts approximate equality (with the -- actual value on the left-hand side, and the expected value on the -- right-hand side). (~?~) :: (Ord a, Num a, Show a, ?epsilon :: a) => a -- ^ The actual value -> a -- ^ The expected value -> Test actual ~?~ expected = TestCase (actual @?~ expected) infix 1 ~?~