请在2024年度Clojure调查问卷中分享您的想法!

欢迎!有关如何使用本指南的更多信息,请参阅关于页面。

0 投票
test.check

受到Haskell的QuickCheck中存在的模拟功能的启发。添加了一个{{classify}}函数,它被设计为{{prop/for-all}}的包装器,返回一个适合{{test.check/quick-check}}的属性(生成器),它将增加底层属性返回的结果映射,在{{:labels}}键下添加收集到的标签。还触发了在{{default-reporter-fn}}中的新事件{{:stats}},其默认实现调用{{test.check.stats/print}},以以下格式打印试验分类

12.7% :lt-30 14.5% :gte-30 29.1% :lt-30, :lt-20 43.6% :lt-30, :lt-10, :lt-20

(注意某些测试用例可能分配了多个标签)

我认为这回答了测试.check设计页面上的问题“我们如何收集关于生成的事物类型的统计数据?”

13 答案

0 投票

评论者:nberger

这里的补丁在引入reporter-fn后不再适用。

当我正在编写新的补丁时,我想知道其他人(特别是gfredericks)对在test.check中实现这个新的:labels概念有何看法。每个试验的结果映射可以可选地包含一些:labels,作为:complete报告的一部分,以便计算统计数据。

另一种选择是实现作为外部库/reporter的统计数据,但要实现这一点,我们需要保留每个试验结果映射中的任意状态,以便积累标签。或者,也许我们可以使(reporter-fn :type :trial ...)包括整个结果映射,这样reporter-fn就有机会“保留”这种状态,但这种方法看起来并不优雅...

0 投票

评论由:gfredericks 发表

需要考虑的事项

  • 统计量仅是参数的函数,因此需要将整个属性包装起来吗?
    尽管haskell 这样做
  • 另一方面,我喜欢将统计作为 {{check}} 命名空间中通用功能的特定实例的想法,但当前的实现并没有完全实现这一点,因为我们{{check}}命名空间中有很多标签相关的内容
  • 但是将其移出来是件困难的事情,因为如果{{check}} 只暴露通用的reduce功能,那么直接使用{{quick-check}}的用户将不得不提供两件事 - 一个包装的属性,和一个适当的reduce函数
0 投票

评论者:nberger

上传了一个利用新的 reporter-fn 机制的补丁。

在这个新补丁中简化了一些内容

  • 删除了即将用作启用/禁用每个测试中统计打印的新 * } var ,默认报告中现在只有在结果映射中有标签时才会打印统计。要禁用统计,只需使用不打印统计的不同 :reporter-fn。
  • 现在仅在统计报告中打印带有标签的行。在先前版本中,有一行显示“没有标签”的试验的百分比。我现在删除了它,以使其更简洁。

还增加了文档字符串,确保统计在 clojurescript 中工作,并进行了其他一些小的改进。

0 投票

评论者:nberger

我认为为试验分配标签提供更多方式会更好。例如

  1. {{(classify prop)}}: 只使用参数向量作为标签。
  2. {{(classify prop label-fn)}}: 通过对参数应用 {{label-fn}} 获取标签。例如:{{(classify prop count)}} - 将参数(向量、字符串等)的计数作为标签分配
  3. {{(classify prop label-fn pred)}}: 仅在 {{pred}} 返回真实值时应用 {{label-fn}}。例如:(classify prop count #(> (count %) 1)) - 仅当计数大于 1 时将参数的计数分配为标签。
  4. {{(classify prop pred)}}: 使用参数向量作为标签,但仅当 {{pred}} 返回真实值。例如:(classify prop #(<= (count %) 1)) - 仅当计数小于或等于 1 时将参数的计数分配为标签。
  5. {{(classify prop pred label)}}: 这是当前的签名。仅在 pred 返回真实值时分配标签

所以我在想更改签名以接收可能的键的映射 {{(:pred :label-fn :label)}}。三个键都是可选的。{{:label}} 和 {{:label-fn}} 不能同时存在。

根据我理解,Haskell QuickCheck (https://hackage.haskell.org/package/QuickCheck-2.8.2/docs/Test-QuickCheck-Property.html) 有不同的函数提供类似的选择
{{(classify prop)}}相当于Haskell QC中的{{collect}}
{{(classify prop label-fn)}}相当于Haskell QC中的{{label}}
{{(classify prop label-fn pred)}}相当于Haskell QC中的{{classify}}

您怎么看,@gfredericks?

0 投票

评论由:gfredericks 发表

讨论之后,我认为2和5是最自然的选择,可能把2称为{{collect}}以反映Haskell版本。

我们讨论过是否将{{nil}}作为在{{collect}}中不标记的标志,但我不太喜欢这个主意。

0 投票

评论由:gfredericks 发表

我也不应该忘记,这可能涉及对confluence页面上的“Test Failure Feedback”问题进行更改: http://dev.clojure.org/display/design/test.check

0 投票

评论由:gfredericks 发表

我也不应该忘记,这可能涉及对confluence页面上的“Test Failure Feedback”问题进行更改: http://dev.clojure.org/display/design/test.check

0 投票

评论者:nberger

bq. 我们讨论过是否将nil作为在collect中不标记的标志,但我不太喜欢这个主意。

也许我们可以使用命名空间关键字来表示应该忽略标签?例如{{clojure.test.check.stats/ignore}}。这样我们就可以通过创建一个在pred不匹配时返回{{stats/ignore}}的函数,很容易地通过collect实现classify。

`
(defn collect
[prop label-fn]
(gen/fmap

(fn [{:keys [args] :as result-map}]
  (let [label (apply label-fn args)]
    (if (= ::ignore label)
      result-map
      (update result-map :labels conj label))))
prop))

(defn classify
[prop pred label]
(collect prop (fn [& args]

              (if (apply pred args)
                label
                ::ignore))))

`

另一个选择可能是向{{collect}}添加一个额外的参数,以接收一个标志,表示是否应该将nil视为标签或忽略它。我更喜欢{{:stats/ignore}}。

0 投票

评论者:nberger

已经用新的补丁替换,这个补丁添加了{{stats/classify}}和{{stats/collect}},正如讨论的那样。我认为这个新的补丁实现了讨论的内容,包括了2和5的情况,函数名与Haskell实现相似,没有对nil进行特殊处理(它是有效的标签),也没有添加我在之前的评论中建议的{{:stats/ignore}}。

0 投票
by

评论者:nberger

添加了一个新的补丁TCHECK87-add-stats-feature-2.patch,该补丁是在当前主分支的基础上重构的。我认为这不是最终版本(我希望能找到一种方法,比如不让标签功能影响到主要的quickcheck循环),但希望它越来越接近了。

0 投票
by

评论者:nberger

添加了一个基于当前主分支的重构补丁TCHECK87-add-stats-feature-3.patch,其中包含一些压缩的提交。同时修复了ClojureScript中的print-stats测试。

0 投票
by
参考:[https://clojure.atlassian.net/browse/TCHECK-87](https://clojure.atlassian.net/browse/TCHECK-87)(由nberger报告)
0 投票
by

这个补丁还有什么在阻止它吗?

...