快速检查自定义数据类型

时间:2016-03-01 15:01:17

标签: haskell quickcheck

我成功地对此进行了快速检查:

testaroo = quickCheck $ checkWin

checkWin :: [(Int, ThePlayers)] -> Bool
checkWin [(1,_),(2,_),(3,_)] = True
checkWin [(4,_),(5,_),(6,_)] = True
checkWin [(7,_),(8,_),(9,_)] = True
checkWin [(1,_),(5,_),(9,_)] = True
checkWin [(3,_),(5,_),(7,_)] = True
checkWin [(1,_),(4,_),(7,_)] = True
checkWin [(2,_),(5,_),(8,_)] = True
checkWin [(3,_),(6,_),(9,_)] = True
checkWin _ = False

但是当我尝试运行时

testaroo = quickCheck $ removeFromList

removeFromList :: (Int, ThePlayers) -> [(Int, ThePlayers)] -> [(Int, ThePlayers)]
removeFromList tuple list = delete tuple list

我遇到以下情况:

No instance for (Arbitrary ThePlayers)
      arising from a use of `quickCheck'
    Possible fix:
      add an instance declaration for (Arbitrary ThePlayers)
    In the expression: quickCheck
    In the expression: quickCheck $ removeFromList
    In an equation for `testaroo':
        testaroo = quickCheck $ removeFromList
Failed, modules loaded: none.

我在checkWin上成功运行了我的quickCheck,我添加了

instance Arbitrary BoardState
    where
    arbitrary  = arbitrary

但说实话,我不太清楚这是做什么的:)。无论如何我可以在我的removeFromList函数上运行测试吗?

2 个答案:

答案 0 :(得分:4)

QuickCheck必须通过

生成随机案例以测试您的财产
No instance for (Arbitrary ThePlayers)

它基本上说它不知道如何为测试生成随机ThePlayers值,你应该实现一个实例Arbitrary ThePlayers

quickCheck的类型也是

quickCheck :: Testable prop => prop -> IO () 

即使模块可以为您生成随机参数,函数removeFromList看起来也不像Testable(属性),checkWin:函数的属性是关于:它应该是什么样的正确结果?结果应该满足什么?参数与结果之间的关系是什么? QuickCheck模块不会也不能从您的函数生成属性,您必须自己指定它。

(顺便说一句,你对checkWin的第一次测试只是因为它有一个偶然的返回类型Bool,它没有表明你的程序的任何属性,几乎每次都会失败)

例如,来自reverse的{​​{1}}函数的一个属性是: Data.List函数不应更改列表的长度,因此请根据这个事实应该是:

reverse

然后您可以基于它构建测试:

prop_length :: [Int] -> Bool
prop_length as = length as == length (reverse as)

您可以尝试some tutorials了解更多信息。

答案 1 :(得分:3)

Arbitrary是一个类型类,只需要实现一个函数arbitrary。正如文档所说:

arbitrary :: Gen a
     

给定类型值的生成器。

Gen是一个monad,允许您构建" 随机"值。 QuickCheck 将使用它来生成随机实例,以生成随机列表[(Int, ThePlayers)]来测试该属性。

由于您没有显示data ThePlayers的定义,我们只能猜测如何生成任意值。

一个例子可能是:

data Foo = Positive Int | Coordinate Int Int | Character Char

instance Arbitrary Foo where
    arbitrary = oneof [arbitraryPositive,arbitraryCoordinate,arbitraryCharacter]
        where arbitraryPositive = do
                  p <- arbitrary
                  return $ Positive $ abs p
              arbitraryCoordinate = do
                  x <- arbitrary
                  y <- arbitrary
                  return $ Coordinate x y
              arbitraryCharachter = do
                  c <- arbitrary
                  return $ Character c