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

欢迎!请查阅关于页面以获取更多关于如何使用本服务的信息。

0投票
test.check

Test.check有种子概念,在测试属性时使用。种子可以由当前时间提供或生成。无论哪种方式,单个种子都用于生成测试的所有试验。如果测试失败,尝试在相同输入上重新测试属性的唯一方法是使用相同的种子再次运行所有测试。如果在发现失败之前测试已经运行数小时,这将变得很繁琐。

我希望能够检查导致失败的确切输入属性。朝这个方向迈出的一步是为每个试验提供显式的不同种子(可能是从初始元种子生成的),并在失败时报告一个可以用来运行一次测试的{{[种子大小]}}对。

尽管这与缩小交互方式很有趣,因为我也可能希望重新运行失败中的缩小值。由于缩小值从未明确地从已知的{{[种子大小]}}生成,仅仅这样的信息是不够的。我们可能可以报告{{[种子大小缩小路径]}},其中第三个元素是遍历缩小树时需要遍历的索引列表。可能最糟糕的部分是它可能相当长。

无论如何,我认为这样会比现在的设置更有用。我可能会为维护的一个分叉分支编写类似的代码,但如果我们可以确定具体的设计,我将很高兴为其编写补丁。

4个答案

0投票
_评论者:reiddraper_

当测试失败时,我们会返回最初失败的所有参数和缩小测试的参数。这不足以吗?

例如

{code:none}
      {:result false,
       :failing-size 45,
       :num-tests 46,
       :fail [[10 1 28 40 11 -33 42 -42 39 -13 13 -44 -36 11 27 -42 4 21 -39]],
       :shrunk {:total-nodes-visited 38,
                :深度 18,
                :结果 false,
                :最小化 [[42]]}}


参见 {{:fail}} 和 {{[:shrunk :smallest]}}。
0投票

评论者:gfredericks

从理论上讲,这确实足够复现问题,但是我不知道有任何内置机制可以简化这个过程。我最终做到的如下

给定以下

`
(defspec foo
(prop/for-all [x gen]

(f x)))

`

在获得一个50行缩减值(例如 {{:bar}})的失败后,我手动格式化它并将其粘贴到我的文件中,如下所示

`
(def shrank
':bar)

(defspec foo
(prop/for-all [x #_gen (gen/return shrank)]

(f x)))

`

现在我可以运行 {{(foo 1)}} 来重新执行并使用失败的值。

这种尴尬的情况部分是由于以下三个事实

  1. 我的生成器创建了大型、笨重的值
  2. 我的属性是一段较大的代码,而不是一个单独的函数
  3. 没有简单的方法来测试特定值上的属性

我可以通过解决第2点来减轻一些痛苦——将我的每一个测试分成一个 {{defspec}} / {{prop/for-all}} 和一个普通函数。但第1点不容易解决,而有一个小元组对我来说更合适。

我已经为这个写了一个原型,并且它运行得相当好。我用 {{:key}} 来指代元组,所以这个术语不会与 {{:seed}} 冲突。我最终将测试命名为 {{(foo 0 :key [329489249329323 19 []])}},但我可能会想出一个不需要传递虚拟第一个参数的方法。

0投票

评论者:gfredericks

我认为这类问题在 TCHECK-96 中变得更加重要,因为如果缩减提前终止,那么能够在没有时间限制的情况下再次运行它将是非常好的(不需要像重新运行带有相同种子的 {{quick-check}} 那样运行所有先前的通过测试)。

我刚刚想到了这个想法,它没有我分叉中任意长 "key" 的缺点:我们将 RNG 提升为一个真正的可序列化值,然后在 {{quick-check}} 中跟踪每次试验中使用的 {{[rng size]}} 对,在失败时报告该对。然后我们有一个类似 {{quick-check}} 的新函数,它接受属性和一组并运行单个试验(如果失败,则会缩减)。

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