I am learning to use QuickCheck
and find it is a very powerful library. I wrote some toy program with stack
, involving a few customized data
type and defined all Arbitrary
instances in one file in my first run like this and it worked well:
-- MyModule.hs
module MyModule
( A(..)
, B(..)
, ...
) where
data A = ...
data B = ... -- depends on type A
-- in test program
module TestMyModule where
import Test.QuickCheck
import MyModule
( A
, B
)
instance Arbitrary A where
arbitrary = ...
instance Arbitrary B where
arbitrary = ... -- depends on arbitrary for type A
prop_A :: A -> Bool
prop_A = undefined
prop_B :: B -> Bool
prop_B = undefined
main = do
quickCheck prop_A
quickCheck prop_B
This works quite well. However when I tried to separate files into two parts, one for A and one for B I ran into issues. I think this was really caused the test program split-up.
-- TestA program
import Test.QuickCheck
import MyModule (A)
instance Arbitrary A where
arbitrary = ...
...
-- TestB program
import Test.QuickCheck
import MyModule (A, B)
instance Arbitrary B where
arbitrary = ... -- code here depends on type A
I got errors like: No instance for (Arbitrary A) arising from a use of ‘quickCheck'
, which makes sense, because in TestB
program, A
is not an instance of Arbitrary
. But how should I organize the files without putting Arbitrary
instance in MyModule
itself? I wanted to avoid putting test related definitions in the module.
Thank you in advance.
CodePudding user response:
As Fyodor Soikin writes, you can package these Arbitray
instances in a module that you put in your test library.
-- in test program
module MyTests.Arbs with
import Test.QuickCheck
import MyModule
-- Arbitrary instances go here...
-- Import MyTests.Arbs in your other test modules
The compiler ought to complain about orphan instances (it must have done so for the code in the OP as well), so you may want to consider wrapping those types in newtype
definitions.
I use a naming scheme for that so that I'd typically have ValidA
, InvalidB
, AnyB
, etc.