1

下面的数据结构可以用后面的 Tasty-SmallCheck 相关代码进行测试。有一个与构造函数 ShB 必须保持的关系:第二个和第三个正整数最多应该和第一个一样大。

data Shape = ShA Int Int Bool 
  | ShB Int Int Int Bool Bool 
  deriving (Show,Read,Eq)

构造函数 ShaA 应该具有正 Int,否则参数之间没有关系。

auxShA :: (Positive Int, Positive Int, Bool) -> Shape
auxShA (i,j,b) = ShA (fromIntegral i) (fromIntegral j) b

auxShB :: (Positive Int, Positive Int, Positive Int) -> Bool -> Bool -> Shape
auxShB (a1,a2,a3) = ShB i u d
  where
  (i,u,d) = auxTriplet (a1,a2,a3)

auxTriplet :: (Positive Int, Positive Int, Positive Int) -> (Int,Int,Int)
auxTriplet (a,b,c) 
  | a >= b && a >= c = (fromIntegral a, fromIntegral b, fromIntegral c)
  | b >= a && b >= c = (fromIntegral b, fromIntegral a, fromIntegral c)
  | otherwise        = (fromIntegral c, fromIntegral a, fromIntegral b)

consB :: (Serial m a1, Serial m a2, Serial m a3, Serial m b, Serial m c) =>
  ((a1,a2,a3) -> b -> c -> e) -> Series m e
consB f = decDepth $
  f <$> series
    <~> series
    <~> series

instance Monad m => Serial m Shape where
  series = cons1 auxShA \/ consB auxShB

生成的案例还可以,但是可以看到重复的案例,例如

list 4 series :: [Shape]

问题是,当满足以下条件时,如何使用 SmallCheck (tasty) 生成测试用例?

  • 有些属性必须保持,例如第一个参数必须为正
  • 如果第一个参数应该大于 10::Int 怎么办?
  • 继续,如果第二个参数应该在第一个 - 5 和第一个之间,而第三个应该在第二个 - 5 和第二个之间呢?

或者,如何生成动态依赖于先前生成的值的测试用例?

第一个想法是向 Shape 编写构造函数来检查输入是否有效(例如上面的要点),但是这种方法仍然存在重复测试用例生成的问题。

上面的代码使用了与SmallCheck invariant -answer类似的解决方案 。

4

0 回答 0