快速检查自定义数据类型

Quickcheck on custom datatype

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

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 函数上进行测试 运行 吗?

Arbitrary 是一个类型类,只有一个功能 arbitrary 你必须实现。正如文档所说:

arbitrary :: Gen a

A generator for values of the given type.

Gen 是一个 monad,它允许您构造一个“random”值。 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

QuickCheck 必须生成随机案例以针对您的 属性 进行测试,

No instance for (Arbitrary ThePlayers)

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


quickCheck的类型也是

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

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

(顺便说一句,你在 checkWin 上的第一个测试被编译只是因为它有一个 return 类型 Bool 偶然,它并不表示你的任何 属性程序,几乎每次都会失败)

例如 Data.Listreverse 函数的一个 属性 是: reverse 函数不应更改列表的长度,所以基于这个事实的检查应该是:

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

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

test_propLength = quickCheck prop_length

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