fakedata-quickcheck-0.1.0: src/Test/QuickCheck/Gen/Faker.hs
module Test.QuickCheck.Gen.Faker
( fakeQuickcheck'
, fakeQuickcheck
)
where
import Faker
import System.IO.Unsafe (unsafePerformIO)
import System.Random (mkStdGen)
import qualified Test.QuickCheck as Q
fakeQuickcheck :: Fake a -> Q.Gen a
fakeQuickcheck = fakeQuickcheck' defaultFakerSettings
-- | copied from https://github.com/parsonsmatt/hedgehog-fakedata/blob/d342c6eb5aeb9990bb36ede1d1f08becc7d71e16/src/Hedgehog/Gen/Faker.hs
-- Works in Quickcheck gen instead of hedgehog
--
-- Select a value 'Fake' program in 'Gen'.
--
-- Note that the implementation relies on 'unsafePerformIO'.
-- The faker library uses IO internally for looking up data files.
-- but 'liftIO' in the 'Fake' monad is a gateway to arbitrary side effects.
-- This library doesn't solve that.
fakeQuickcheck' :: FakerSettings -> Fake a -> Q.Gen a
fakeQuickcheck' fakerSettings f = do
randomGen <- mkStdGen <$> Q.choose (minBound, maxBound)
pure $!
unsafePerformIO $
-- (parsonsmatt): OK so `unsafePerformIO` is bad, unless you know exactly
-- what you're doing, so do I know exactly what I am doing? Perhaps I can
-- convince you.
--
-- The Faker library doesn't keep the data as Haskell values, but stores it
-- in `data-files`. The code that generates this fake data loads the values
-- from the `data-files` for the library. That's what happens in IO. It is
-- possible that the data-file is missing, and an exception will be thrown.
-- However, no mutating actions are performed. I believe this is a safe use
-- of 'unsafePerformIO'.
--
-- The alternative would be to lift it into `GenT IO a`, which is
-- undesirable, as it would harm composition with basically any other
-- generator.
Faker.generateWithSettings
(Faker.setRandomGen
randomGen
fakerSettings
)
f