zoukankan      html  css  js  c++  java
  • 当一个数不是数字时:随机测试生成器的好处(译)

    摘要:

    我们希望在划分我们的测试时,我们将考虑所有的场景,但是太容易忽略不常用的用例。这就是随机测试生成器的好处。我们可能在测试几十个测试用例后感觉很舒适;这些工具能生成几百个。随着更多的东西被扔到墙上,一些有趣的东西更有可能被粘在墙上。

    在第一个尝试FsCheck和基于属性的测试后,我恼火了。

    Haskell编程语言已经存在一段时间了,然而我从来不用它。吸引我注意的是一个名为QuickCheck的工具和它引进的算法。因为我一直工作在.NET领域,我采选用FsCheck做研究,一个F#端口的QuickCheck。我的恼火来自于演示list集合的属性。

    当我们反转一个列表,然后再反转一次,我们希望得到初始列表,对吗?在不考虑这个列表有多长或者包含什么,这个属性应该是真的。想象一下当我第一次用FsCheck测试失败时,我有多么惊讶。第一次带有整数列表的测试通过了,但是当我把它变成持有浮点型时,它失败了。

    FSCheck生成随机值填入列表,然后检查属性是否被测试持有。它做了很多很多次测试,为了查找失败的值的组合。在整数的用例中,它不仅仅是我们首先考虑到的1、2、3……,还有会被存储成固定浮点整数、零和负数的最大和最小整数值。我们也需要考虑空列表。FsCheck所有这些都做了。为什么当我考虑浮点数时,它失败了?

    解释来自于对浮点值的定义。他们采用一种位的模式,并将该模式解释为一个带有小数点的数字。无论如何,并不是所有可能的比特组合都可以用这种方式进行有意义的解释。我们把这些麻烦的模式NaN定义为:不是一个数。令我惊讶的是,NaN变量可以是逐位相同的,但不相等。让他们明白这一点。这似乎合情合理,但却有违直觉——而且很容易被忽视。

    我们希望在设计测试的时候,考虑所有这样的病态情况,但是很容易忽略像NaN这样的东西。这就是像FsCheck这样的随机测试生成器的好处。我们在测试几十个测试用例后可能感觉很舒服。FsCheck生成几百个。随着更多的东西被扔到墙上,一些有趣的东西更有可能粘在墙上。

    在FsCheck发现故障之后,它将采取第二步:它试图减少引发问题所需的数据量。我不详细讨论这第二步,因为我的观点是,看到像我刚才用NaN描述的那样的错误有助于我们更深入地思考代码库在做什么——尤其是在将它的测试缩减到最小的形式之后。

    在浮点值列表的情况下,我们可能认为NaN业务是假的。我们这样做甚至可能是正确的。但是运行测试的目的是让我们考虑代码库。也许我们应该在系统的边缘添加一些东西来使NaN值出现在系统之外,或者我们应该确保NaN不能从系统内部的任何转换中产生。

    我们的代码有缺陷,因为我们对它的思考存在盲点。即使是世界上最大的自动测试用例生成器也会有盲点。令人高兴的是,机器和人类有不同的盲点。

        像FsCheck或QuickCheck这样的工具利用了一种不同的测试范例,利用机器的优势来弥补我们的不足。机器可以通过算法制定出大量的测试数据集,这些数据集手工组装起来既昂贵又枯燥。但是他们需要基于属性的测试来消耗所有的数据。

    当我还是一名新程序员时,我并不欣赏这一点。我正在研究一个统计应用程序,它严重依赖于贝叶斯统计和概率。有一些事情你可以依靠条件概率。首先,概率总是在0到1之间。另一方面,当我们总结所有条件时,我们应该得到一个。无论我们在代码中添加什么,这些属性是我们可以自动检查的。

    同样,我最近与一些朋友进行了一次对话,他们正在构建一个计费系统。我问了一些问题:所有的项目都是正数的吗?我们是否知道许多行项目的小计将超过更少项目的小计?在不考虑求和顺序的情况下,总数是否会发生变化?我问,还有哪些属性是不变的,我们可以断言。每个这样的不变量都可以作为基于属性的测试的基础。跟你打赌,我肯定会给这个系统一些负的价格。

    广泛的属性测试可以教会我们很多关于代码库的知识。测试从不确定代码库是无错误的,但是测试确实缩小了错误可以隐藏的范围。为了学得更多,我们必须理解测试的作用和它们所显示的内容。这可能意味着我们应该更多地关注理解我们的测试,而不是仅仅增加少量理解的测试的乘法。就像FsCheck将大型失败测试简化为更简单的表单一样,我们也应该定期检查我们的测试套件。

    是否每个测试告诉我们的不仅仅是重现过去几年bug报告的环境?这些测试是否可以重新组织以阐明我们为什么关心它们?我们的目标应该是策划测试,以最大限度地从每个测试的成功或失败中得到理解。

    当我对浮点的基于属性的测试失败时,NaN让我感到惊讶。这并不是由于列表倒转的故障;它失败的原因是测试中固有的关于如何比较浮点数的假设。这提醒我们寻找与我们的假设相矛盾的数据。我们在测试中加入的惊喜越多,我们的系统就会变得越健壮。这需要结合多种不同的范例和功能来利用每种范例和功能的优势。

    被NaN吓到似乎是个坏消息。它让我们陷入了一个失败的测试,这个测试只与我们正在测试的代码间接相关。但是这样做会让我们想起一些我们可能已经忘记的软件。这样的提醒会把惊喜变成好消息。

  • 相关阅读:
    Building a flexiable renderer
    Indirect Illumination in mental ray
    我的心情
    Cellular Automata
    Subsurface Scattering in mental ray
    Shader Types in mental ray
    BSP Traversal
    我的渲染器终于达到了MR的速度
    How to handle displacement and motion blur
    说明
  • 原文地址:https://www.cnblogs.com/fengye151/p/11165603.html
Copyright © 2011-2022 走看看