请在2024 Clojure 状态调查!中分享您的想法。

欢迎!请查看关于页面,了解有关此功能的一些更多信息。

0
test.check

从 Haskell 的 QuickCheck 中受到启发。增加了一个 {{classify}} 函数,该函数旨在用作 {{prop/for-all}} 的包装器,返回适合 {{test.check/quick-check}} 的属性(生成器),这将增强底层属性返回的 result-map,在 {{: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

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

我认为它回答了来自 test.check 设计页面的“我们如何收集生成物的统计数据?”这个问题

13 个答案

0

评论者:nberger

此补丁在引入 reporter-fn 之后不再适用。

当我忙于编写新的补丁时,我想了解其他人(特别是 gfredericks)对在 test.check 中引入这种新的 :labels 概念的看法。trial 的结果图中的每个结果图都可以选择性地包含一些 :labels,这些标签包括在 :complete 报告中,以便可以从计算统计数据。

另一种选择是实现统计作为一个外部库/reporter,但要实现这一点,我们需要将 trials 循环保持为来自每个 trial 的结果图的任意状态的每个 trial,以便我们可以累积标签。或者,我们也许可以修改 (reporter-fn :type :trial ...) 以包括完整的结果图,这样 reporter-fn 就有机会“保存”此状态,但这种方法看起来并不优雅...

0

由 gfredericks 发表的评论:

需要考虑的事项:

  • 统计信息仅是参数的函数,因此有必要把整个属性包起来吗?
    不过Haskell就是这样做的。
  • 另一方面,我喜欢统计信息成为 {{check}} 命名空间中通用特性的一个特殊实例的想法,但当前实现并没有完全达到这一点,因为我们{{check}}命名空间中有很多标签相关的内容。
  • 然而,将其移动出去是困难的,因为如果 {{check}} 只公开了一个通用reduce特性,那么直接访问 {{quick-check}} 的用户将不得不提供两样东西——一个包装好的属性和正确的reduce函数。
0

评论者:nberger

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

在此新补丁中,某些内容已被简化。

  • 移除了原本计划用作启停每个测试的统计信息打印功能的 new * } var。现在,默认-reporter-fn 只在结果映射中存在标签时打印统计信息。要避免打印统计信息,只需使用不打印统计信息的不同 :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 页面上针对 "测试失败反馈" 问题的修改重叠: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,该补丁基于当前的master版。我不认为这是最终版本(我希望找到一种方法,例如,不让标签相关的内容污染主要的quickcheck循环),但也许它正在逐渐接近。

0

评论者:nberger

新增了基于当前master的TCHECK87-add-stats-feature-3.patch补丁,其中包含一些压缩的提交。同时修复了ClojureScript中的print-stats测试。

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

有什么东西阻碍了这个补丁的发布吗?

...