-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | A simple test framework. -- -- This is a simple testing library. It focuses mainly on making it easy -- to run large test suites and collect the results together. -- -- This package is currently fairly experimental. The API may change in -- the near future. Hopefully this release should be relatively bug-free, -- however. -- -- Changes: -- -- @package AC-MiniTest @version 1.1.1 -- | This is the main testing module. Start reading here if you want to -- know what this package is all about. -- -- There's a documentation section at the bottom of this page. You might -- want to start by reading that. Otherwise, here's a quick summary: -- -- module Test.AC.Test -- | An executable test. data Test -- | Create a Test from a simple Bool value. -- -- The test passes if the value is True. The test fails if the -- value is False, or if an exception is thrown in the course of -- computing the value. test :: Bool -> Test -- | This test always succeeds, but writes a note in the log to say that -- the test case was "inapplicable". -- -- This is generally useful if you have a test generation function which -- doesn't work for certain combinations of inputs. In that instance, the -- test still passes, but there is a note in the log letting you know it -- was only a "null" test. inapplicable :: Test -- | Test for exceptions. -- -- Ordinarily, any test which throws an exception is deemed to have -- failed. However, this test passes if evaluating the argument to -- WHNF causes an exception to be thrown. The test fails if no -- exception is thrown. -- -- This can be useful for checking that functions reject invalid input by -- throwing an exception. (Of course, you cannot check that the -- correct exception is thrown!) -- -- If WHNF is not enough to trigger the exception, you can wrap the -- expression in some suitable forcing function. (The function -- length . show can sometimes be used for this -- purpose.) -- -- Note that an infinite loop is not an exception (unless the loop -- exhausts some resource). -- -- If an exception is not thrown, the actual value returned is not -- recorded. See throws for a function that records this -- information. (Note that this requires adding a Show -- constraint.) throws_ :: x -> Test -- | Test for exceptions. -- -- Ordinarily, any test which throws an exception is deemed to have -- failed. However, this test passes if evaluating the argument to -- WHNF causes an exception to be thrown. The test fails if no -- exception is thrown. -- -- This can be useful for checking that functions reject invalid input by -- throwing an exception. (Of course, you cannot check that the -- correct exception is thrown!) -- -- If WHNF is not enough to trigger the exception, you can wrap the -- expression in some suitable forcing function. (The function -- length . show can sometimes be used for this -- purpose.) -- -- Note that an infinite loop is not an exception (unless the loop -- exhausts some resource). -- -- If no exception is thrown, the actual value returned is recorded. This -- requires adding a Show constraint. See throws_ for a -- function without this constraint. throws :: Show x => x -> Test -- | Compare two values for equality. -- -- The right-hand value is the "target" value, and the left-hand value -- (next to the ? sign) is the "actual" value. The test passes -- if both values are equal according to ==. The test fails if any -- exceptions are thrown by == or show. -- -- This operator has the same precedence as == (i.e., 4). (?=) :: (Eq x, Show x) => x -> x -> Test -- | Compare two values for inequality. -- -- The right-hand value is the "target" value, and the left-hand value -- (next to the ? sign) is the "actual" value. The test passes -- if both values are unequal according to /=. The test fails if -- any exceptions are thrown by /= or show. -- -- This operator has the same precedence as /= (i.e., 4). (?/=) :: (Eq x, Show x) => x -> x -> Test -- | Compare two values for inequality. -- -- The right-hand value is the "target" value, and the left-hand value -- (next to the ? sign) is the "actual" value. The test passes -- if the actual value is less than the target value according to -- <. The test fails if any exceptions are thrown by -- < or show. -- -- This operator has the same precedence as < (i.e., 4). (?<) :: (Ord x, Show x) => x -> x -> Test -- | Compare two values for inequality. -- -- The right-hand value is the "target" value, and the left-hand value -- (next to the ? sign) is the "actual" value. The test passes -- if the actual value is less than or equal to the target value -- according to <=. The test fails if any exceptions are thrown -- by <= or show. -- -- This operator has the same precedence as <= (i.e., 4). (?<=) :: (Ord x, Show x) => x -> x -> Test -- | Compare two values for inequality. -- -- The right-hand value is the "target" value, and the left-hand value -- (next to the ? sign) is the "actual" value. The test passes -- if the actual value is more than the target value according to -- >. The test fails if any exceptions are thrown by -- > or show. -- -- This operator has the same precedence as > (i.e., 4). (?>) :: (Ord x, Show x) => x -> x -> Test -- | Compare two values for inequality. -- -- The right-hand value is the "target" value, and the left-hand value -- (next to the ? sign) is the "actual" value. The test passes -- if the actual value is more than or equal to the target value -- according to >=. The test fails if any exceptions are thrown -- by >= or show. -- -- This operator has the same precedence as >= (i.e., 4). (?>=) :: (Ord x, Show x) => x -> x -> Test -- | Attach a title to a test. -- -- This title is an arbitrary human-readable label. It is recorded in -- relation to the test, but has no other function. title :: String -> Test -> Test -- | Attach an argument value note. -- -- The String is the argument name, and the x is that -- argument's value, which must implement show. argument :: Show x => String -> x -> Test -> Test -- | Attach an argument value note. -- -- The first String is the argument name, and the second is some -- suitable textual representation of that argument's value. argument_ :: String -> String -> Test -> Test -- | Note down a temporary intermediate value computed in the process of -- constructing a test. -- -- The String is a name for this value, and the x is the -- value itself, which must implement show. temporary :: Show x => String -> x -> Test -> Test -- | Note down a temporary intermediate value computed in the process of -- constructing a test. -- -- The first String is the temporary name, and the second is some -- suitable textual representation of the temporary's value. temporary_ :: String -> String -> Test -> Test -- | Add a textual note to the test log. note :: String -> Test -> Test -- | Create a Test from an IO action that returns a -- Bool. -- -- The test passes if the value returned is True. The test fails -- if the value returned is False, or if an uncaught exception -- escapes. testIO :: IO Bool -> Test -- | Create a Test from an IO action with seperate set-up and -- clean-up phases. -- -- The first argument is a set-up action. This might be used to -- initialise mutable storage or create disk structures, or just to open -- some handles. Its result is passed to the second argument, which then -- does the actual test propper. Finally, the third argument is run -- (again with the set-up result as argument) to do any post-test -- clean-up operations required. Its result is discarded. -- -- If any of these IO actions throw an exception, the test is -- marked failed. Note that if the set-up action throws an exception, the -- test and clean-up actions are not run. (If only the main test action -- throws an exception, the clean-up is still run.) testIO3 :: IO x -> (x -> IO Bool) -> (x -> IO y) -> Test -- | Test for exceptions in the IO monad. -- -- Ordinarily, any test which throws an exception is deemed to have -- failed. However, this test passes if evaluating the action's -- result to WHNF causes an exception to be thrown. The test fails -- if no exception is thrown. -- -- This can be useful for checking that a function rejects invalid input -- by throwing an exception, or that invalid I/O operations are reported. -- (Of course, you cannot check that the correct exception is -- thrown!) -- -- Note that the IO action is run and its result is reduced -- (to WHNF only). Note also that infinite loops are not exceptions -- (unless the loop exhausts some resource). -- -- If no exception is thrown, the actual value returned is not recorded. -- See throwsIO for a function which does record this information. -- (This requires adding a Show constraint.) throws_IO :: IO x -> Test -- | Test for exceptions in the IO monad. -- -- Ordinarily, any test which throws an exception is deemed to have -- failed. However, this test passes if evaluating the action's -- result to WHNF causes an exception to be thrown. The test fails -- if no exception is thrown. -- -- This can be useful for checking that a function rejects invalid input -- by throwing an exception, or that invalid I/O operations are reported. -- (Of course, you cannot check that the correct exception is -- thrown!) -- -- Note that the IO action is run and its result is reduced -- (to WHNF only). Note also that infinite loops are not exceptions -- (unless the loop exhausts some resource). -- -- If no exception is thrown, the actual value returned is recorded. This -- requires adding a Show constraint; see throws_IO for a -- function without this constraint. throwsIO :: Show x => IO x -> Test -- | The test monad. -- -- Notice the MonadIO instance. This allows you to call -- liftIO to perform arbitrary IO actions at any point -- within the test monad. data TestM x -- | Create a Test from a TestM action. -- -- The test passes if the TestM action returns True. The -- test fails if it returns False or an uncaught exception -- escapes. testM :: TestM Bool -> Test -- | Check a TestM action for exceptions. -- -- Ordinarily, any test which throws an exception is deemed to have -- failed. However, this test passes if evaluating the action's -- result to WHNF causes an exception to be thrown. The test fails -- if no exception is thrown. -- -- This can be useful for checking that a function rejects invalid input -- by throwing an exception, or that invalid I/O operations are reported. -- (Of course, you cannot check that the correct exception is -- thrown!) -- -- Note that the TestM action is run and its result is -- reduced (to WHNF only). Note also that infinite loops are not -- exceptions (unless the loop exhausts some resource). -- -- If no exception is thrown, the actual value returned is not recorded. -- See throwsM for a function that does record the value. This -- requires adding a Show constraint. throws_M :: TestM x -> Test -- | Check a TestM action for exceptions. -- -- Ordinarily, any test which throws an exception is deemed to have -- failed. However, this test passes if evaluating the action's -- result to WHNF causes an exception to be thrown. The test fails -- if no exception is thrown. -- -- This can be useful for checking that a function rejects invalid input -- by throwing an exception, or that invalid I/O operations are reported. -- (Of course, you cannot check that the correct exception is -- thrown!) -- -- Note that the TestM action is run and its result is -- reduced (to WHNF only). Note also that infinite loops are not -- exceptions (unless the loop exhausts some resource). -- -- If no exception is thrown, the actual value returns is recorded. This -- requires adding a Show constraint. See throws_M for a -- function without this constraint. throwsM :: Show x => TestM x -> Test -- | Mark the current test as "inapplicable" and return True. (See -- inapplicable.) inapplicableM :: TestM Bool -- | Note down a temporary intermediate value computed in the process of -- constructing a test. -- -- The String is a name for this value, and the x is the -- value itself, which must implement show. temporaryM :: Show x => String -> x -> TestM () -- | Note down a temporary intermediate value computed in the process of -- constructing a test. -- -- The first String is the name, and the second is some suitable -- textual representation of the value. temporaryM_ :: String -> String -> TestM () -- | Add a textual note to the log file. noteM :: String -> TestM () -- | Combine multiple tests into a single composite test. -- -- The composite test fails if any of its constituent tests fail. Whether -- the remaining tests are run depends on the testing mode (the -- cfg_FailAbort parameter in TestConfig). -- -- Essentially, this takes the logical-AND of several tests. You can -- achieve the same result using the normal && operator or -- the and function, operating on plain Bool values rather -- than Test objects. However, by turning subexpressions into -- Test objects and using tests, the result of each -- subexpression will be logged to file in addition to the overall -- result. Depending on the context, that may or may not be helpful. You -- decide which you want. tests :: [Test] -> Test -- | Create a composite test which passes if at least one child test -- passes. -- -- All child tests are always run, regardless of error reporting mode. No -- test failures are reported, unless all children fail. -- -- Essentially, this takes the logical-OR of several tests. You can -- achieve the same result using the normal || operator or the -- or function, operating on plain Bool values rather than -- Test objects. However, by turning subexpressions into -- Test objects and using alternatives, the result of each -- subexpression will be logged to file in addition to the overall -- result. Depending on the context, that may or may not be helpful. You -- decide which you want. alternatives :: [Test] -> Test -- | Execute a test. -- -- Ordinarily, "the test" will be a composite test created with -- tests, and will actually contain multiple sub-tests within it. -- -- A Bool value is returned indicating whether the test was -- successful or not. Test progress information is printed to -- stdout. If any test fails, detailed information for that test -- is printed to stdout, and testing aborts. -- -- For more control, see run_test_full. run_test :: Test -> IO Bool -- | Execute a test. -- -- Ordinarily, "the test" will be a composite test created with -- tests, and will actually contain multiple sub-tests within it. -- -- A Bool value is returned indicating whether the test was -- successful or not. Test progress information is printed to -- stdout. Various testing options can be configured using the -- TestConfig argument. In particular, it is possible to log -- detailed testing data to an XML log file (the cfg_LogFile -- parameter). -- -- The related run_test function runs a test with the -- default_config test settings, which are useful for quick -- interactive testing during a debugging session. run_test_full :: TestConfig -> Test -> IO Bool -- | Configuration settings for a test run. data TestConfig TestConfig :: Maybe FilePath -> Maybe String -> Bool -> Bool -> TestConfig -- | If Nothing, no log file is produced. Otherwise, this is the -- full path to the XML log file. cfg_LogFile :: TestConfig -> Maybe FilePath -- | Path to an XSL file. If given, the XML log file will use this XSL as a -- stylesheet. This value is ignored if no XML log is produced. cfg_LogXSL :: TestConfig -> Maybe String -- | If True, report test failures to stdout. If -- False, just report test progress to stdout. cfg_FailReport :: TestConfig -> Bool -- | If True, abort testing if a test fails, otherwise continue -- testing. (In other words, False causes all tests to be -- run, regardless of test failures, while True runs until a test -- fails and then stops.) cfg_FailAbort :: TestConfig -> Bool -- | The default test configuration, as used by run_test. -- --
--   cfg_LogFile    = Nothing
--   cfg_LogXSL     = Nothing
--   cfg_FailReport = True
--   cfg_FailAbort  = True
--   
-- -- You can use this as a starting point if you only want to customise a -- few test settings. (More options may be added in future.) default_config :: TestConfig instance MonadIO TestM instance Monad TestM -- | Properties for testing that instances of the Eq class perform -- correctly. -- -- p_reflexive, p_symmetric and p_transitive check -- the basic properties of an equity relation. In other words, they test -- the == method. p_not_equal checks for the -- extraordinarily unlikely case of == and /= not agreeing -- on equity. (The default implementation of /= automatically -- guarantees that this test will pass, and that's what most people -- presumably use.) module Test.AC.Class.Eq -- | Check that x == x. p_reflexive :: (Show x, Eq x) => x -> Test -- | Check that if x == y then y == x as well. p_symmetric :: (Show x, Eq x) => x -> x -> Test -- | Check that if x == y and y == z then x == -- z. p_transitive :: (Show x, Eq x) => x -> x -> x -> Test -- | Check that x /= y is the same as not (x == y). p_not_equal :: (Show x, Eq x) => x -> x -> Test -- | Given a list of distinct values, perform all applicable tests -- on all possible combinations of inputs. (If the inputs are not -- distinct, some redundant tests are performed.) p_Eq :: (Show x, Eq x) => [x] -> Test -- | Properties for testing that instances of the Ord class perform -- correctly. -- -- p_symmetric and p_transitive check the basic properties -- of the ordering. In other words, they test the compare method. -- p_equal checks that Ord agrees with Eq (that is, -- compare returns EQ when == returns True). -- The Test.AC.Class.Eq module already checks that Eq is -- reflexive, so if Ord agrees with Eq then Ord too -- is reflexive, and we don't need a seperate test for that. The -- remaining tests (i.e., p_compare, p_min and -- p_max) check for the extraordinarily unlikely case that the -- various Ord methods do not agree with each other. (Usually they -- are implemented in terms of each other.) module Test.AC.Class.Ord -- | Check that compare agrees with == on equity. p_equal :: (Show x, Ord x) => x -> x -> Test -- | Check that swapping the arguments to compare works correctly. p_symmetric :: (Show x, Ord x) => x -> x -> Test -- | Check that if x < y and y < z then x < -- z. p_transitive :: (Show x, Ord x) => x -> x -> x -> Test -- | Check that compare agrees with >, <, etc. p_compare :: (Show x, Ord x) => x -> x -> Test -- | Check that min works correctly. p_min :: (Show x, Ord x) => x -> x -> Test -- | Check that max works correctly. p_max :: (Show x, Ord x) => x -> x -> Test -- | Given a list of distinct values, perform all applicable tests -- on all possible combinations of inputs. (If the inputs are not -- distinct, some redundant tests are performed.) p_Ord :: (Show x, Ord x) => [x] -> Test -- | Defines the Label type, for making values showable. module Test.AC.Label -- | The Label type. -- -- A value of type Label x is really a value of type x, -- but with a textual label. The Show instance returns this label. -- -- This can be tremendously useful for allowing you to show values -- which would not otherwise be printable. For example, functions. Rather -- than passing a function, you can pass a labelled function. This allows -- you to know, at runtime, which function you're dealing with, -- which is very useful for test purposes. -- -- You can use label to extract the label text, and value -- to extract the actual data value. -- -- The Show instance uses the label, but the other -- instances use only the value, ignoring the label. (In -- particular, any operations which alter the value leave the -- label untouched.) data Label x Label :: String -> !x -> Label x label :: Label x -> String value :: Label x -> !x -- | This type is similar to Label. However, Label cannot be -- made an instance of higher-kinded classes such as Functor and -- Monad. This type gets around that irritating limitation. data Label1 c x1 Label1 :: String -> c x1 -> Label1 c x1 label1 :: Label1 c x1 -> String value1 :: Label1 c x1 -> c x1 instance Monad c => Monad (Label1 c) instance Functor c => Functor (Label1 c) instance Show (Label1 c x1) instance Bounded (c x1) => Bounded (Label1 c x1) instance Enum (c x1) => Enum (Label1 c x1) instance Ord (c x1) => Ord (Label1 c x1) instance Eq (c x1) => Eq (Label1 c x1) instance Show (Label x) instance Bounded x => Bounded (Label x) instance Enum x => Enum (Label x) instance Ord x => Ord (Label x) instance Eq x => Eq (Label x) -- | Properties for testing that instances of the Functor class -- perform correctly. -- -- This testing requires an Eq instance, which not all -- Functors actually have. It also requires a Show -- instance, which is also uncommon. The Label1 wrapper may be -- useful in dealing with the Show requirement. -- -- Tests are supplied both in regular "unlabelled" form, and also in a -- special "labelled" form, where function objects have Labels -- attached to them. Because of this, the function used for each test can -- be recorded in the test log, which can be quite helpful. module Test.AC.Class.Functor -- | Check that fmap id == id. p_map_id :: (Functor f, Eq (f x), Show (f x)) => f x -> Test -- | Check that fmap (f . g) == fmap -- f . fmap g. p_map_compose :: (Functor f, Eq (f z), Show (f x), Show (f y), Show (f z)) => f x -> (x -> y) -> (y -> z) -> Test -- | Given a list of distinct Functor values and functions, -- perform all tests on all combinations of inputs. (If the inputs are -- not distinct, some redundant tests will be performed.) -- -- The argument types are somewhat constrained to keep the type signature -- reasonably simple. p_Functor :: (Functor f, Eq (f x), Show (f x)) => [f x] -> [x -> x] -> Test -- | Check that fmap (f . g) == fmap -- f . fmap g. p_map_compose_L :: (Functor f, Eq (f z), Show (f x), Show (f y), Show (f z)) => f x -> Label (x -> y) -> Label (y -> z) -> Test -- | Given a list of distinct Functor values and functions, -- perform all tests on all combinations of inputs. (If the inputs are -- not distinct, some redundant tests will be performed.) -- -- The argument types are somewhat constrained to keep the function's -- type signature reasonably simple. p_Functor_L :: (Functor f, Eq (f x), Show (f x)) => [f x] -> [Label (x -> x)] -> Test -- | Properties for testing that instances of the Monad class -- perform correctly. -- -- This testing requires an Eq instance, which not all -- Monads actually have. It also requires a Show instance, -- which is also uncommon. The Label1 wrapper may be useful in -- dealing with the Show requirement. -- -- Tests are supplied both in regular "unlabelled" form, and also in a -- special "labelled" form, where function objects have Labels -- attached to them. Because of this, the function used for each test can -- be recorded in the test log, which can be quite helpful. module Test.AC.Class.Monad -- | Check that return x >>= f == f x. p_return_bind :: (Monad m, Eq (m y), Show x, Show (m x), Show (m y)) => x -> (x -> m y) -> Test -- | Check that mx >>= return == mx. p_bind_return :: (Monad m, Eq (m x), Show (m x)) => m x -> Test -- | Check that >>= is associative. -- -- Approximately, mx >>= (f >>= g) == (mx -- >>= f) >>= g, but that doesn't type-check. To be -- exact, mx >>= (\ x -> f x >>= g) == (mx -- >>= f) >>= g. p_bind_associative :: (Monad m, Eq (m z), Show (m x), Show (m y), Show (m z)) => m x -> (x -> m y) -> (y -> m z) -> Test -- | Given a list of distinct inputs, run all applicable -- Monad tests on all combinations of inputs. (If the inputs are -- not distinct, some redundant tests will be performed.) -- -- The argument types have been constrainted a bit to keep the function's -- type signature reasonably simple. p_Monad :: (Monad m, Eq (m x), Show x, Show (m x)) => [x] -> [x -> m x] -> [m x] -> Test -- | Check that fmap f mx == mx >>= return . f. p_Functor_Monad :: (Functor m, Monad m, Eq (m y), Show (m x), Show (m y)) => m x -> (x -> y) -> Test -- | Check that return x >>= f == f x. p_return_bind_L :: (Monad m, Eq (m y), Show x, Show (m x), Show (m y)) => x -> Label (x -> m y) -> Test -- | Check that >>= is associative. -- -- Approximately, mx >>= (f >>= g) == (mx -- >>= f) >>= g, but that doesn't type-check. To be -- exact, mx >>= (\ x -> f x >>= g) == (mx -- >>= f) >>= g. p_bind_associative_L :: (Monad m, Eq (m z), Show (m x), Show (m y), Show (m z)) => m x -> Label (x -> m y) -> Label (y -> m z) -> Test -- | Given a list of distinct inputs, run all applicable -- Monad tests on all combinations of inputs. (If the inputs are -- not distinct, some redundant tests will be performed.) -- -- The argument types have been constrainted a bit to keep the function's -- type signature reasonably simple. p_Monad_L :: (Monad m, Eq (m x), Show x, Show (m x)) => [x] -> [Label (x -> m x)] -> [m x] -> Test -- | Check that fmap f mx == mx >>= return . f. p_Functor_Monad_L :: (Functor m, Monad m, Eq (m y), Show (m x), Show (m y)) => m x -> Label (x -> y) -> Test