I'm trying to do a property-based test for a chess game. I have set up the following typeclass
class Monad m => HasCheck m where
isCollision :: Coord -> m Bool
which checks if a given coordinate contains a collision or out of bounds.
Now I have a function that generates the moveset of allowed actions for a knight like the following
collisionKnightRule :: HasCheck m => Coord -> m (Set Coord)
collisionKnightRule =
Set.filterM isCollision . knightMoveSet
-- | Set of all moves, legal or not
knightMoveSet :: Coord -> Set Coord
knightMoveSet (x,y) =
Set.fromList
[ (x+2,y-1),(x+2,y+1),(x-2,y-1),(x-2,y+1)
, (x+1,y-2),(x+1,y+2),(x-1,y-2),(x-1,y+2)
]
knightMoves :: HasCheck m => Coord -> m (Set Coord)
knightMoves pos =
do let moveSet =
knightMoveSet pos
invalidMoves <- collisionKnightRule pos
return $ Set.difference moveSet invalidMoves
and an instance for the HasCheck class for an arbitrary coordinate
instance HasCheck Gen where
isCollision _ =
Quickcheck.arbitrary
and so afterwards to test this I want to ensure that the generated moveset is a proper subset of all possible moves.
knightSetProperty :: Piece.HasCheck Gen
=> (Int,Int)
-> Gen Bool
knightSetProperty position =
do moves <- Piece.knightMoves position
return $ moves `Set.isProperSubsetOf` (Piece.knightMoveSet position)
-- ... later on
it "Knight ruleset is subset" $
quickCheck knightSetProperty
Of course this fails because it could be that the knight can't move anywhere, which would mean that it's not a proper subset but the same set. However the error reported is not particularly helpful
*** Failed! Falsifiable (after 14 tests and 3 shrinks):
(0,0)
This is because quickcheck doesn't report the generated value of isCollision. Therefore I wonder, how can I make quickCheck report the generated value of isCollision
?
Aucun commentaire:
Enregistrer un commentaire