tasty-checklist-1.0.3.0: test/TestChecklist.hs
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PatternSynonyms #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Main where
import Data.Parameterized.Context ( pattern Empty, pattern (:>) )
import qualified Data.Text as T
import Test.Tasty
import Test.Tasty.Checklist
import Test.Tasty.ExpectedFailure
import Test.Tasty.HUnit
main :: IO ()
main = defaultMain $ testGroup "Checklist testing"
[
expectFailBecause "3 failed checks" $
testCase "simple checklist" $
withChecklist "simple" $ do
let tst :: Int -> Bool
tst = (> 3)
check "one" tst 1
check "two" tst 2
check "five" tst 5
check "three" tst 3
check "four" tst 4
, expectFailBecause "2 failed checks" $
testCase "simple checklist with retraction" $
withChecklist "simple retracted" $ do
let tst :: Int -> Bool
tst = (> 3)
check "one" tst 1
check "two" tst 2
check "five" tst 5
check "three" tst 3
check "four" tst 4
discardCheck "two"
, expectFailBecause "3 failed checks and assert" $
testCase "simple checklist and assert" $
withChecklist "simple" $ do
let tst :: Int -> Bool
tst = (> 3)
check "one" tst 1
check "two" tst 2
check "five" tst 5
check "three" tst 3
check "four" tst 4
3 @=? (4 :: Int)
, testCase "someFun 7 result is good" $
-- everything should pass, no check failures
withChecklist "someFun 7" $
someFun 7 `checkValues`
(Empty
:> Val "foo" foo 42
:> Val "baz" baz "The answer to the universe"
:> Val "shown" show "The answer to the universe is 42!"
:> Val "odd answer" oddAnswer False
)
, expectFailBecause "2 values don't match" $
testCase "someFun 3 result" $
withChecklist "someFun" $
someFun 3 `checkValues`
(Empty
:> Val "foo" foo 42
:> Val "baz" baz "The answer to the universe"
:> Val "shown" show "The answer to the universe is 42!"
:> Val "odd answer" oddAnswer False
)
, expectFailBecause "assertion" $
testCase "normal assert failure" $
withChecklist "asserts" $ do
3 @=? (5 :: Int)
, expectFailBecause "2 values don't match and assertion" $
testCase "someFun 3 result and assert" $
withChecklist "someFun" $ do
someFun 3 `checkValues`
(Empty
:> Val "foo" foo 42
:> Val "baz" baz "The answer to the universe"
:> Val "shown" show "The answer to the universe is 42!"
:> Val "odd answer" oddAnswer False
:> Got "even answer" (not . oddAnswer)
)
3 @=? (5 :: Int)
, testCase "object w/o Show is OK" $
-- The test object has a TestShow instance but no Show
-- instance. The test should pass, no checks or failures
withChecklist "opaque object" $
genOpaque `checkValues`
(Empty
:> Val "displayed" display "[[19]]"
:> Val "answer" answer 19
:> Val "revealed" reveal 19
:> Val "the answer" answer 19
)
, expectFailBecause "revealed test check fails" $
-- The test object has a TestShow but no Show
testCase "object w/o Show bad comparison" $
withChecklist "opaque object bad expected" $
genOpaque `checkValues`
(Empty
:> Val "displayed" display "[[19]]"
:> Val "answer" answer 19
:> Val "revealed" reveal 18
:> Val "the answer" answer 19
)
----------------------------------------
, testCase "Compare identical multi-line results" $
withChecklist "multi-line" $
let result = fmap (T.replace " " " ") soliloquy
in result `checkValues`
(Empty
:> Val "length" length (length soliloquy)
:> Val "word count" (length . T.words . T.unlines) 114
:> Observe "unchanged" id soliloquy
(\expect actual ->
multiLineDiff (T.unlines expect) (T.unlines actual))
)
, expectFailBecause "there are changes" $
testCase "Compare changed multi-line results" $
withChecklist "multi-line" $
let result = fmap (T.replace " " " ") soliloquy
in result `checkValues`
(Empty
:> Val "length" length (length soliloquy)
:> Val "word count" (length . T.words . T.unlines) 113
:> Observe "unchanged" id soliloquy
(\expect actual ->
multiLineDiff (T.unlines expect) (T.unlines actual))
)
]
----------------------------------------------------------------------
data Struct = MyStruct { foo :: Int
, bar :: Char
, baz :: String }
instance Show Struct where
show s = baz s <> " is " <> (show $ foo s) <> (bar s : [])
instance TestShow Struct -- uses the Show instance
someFun :: Int -> Struct
someFun n = MyStruct (n * 6)
(if n * 6 == 42 then '!' else '?')
"The answer to the universe"
oddAnswer :: Struct -> Bool
oddAnswer = odd . foo
----------------------------------------------------------------------
data Opaque = Hidden { answer :: Int }
genOpaque :: Opaque
genOpaque = Hidden 19
reveal :: Opaque -> Int
reveal = answer
display :: Opaque -> String
display o = "[[" <> show (answer o) <> "]]"
-- Note that Opaque doesn't have a standard Show instance, but a
-- TestShow can be provided to suffice for testing.
instance TestShow Opaque where
testShow = display
----------------------------------------------------------------------
soliloquy :: [T.Text]
soliloquy =
[ "To be, or not to be--that is the question:"
, "Whether 'tis nobler in the mind to suffer"
, "The slings and arrows of outrageous fortune"
, "Or to take arms against a sea of troubles"
, "And by opposing end them. To die, to sleep--"
, "No more--and by a sleep to say we end"
, "The heartache, and the thousand natural shocks"
, "That flesh is heir to. 'Tis a consummation"
, "Devoutly to be wished. To die, to sleep--"
, "To sleep--perchance to dream: ay, there's the rub,"
, "For in that sleep of death what dreams may come"
, "When we have shuffled off this mortal coil,"
, "Must give us pause. There's the respect"
, "That makes calamity of so long life."
]
instance TestShow [T.Text] where testShow = show . T.unlines