哈斯克尔/ SmallCheck:如何控制`Depth`参数? [英] Haskell / SmallCheck: How to control the `Depth` parameter?

查看:160
本文介绍了哈斯克尔/ SmallCheck:如何控制`Depth`参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的数据结构smallcheck进行测试。

  { - #语言FlexibleInstances,MultiParamTypeClasses# - }
{ - #语言DeriveGeneric# - }进口Test.Tasty
进口Test.Tasty.SmallCheck
进口Test.SmallCheck.Series
进口GHC.Generics数据T1 = T1 {P1 ::诠释,
               P2 ::字符,
               P3 :: [INT]
             }导出(均衡器,显示,一般)例如单子M =>串行米T1主要:: IO()
主要= defaultMain测试测试:: TestTree
测试= testGroup测试[scProps]scProps = testGroup(由SmallCheck选中)
  [testPropertyTest1的prop_test1
  ]prop_test1 X = X ==点¯x
             其中,类型=(X :: T1)

在运行测试有没有通用的解决方案来设置深度参数为(个人)的测试,或者更好的是,一个细粒度的解决方案将深度参数个别领域如:限制 P3 深度为2,避免搜索空间的组合爆炸?

提前感谢!

朱尔斯

信息:
一个有点相关的问题是<一个href=\"http://stackoverflow.com/questions/20092191/how-much-should-one-control-the-depth-parameter-in-smallcheck\">here.

编辑:结果
我参加了公认的答案给出的解决方案,通过罗马Cheplyaka 并在最小的工作示例实现他们(感谢,罗马):

  { - #语言FlexibleInstances,MultiParamTypeClasses# - }进口Test.Tasty
进口Test.Tasty.Options
进口Test.Tasty.SmallCheck
进口Test.SmallCheck.Series
进口Data.Functor
- ================================================ =============================
主要:: IO()
主要= defaultMain测试
- ================================================ =============================
- 要测试的数据结构
数据T1 = T1 {P1 ::诠释,
               P2 ::字符,
               P3 ::诠释,
               P5 :: [INT]
             }导出(显示,公式)
- ================================================ =============================
- 一些测试的属性
prop_test1 X Y = X ==ÿ
               其中,类型=(X :: T1,Y :: T1)
prop_test2 X = X ==点¯x
             其中,类型=(X :: T1)
- ================================================ =============================
- 如何改变搜索空间的深度?
{ - |我可能性:命令行| - }
- 富@ $酒吧runhaskell Test.hs --smallcheck深入2 - ------------------------------------------------ -----------------------------
{ - |可能性二:| - }
- 正常:
- 测试:: TestTree
- 试验= testGroup测试[scProps] - 自定义:
测试:: TestTree
测试= localOption D $ testGroup测试[scProps]
      其中,d = 3 :: SmallCheckDepthscProps = testGroup(由SmallCheck选中)
  [testPropertyTest1的prop_test1,
    testPropertyTest2的prop_test2
  ] - ------------------------------------------------ -----------------------------
{ - |可能性三:制作的系列类型的实例时,调整深度| - }
- 正常:
- 实例(Monad的M)=&GT;串行米T1哪里
- 系列= T1&LT; $&GT;系列&LT;&〜GT;系列&LT;&〜GT;系列&LT;&〜GT;系列 - 自定义:
实例(单子M)=&GT;串行米T1哪里
    系列= localDepth(常量4)$ T1&LT; $&GT; (localDepth(常量2)系列)LT;〜&GT;系列&LT;&〜GT;系列&LT;&〜GT; (decDepth系列) - (几个例子):
- 实例(Monad的M)=&GT;串行米T1哪里
- 系列= decDepth $ T1&LT; $&GT;系列&LT;&〜GT;系列&LT;&〜GT;系列&LT;&〜GT; (decDepth系列)
- 实例(Monad的M)=&GT;串行米T1哪里
- 系列= localDepth(常量3)$ T1&LT; $&GT;系列&LT;&〜GT;系列&LT;&〜GT;系列&LT;&〜GT;系列
- 实例(Monad的M)=&GT;串行米T1哪里
- 系列= localDepth(常量4)$ T1&LT; $&GT;系列&LT;&〜GT;系列&LT;&〜GT;系列&LT;&〜GT; (decDepth系列)


解决方案

我将列出控制的美味和放大器的手段启动; smallcheck提供开箱即用的:


  • 在当前的运行一个测试套件,你可以通过 - smallcheck深度选项来控制«共同»深度

  • 在当前的的测试套件,你可以使用 adjustOption 来调整任何相对什么已经在命令行上指定子树的深度(或父树)

  • 最后,编写串行实例时,您可以使用 localDepth 来调整你有多深想为每个特定的领域,相对于整个结构的深度。通常它的整体深度 - 1(这是 decDepth 不标准的定义),但你可以创造自己的规则

因此​​,这样的控制是可能的,虽然在一个间接的方式。通常,这是你想要什么呢 - 参见这个答案

如果您的真正的要在运行时控制各个领域的深度......是的,这是可能的,虽然这是一个有点复杂,因为它不是一个预期的用例。 (不过,这是pretty很酷,它可能在所有!)这里有一个工作的例子。

如果这个功能对你很重要,也许在github上打开的问题,并解释为什么你需要它。 (但是,首先,一定要读我到上面链接ocharles反应。这是罕见的,你需要在所有调整运行时的深度。)

I have a simple data structure to test in smallcheck.

{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}
{-# LANGUAGE DeriveGeneric #-}

import Test.Tasty
import Test.Tasty.SmallCheck
import Test.SmallCheck.Series
import GHC.Generics

data T1 = T1 { p1 :: Int,
               p2 :: Char,
               p3 :: [Int]
             } deriving (Eq, Show, Generic)

instance Monad m => Serial m T1

main :: IO ()
main = defaultMain tests

tests :: TestTree
tests = testGroup "Tests" [scProps]

scProps = testGroup "(checked by SmallCheck)"
  [ testProperty "Test1" prop_test1
  ]

prop_test1 x = x == x
             where types = (x :: T1)

When running the tests is there any general solution to set the Depth parameter for the (individual) tests, or better yet, a fine grained solution to set the Depth parameter for individual fields e.g. limit the depth of p3 to 2 to avoid the combinatorial explosion of the search space?

Many thanks in advance!

jules

info: A somewhat related question is here.

EDIT:
I took the solutions given in the accepted answer by Roman Cheplyaka and implemented them in a minimal working example (thanks, Roman):

{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}

import Test.Tasty
import Test.Tasty.Options
import Test.Tasty.SmallCheck
import Test.SmallCheck.Series
import Data.Functor
-- =============================================================================
main :: IO ()
main = defaultMain tests
-- =============================================================================
-- the data structure to be tested
data T1 = T1 { p1 :: Int,
               p2 :: Char,
               p3 :: Int,
               p5 :: [Int]
             } deriving (Show, Eq)
-- =============================================================================
-- some test-properties
prop_test1 x y = x == y
               where types = (x :: T1, y :: T1)
prop_test2 x = x == x
             where types = (x :: T1)
-- =============================================================================
-- how to change the depth of the search spaces?
{-| I Possibility: Command Line |-}
-- foo@bar$ runhaskell Test.hs --smallcheck-depth 2

-- -----------------------------------------------------------------------------
{-| II Possibility: |-}
-- normal:
-- tests :: TestTree
-- tests = testGroup "Tests" [scProps]

-- custom:
tests :: TestTree
tests = localOption d $ testGroup "Tests" [scProps]
      where d = 3 :: SmallCheckDepth

scProps = testGroup "(checked by SmallCheck)"
  [ testProperty "Test1" prop_test1, 
    testProperty "Test2" prop_test2 
  ]

-- -----------------------------------------------------------------------------
{-| III Possibility: Adjust Depth when making the type instance of Serial |-}
-- normal:
-- instance (Monad m) => Serial m T1 where
--   series = T1 <$> series <~> series <~> series <~> series 

-- custom:
instance (Monad m) => Serial m T1 where
    series = localDepth (const 4) $ T1 <$> (localDepth (const 2) series) <~> series <~> series <~> (decDepth series) 

-- (a few more examples):
-- instance (Monad m) => Serial m T1 where
--    series = decDepth $ T1 <$> series <~> series <~> series <~> (decDepth series ) 
-- instance (Monad m) => Serial m T1 where
--   series = localDepth (const 3) $ T1 <$> series <~> series <~> series <~> series 
-- instance (Monad m) => Serial m T1 where
--    series = localDepth (const 4) $ T1 <$> series <~> series <~> series <~> (decDepth series) 

解决方案

I'll start by listing the means of control that tasty & smallcheck provide out of the box:

  • when running a test suite, you can pass the --smallcheck-depth option to control the «common» depth
  • when writing a test suite, you can use adjustOption to adjust the depth for any subtree relative to what has been specified on the command line (or for the parent trees)
  • finally, when writing Serial instances, you can use localDepth to adjust how much depth you want for each particular field, relative to the depth of the whole structure. Normally it's overall depth - 1 (that's what decDepth does in the standard definitions), but you can invent your own rules.

So, such control is possible, although in an indirect way. Typically it's what you want anyway — see also this answer.

If you really want to control depth of individual fields at runtime... yes, it's possible, although it's a bit complicated, because it wasn't an intended use case. (Still, it's pretty cool that it's possible at all!) Here's a working example.

If this functionality is important for you, maybe open an issue at github and explain why you need it. (But first, be sure to read my response to ocharles that is linked above. It's rare that you need to adjust the depth during runtime at all.)

这篇关于哈斯克尔/ SmallCheck:如何控制`Depth`参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆