{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE RankNTypes #-} ----------------------------------------------------------------------------- -- | -- Module : Distribution.TestSuite -- Copyright : Thomas Tuegel 2010 -- License : BSD3 -- -- Maintainer : [email protected] -- Portability : portable -- -- This module defines the detailed test suite interface which makes it -- possible to expose individual tests to Cabal or other test agents. module Distribution.TestSuite ( TestInstance(..) , OptionDescr(..) , OptionType(..) , Test(..) , Options , Progress(..) , Result(..) , testGroup ) where import Prelude () import Distribution.Compat.Prelude data TestInstance = TestInstance { run :: IO Progress -- ^ Perform the test. , name :: String -- ^ A name for the test, unique within a -- test suite. , tags :: [String] -- ^ Users can select groups of tests by -- their tags. , options :: [OptionDescr] -- ^ Descriptions of the options recognized -- by this test. , setOption :: String -> String -> Either String TestInstance -- ^ Try to set the named option to the given value. Returns an error -- message if the option is not supported or the value could not be -- correctly parsed; otherwise, a 'TestInstance' with the option set to -- the given value is returned. } data OptionDescr = OptionDescr { optionName :: String , optionDescription :: String -- ^ A human-readable description of the -- option to guide the user setting it. , optionType :: OptionType , optionDefault :: Maybe String } deriving (Eq, Read, Show) data OptionType = OptionFile { optionFileMustExist :: Bool , optionFileIsDir :: Bool , optionFileExtensions :: [String] } | OptionString { optionStringMultiline :: Bool } | OptionNumber { optionNumberIsInt :: Bool , optionNumberBounds :: (Maybe String, Maybe String) } | OptionBool | OptionEnum [String] | OptionSet [String] | OptionRngSeed deriving (Eq, Read, Show) data Test = Test TestInstance | Group { groupName :: String , concurrently :: Bool -- ^ If true, then children of this group may be run in parallel. -- Note that this setting is not inherited by children. In -- particular, consider a group F with "concurrently = False" that -- has some children, including a group T with "concurrently = -- True". The children of group T may be run concurrently with each -- other, as long as none are run at the same time as any of the -- direct children of group F. , groupTests :: [Test] } | ExtraOptions [OptionDescr] Test type Options = [(String, String)] data Progress = Finished Result | Progress String (IO Progress) data Result = Pass | Fail String | Error String deriving (Eq, Read, Show) -- | Create a named group of tests, which are assumed to be safe to run in -- parallel. testGroup :: String -> [Test] -> Test testGroup n ts = Group { groupName = n, concurrently = True, groupTests = ts }