16

假设我想为该(!!)函数编写一些单元测试。

my_prop xs n = ...

我想将 n 限制为仅有效索引,我知道我可以做类似的事情

my_prop xs n = (not.null) (drop n xs) ==> ...

但这使得绝大多数生成的案例都是无效的并被丢弃。有没有办法可以设置,以便 QuickCheckxs首先生成列表并使用它的值来生成有效的情况n

4

3 回答 3

18

使用forAll,您可以指定一个依赖于早期参数的生成器,例如n

my_prop (NonEmpty xs) = forAll (choose (0, length xs - 1)) $ \n -> ...
于 2012-10-10T20:46:55.390 回答
10

您可以制作一个仅创建有效索引并编写您的属性的生成器,例如

import Test.QuickCheck
import Test.QuickCheck.Gen
import System.Random

indices :: [a] -> Gen Int
indices xs = MkGen $ \sg _ -> fst $ randomR (0, length xs - 1) sg

my_prop :: [Char] -> Property
my_prop xs = not (null xs) ==> forAll (indices xs) (\i -> xs !! i /= '0')

消除Int争论。

于 2012-10-10T20:46:35.260 回答
5

正如 Daniel Wagner 所建议的,一种可能性是创建我自己的数据类型并给它一个Arbitrary实例。

data ListAndIndex a = ListAndIndex [a] Int deriving (Show)

instance Arbitrary a => Arbitrary (ListAndIndex a) where
   arbitrary = do
     (NonEmpty xs) <- arbitrary
     n  <- elements [0..(length xs - 1)]
     return $ ListAndIndex xs n

NonEmptyTest.QuickCheck.Modifiers来自用于生成非空列表的自定义类型。

于 2012-10-11T19:58:33.550 回答