如何为 quickBatch 测试编写 EqProp 实例?

How to write EqProp instances for quickBatch tests?

我遇到过 2 个例子:

data List a = 
    Nil 
  | Cons a (List a) 
  deriving (Eq, Show) 

instance Eq a => EqProp (List a) where
  (=-=) = eq
newtype ZipList' a = 
  ZipList' (List a) 
  deriving (Eq, Show)

instance Eq a => EqProp (ZipList' a) where 
  xs =-= ys = xs' `eq` ys' 
    where xs' = let (ZipList' l) = xs 
                in take' 3000 l 
          ys' = let (ZipList' l) = ys 
                in take' 3000 l 

take' :: Int -> List a -> List a
take' n (Cons a as) = Cons a (take' (n - 1) as)

(还有FunctorApplicative实例,正在测试中):

main :: IO ()
main =
  hspec $ do
    describe "List" $ do
      it "Functor" $
        property (quickBatch $ functor (undefined :: List (Int, Float, String)))
      it "Applicative" $
        property
          (quickBatch $ applicative (undefined :: List (Int, Float, String)))
    describe "ZipList'" $ do
      it "Functor" $
        property
          (quickBatch $ functor (undefined :: ZipList' (Int, Float, String)))
      it "Applicative" $
        property
          (quickBatch $ applicative (undefined :: ZipList' (Int, Float, String)))

据我了解,我们采用 3000 个值,否则测试将永远追逐无限列表。但是在第一个例子中,也有一个无限列表,不是吗?那么为什么 EqProp 在这种情况下微不足道?

您的 属性 测试库(我知道 quickCheck,但不知道 quickBatch)应该在生成值时管理数据大小,而不是在比较值时。限制相等性检查的大小不是一个好主意,因为这意味着

  1. 数据生成可以是无限的,因此您的测试在进行相等性检查之前可以是非终止的
  2. 您可能会在第 3001 个元素不同的地方出现误报

因为已经有 [] 的实例并且 ZipList 是一个 newtype 我们可以像这样免费获得实例。

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE StandaloneDeriving #-}

deriving instance Eq a => EqProp (ZipList' a)