标签: haskell-hedgehog

使用Hedgehog(或任何其他基于属性的测试框架)生成随机GADT的最安全方法

我有像这样的GADT:

data TType a where
    TInt  :: TType Int
    TBool :: TType Bool
Run Code Online (Sandbox Code Playgroud)

我想要一个像这样的功能:

genTType :: Gen (TType a)
Run Code Online (Sandbox Code Playgroud)

哪个可以生成TType类型的随机构造函数.我可以通过创建存在的合格数据类型来实现这一点

data AnyType = forall a . MkAnyType (TType a)
Run Code Online (Sandbox Code Playgroud)

然后生成随机数01(包括)并AnyType根据整数值创建.像这样:

intToAnyType :: Int -> AnyType
intToAnyType 0 = MkAnyType TInt
intToAnyType 1 = MkAnyType TBool
intToAnyType _ = error "Impossible happened"
Run Code Online (Sandbox Code Playgroud)

但这种方法对我来说有几个缺点:

  1. 没有外部类型安全.如果我向TType数据类型添加另一个构造函数,我可能忘记修复测试,编译器不会警告我这一点.
  2. 编译器无法阻止我写作intToAnyType 1 = MkAnyType TInt.
  3. 我不喜欢这个error.Int类型太宽泛了我.让这种模式匹配详尽无遗是件好事.

我可以在Haskell中做些什么来消除尽可能多的缺点?最好使用此模块的发电机:

haskell type-safety gadt property-based-testing haskell-hedgehog

7
推荐指数
1
解决办法
216
查看次数

在Hedgehog中通过'Gen'或'forAll'生成随机输入之间的区别

假设,我想在Haskell Sumhedgehog库的帮助下测试以下的associativity属性:

a <> (b <> c) ? (a <> b) <> c
Run Code Online (Sandbox Code Playgroud)

我实际上有两种方法来生成随机输入.

1.生成全部Gen(使用Gen'Applicative和Monad实例)

genTriple :: Get (Int, Int, Int)
genTriple = liftA3 (,,) Gen.enumBounded Gen.enumBounded Gen.enumBounded

prop_assoc :: Property
prop_assoc = property $ do
  (a, b, c) <- forAll genTriple
  (Sum a <> Sum b) <> Sum c === Sum a <> (Sum b <> Sum c)
Run Code Online (Sandbox Code Playgroud)

2.生成每个字段 forAll

prop_assoc :: Property
prop_assoc = property $ do
  a <- forAll Gen.enumBounded …
Run Code Online (Sandbox Code Playgroud)

testing automated-tests haskell property-based-testing haskell-hedgehog

7
推荐指数
1
解决办法
184
查看次数

QuickCheck:为什么没有通过测试的函数以及使用什么来代替?

为什么没有QuickCheck类似于hedgehog's的函数success?我特别想知道如何翻译如下属性:

prop_specialPair :: Property
prop_specialPair = property $ do
  (_, xs) <- forAll specialPair
  case xs of
    x:_ -> x /== 3
    _   -> success

Run Code Online (Sandbox Code Playgroud)

QuickCheck如果我使用=/=,然后我被迫返回类型的东西Property,而且似乎有没有固定函数返回一个通过性。

所以我要么不得不求助于Bool类型:

prop_specialPair :: SpecialPair -> Bool
prop_specialPair SpecialPair { xs } =
  case xs of
    x:_ -> x == 3
    _   -> True
Run Code Online (Sandbox Code Playgroud)

或者对 使用非常尴尬的编码success,例如:

prop_specialPair :: SpecialPair -> Property
prop_specialPair SpecialPair { xs } =
  case xs …
Run Code Online (Sandbox Code Playgroud)

haskell quickcheck haskell-hedgehog

7
推荐指数
1
解决办法
105
查看次数

QuickCheck 中的相关收缩

我面临着为一个生成器编写一个收缩函数的问题,该函数取决于另一个生成器输出的值。基本上是以下形式的生成器:

do
  a <- genA
  b <- f a
  pure $! g a b
Run Code Online (Sandbox Code Playgroud)

在哪里genA :: Gen af :: a -> Gen b g :: a -> b -> c。为了论证的方便,假设g = (,). 那么问题是,给定一对(a, b),收缩可能会破坏,和a之间存在的关系。afb

举个例子,请考虑以下具有缓存长度的列表:

data List =
  List
  { llength :: Int
  , list :: [Int]
  } deriving (Eq, Show)
Run Code Online (Sandbox Code Playgroud)

arbitrary函数可以很容易地定义:

instance Arbitrary List where
  arbitrary = do
    n <- choose (0, 10)
    xs …
Run Code Online (Sandbox Code Playgroud)

haskell quickcheck haskell-hedgehog

5
推荐指数
1
解决办法
165
查看次数

为什么这个 Hedgehog 生成器没有收缩得更快?

我制作了一个 Hedgehog 生成器,可以通过以下方式生成任意 256 位值:

genWord256 :: Gen Word256
genWord256 = do
  bytes <- Gen.integral (Range.linear 0 31)
  let lo = 2 ^ (8 * bytes)
      hi = 2 ^ (8 * (bytes + 1))
  pred <$> Gen.integral (Range.constant lo hi)
Run Code Online (Sandbox Code Playgroud)

让 size 参数决定数字中的字节数,我认为对我的应用程序很有意义。但是,评估此生成器如何缩小并应用于ceiling . logBase 2此,我的问题是:

为什么刺猬决定强调其初始结果的附近?我是否以某种方式误解了“不受大小参数影响的范围含义?( Range.constant) 我会认为这里的任何收缩都必须具有较少的位数。

?> Gen.print genWord256
=== Outcome ===
68126922926972638
=== Shrinks ===
112                 -- 7 bits
4035711763          -- 32 bits
106639875637011     -- 47 bits
281474976710655 …
Run Code Online (Sandbox Code Playgroud)

haskell haskell-hedgehog

4
推荐指数
1
解决办法
69
查看次数