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.
As Fyodor Soikin writes, you can package these
Arbitrayinstances in a module that you put in your test library.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
newtypedefinitions.I use a naming scheme for that so that I'd typically have
ValidA,InvalidB,AnyB, etc.