module Test.QuickCheck.Extra ( (<=!) , (>=!) , slowTest , slowTestQCRatio ) where import Control.Applicative ( (<|>) ) import Data.Proxy ( Proxy(..) ) import Data.Ratio ( (%) ) import Data.Tagged ( Tagged(..) ) import Numeric ( readFloat ) import Test.QuickCheck ( Property , counterexample ) import Test.Tasty ( TestTree , adjustOption , askOption ) import Test.Tasty.Options ( IsOption(..) , OptionDescription(..) ) import Test.Tasty.QuickCheck ( QuickCheckTests(..) ) import Text.ParserCombinators.ReadP ( char , eof , readP_to_S , readS_to_P ) infix 4 <=! (<=!) :: (Ord a, Show a) => a -> a -> Property x <=! y = counterexample (show x ++ " ≰ " ++ show y) (x <= y) infix 4 >=! (>=!) :: (Ord a, Show a) => a -> a -> Property x >=! y = counterexample (show x ++ " ≱ " ++ show y) (x >= y) -------------------------------------------------------------------------------- -- Reduce the number of slow tests -------------------------------------------------------------------------------- newtype SlowTestQCRatio = SlowTestQCRatio Rational slowTestQCRatio :: OptionDescription slowTestQCRatio = Option (Proxy :: Proxy SlowTestQCRatio) readRational :: String -> Maybe Rational readRational s = case readP_to_S readRationalP s of [(r,"")] -> Just r _ -> Nothing where readRationalP = readS_to_P readFloat <* eof <|> do n <- readS_to_P reads _ <- char '/' d <- readS_to_P reads eof pure (n%d) instance IsOption SlowTestQCRatio where defaultValue = SlowTestQCRatio (1%10) parseValue = fmap SlowTestQCRatio . readRational optionName = Tagged "slow-test-ratio" optionHelp = Tagged $ unwords [ "Some of the slow tests can take a long time to run; set this" , "flag to change the number of slow test QuickCheck test cases as" , "a proportion of the non-slow test number." ] slowTest :: TestTree -> TestTree slowTest t = askOption (\(SlowTestQCRatio r) -> adjustOption (qcRatio r) t) where qcRatio r (QuickCheckTests n) = QuickCheckTests (floor (fromIntegral n * r))