import Control.Concurrent (threadDelay)
import Control.Monad.IO.Class (liftIO)
import Data.IORef (atomicModifyIORef', readIORef, newIORef)
import qualified Hedgehog.Gen as Gen
import qualified Hedgehog.Range as Range
import Test.Hspec (before, beforeAll, describe, hspec, it, shouldBe)
import Test.Hspec.Hedgehog (PropertyT, diff, forAll, hedgehog,
(/==), (===))
import Test.Hspec.QuickCheck (modifyMaxSuccess)
main :: IO ()
main = hspec $ do
describe "regular tests" $ do
it "works" $ do
True `shouldBe` True
describe "hedgehog" $ do
it "is useful if you get an ambiguous error" $ hedgehog $ do
"no ambiguity" === "no ambiguity"
describe "hedgehog tests" $ do
it "lets you use PropertyT directly" $ hedgehog $ do
x <- forAll $ Gen.integral (Range.linear 0 1000)
y <- forAll $ Gen.integral (Range.linear 0 5000)
diff (x + y) (>=) (x :: Integer)
it "lets you use PropertyT directly without forcing the type" $ do
x <- forAll $ Gen.integral (Range.linear 0 1000)
y <- forAll $ Gen.integral (Range.linear 0 5000)
diff (x + y) (>=) (x :: Integer)
it "renders a progress bit" $ hedgehog $ do
x <- forAll $ Gen.integral (Range.linear 0 1000)
y <- forAll $ Gen.integral (Range.linear 1 5000)
liftIO $ threadDelay (100 * x + y)
describe "with hooks" $ do
before (pure "Hello!") $ do
it "has functions" $ \str -> hedgehog $
str === "Hello!"
it "goes before or after" $ \str -> do
pure () :: PropertyT IO ()
str === "Hello!"
it "generates" $ \str -> hedgehog $ do
wrongLen <- forAll $ Gen.integral (Range.linear 0 3)
length str /== wrongLen
describe "modifyMaxSuccess" $ do
modifyMaxSuccess (\_ -> 10) $ do
beforeAll (newIORef (0 :: Integer)) $ do
it "counts to 10" $ \ref -> hedgehog $ do
liftIO $ atomicModifyIORef' ref (\a -> (a + 1, ()))
True === True
it "works" $ \ref -> do
val <- readIORef ref
val `shouldBe` 10