{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE CPP #-}
module Test.Validity.Utils
( nameOf
, genDescr
, binRelStr
, shouldFail
, failsBecause
, Anon(..)
, shouldBeValid
, shouldBeInvalid
) where
import Control.Monad.Trans.Writer (mapWriterT)
import Control.Arrow (second)
import Data.Data
import Test.Hspec
import Test.Hspec.Core.Formatters
import Test.Hspec.Core.Runner
import Test.Hspec.Core.Spec
import Test.QuickCheck.Property
import Test.Validity.Property.Utils
nameOf ::
forall a. Typeable a
=> String
nameOf = show $ typeRep (Proxy @a)
genDescr ::
forall a. Typeable a
=> String
-> String
genDescr genname = unwords ["\"" ++ genname, "::", nameOf @a ++ "\""]
binRelStr ::
forall a. Typeable a
=> String
-> String
binRelStr op = unwords ["(" ++ op ++ ")", "::", name, "->", name, "->", "Bool"]
where
name = nameOf @a
newtype Anon a =
Anon a
instance Show (Anon a) where
show _ = "Anonymous"
instance Functor Anon where
fmap f (Anon a) = Anon (f a)
mapSpecTree' :: (SpecTree a -> SpecTree b) -> SpecM a r -> SpecM b r
mapSpecTree' f (SpecM specs) = SpecM (mapWriterT (fmap (second (map f))) specs)
failsBecause :: String -> SpecWith () -> SpecWith ()
failsBecause s = mapSpecTree' go
where
go :: SpecTree () -> SpecTree ()
go sp =
Leaf
Item
{ itemRequirement = s
, itemLocation = Nothing
#if MIN_VERSION_hspec_core(2,5,0)
, itemIsParallelizable = Nothing
#else
, itemIsParallelizable = False
#endif
, itemExample =
\_ _ _ -> do
let conf =
defaultConfig {configFormatter = Just silent}
r <- hspecWithResult conf $ fromSpecList [sp]
let succesful =
summaryExamples r > 0 && summaryFailures r > 0
pure $ produceResult succesful
}
#if MIN_VERSION_hspec_core(2,4,0)
#if MIN_VERSION_hspec_core(2,5,0)
produceResult :: Bool -> Test.Hspec.Core.Spec.Result
produceResult succesful = Result
{ resultInfo = ""
, resultStatus =
if succesful
then Success
else Failure Nothing $ Reason "Should have failed but didn't."
}
#else
produceResult :: Bool -> Either a Test.Hspec.Core.Spec.Result
produceResult succesful =
Right $
if succesful
then Success
else Failure Nothing $ Reason "Should have failed but didn't."
#endif
#else
produceResult :: Bool -> Test.Hspec.Core.Spec.Result
produceResult succesful =
if succesful
then Success
else Fail Nothing "Should have failed but didn't."
#endif
shouldFail :: Property -> Property
shouldFail =
mapResult $ \res ->
res
{ reason = unwords ["Should have failed:", reason res]
, expect = not $ expect res
}