File: SmallCheckSpec.hs

package info (click to toggle)
haskell-hspec-smallcheck 0.5.3-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 80 kB
  • sloc: haskell: 198; makefile: 3
file content (69 lines) | stat: -rw-r--r-- 2,597 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Test.Hspec.SmallCheckSpec (main, spec) where

import           Test.Hspec

import           Data.Orphans ()
import qualified Control.Exception as E

import qualified Test.Hspec.Core.Spec as H
import qualified Test.Hspec.Runner as H
import           Test.SmallCheck
import           Test.QuickCheck (stdArgs)
import           Test.HUnit (Assertion, assertFailure, assertEqual)

import           Test.Hspec.SmallCheck

main :: IO ()
main = hspec spec

exceptionEq :: E.SomeException -> E.SomeException -> Bool
exceptionEq a b
  | Just ea <- E.fromException a, Just eb <- E.fromException b = ea == (eb :: E.ErrorCall)
  | Just ea <- E.fromException a, Just eb <- E.fromException b = ea == (eb :: E.ArithException)
  | otherwise = undefined

deriving instance Eq H.FailureReason
deriving instance Eq H.ResultStatus
deriving instance Eq H.Result

instance Eq E.SomeException where
  (==) = exceptionEq

spec :: Spec
spec = do
  describe "evaluateExample" $ do
    context "with Property IO" $ do
      it "returns Success if property holds" $ do
        eval True `shouldReturn` H.Result "" H.Success

      it "returns Failure if property does not hold" $ do
        eval False `shouldReturn` H.Result "" (H.Failure Nothing (H.Reason "condition is false"))

      it "shows what falsified it" $ do
        eval (/= (2 :: Int)) `shouldReturn` H.Result "" (H.Failure Nothing (H.Reason "there exists 2 such that\n  condition is false"))

      it "propagates exceptions" $ do
        eval (error "foobar" :: Property IO) `shouldThrow` errorCall "foobar"

      context "with HUnit Assertion" $ do
        it "includes failure reason" $ do
          H.Result "" (H.Failure _loc reason) <- eval ((\ _ -> assertFailure "some failure") :: Int -> Assertion)
          reason `shouldBe` H.Reason "there exists 0 such that\nsome failure"

        context "with assertEqual" $ do
          it "includes actual and expected" $ do
            H.Result "" (H.Failure _loc reason) <- eval (assertEqual "foo" (42 :: Int))
            reason `shouldBe` H.ExpectedButGot (Just "there exists 0 such that\nfoo") "42" "0"
  where
    eval :: Testable IO a => a -> IO H.Result
    eval = evaluateExample . property

    evaluateExample :: (Example a, Arg a ~ ()) => a -> IO H.Result
    evaluateExample e = H.evaluateExample e defaultParams ($ ()) (const $ return ())

    defaultParams :: H.Params
    defaultParams = H.Params stdArgs (H.configSmallCheckDepth H.defaultConfig)