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 报告中,以便计算统计数据。

另一种方案是将统计作为外部库/报告器实现,但为此我们需要 trials 循环保留每个试验的结果映射中的任意状态,在那里我们可以累积标签。或者,也许我们可以使(reporter-fn :type :trial ...) 包含整个结果映射,这样报告器函数就有机会“保存”这个状态,但这种方法看起来并不是非常优雅...

0

评论者:gfredericks

需要考虑的事项

  • 这些统计数据仅是args的函数,因此是否需要将整个属性包裹起来?
    不过Haskell确实这么做
  • 另一方面,我喜欢统计学作为check命名空间通用特性的一个特定实例的想法,但当前的实现并没有完全达到这一点,因为我们在check命名空间中有大量的标签条目
  • 但是很难将其移出来,因为如果check只是公开了一个通用的reduce特性,那么直接访问quick-check的用户将需要提供两件事情——一个包装好的属性,以及正确的reduce函数
0
by

评论者:nberger

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

在这个新的补丁中,一些东西被简化了

  • 移除了新变量* } var,该变量原本被用来启用/禁用每个测试的统计数据打印。现在,默认的reporter-fn只有在结果映射中存在标签时才会打印统计数据。要打印统计数据,只需使用不同的:reporter-fn即可,它不会打印统计数据。
  • 在统计数据报告中,现在只打印带有标签的行。在之前的版本中,有一行显示“无标签”的试验百分比。我已将其移除,以减少冗余。

还添加了一些文档字符串,确保了统计数据在clojurescript中能工作,以及其他一些微小改进。

0
by

评论者:nberger

我想为分配标签给试验提供更多方式。例如

  1. {{(classify prop)}}:它仅使用args的向量作为标签。
  2. {{(classify prop label-fn)}}:通过将一个{{label-fn}}应用于args来获取标签。例如:{{(classify prop count)}} - 将args的计数(向量、字符串等)分配为标签
  3. {{(classify prop label-fn pred)}}:仅在{{pred}}返回真值时应用{{label-fn}}。例如:(classify prop count #(> (count %) 1)) - 只有当计数大于1时,才将计数值分配为标签
  4. {{(classify prop pred)}}:仅在{{pred}}返回真值时,使用args的向量作为标签。例如:(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 页面上解决“测试失败反馈”问题所做的更改:http://dev.clojure.org/display/design/test.check

0

评论者:gfredericks

我还应该牢记,这可能会影响 confluence 页面上解决“测试失败反馈”问题所做的更改:http://dev.clojure.org/display/design/test.check

0

评论者:nberger

bq. 我们讨论了是否有必要将 nil 视为在 collect 中不进行标记的标志,但我并不特别赞成这个想法。

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

`
(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

评论者:nberger

添加了一个新的补丁TCHECK87-add-stats-feature-2.patch,它基于当前主版本。我不认为这是最终版本(我希望能找到一种方法来避免将标签等冗余内容添加到主要的快速检查循环中)但希望这更接近最终版本了。

0

评论者:nberger

添加了一个基于当前主版本的新补丁TCHECK87-add-stats-feature-3.patch,其中包含一些压缩的提交。还修复了ClojureScript中的print-stats测试。

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

有什么阻碍这个补丁吗?

...