【问题标题】:How can randomly generated input for a function be used for testing in a systematic way?如何以系统的方式将随机生成的函数输入用于测试?
【发布时间】:2017-02-28 15:21:33
【问题描述】:

如何以系统的方式使用随机输入测试方法?我的意思是,如果被测试单元的输入数据每次运行都发生变化,那么如何有效地找出导致失败的值并在代码更改后重新测试这些相同的值?例如函数int[] foo(int[] data),它可以检查返回值是否正确,在为“硬编码输入”(例如{1,2,3})编写测试用例之后如何测试随机输入?如果每次都是随机的,任何错误都不会重现。我可以将随机输入打印到屏幕上,但这对于每个功能都会变得混乱。有什么建议?

另外,如果整个程序都在测试,它仍然是单元测试吗?例如在一个@Test中调用构造函数和类的所有方法?这个类只有一个开始的公共方法,所以这无法避免,但我想知道 JUnit 是否是它的最佳工具。

【问题讨论】:

  • 当输入是随机的,你怎么知道预期的结果是什么?
  • @TimothyTruckle 在某些情况下可以检查,例如很容易检查返回的值是否已排序。
  • 这是一场我工作的辩论,我们当然不同意。在某些情况下,随机测试是您能做的最好的事情,并且在某些人中他们受到高度尊重。为了测试中值算法,我编写了一个对输入进行混洗的测试,但由于我知道元素是什么,我也可以独立于它们的顺序来判断正确的中值。显然,这个测试并不是孤立的,但理论上它可能有一天会发现一个尚未被破坏的错误。
  • 为了可复制性,将随机种子打印到屏幕上。
  • 当我们对某个行为进行单元测试时,当测试失败时,我们可以清楚地了解原因。使用随机输入,您无法(轻松)重现错误情况。

标签: java testing junit language-agnostic


【解决方案1】:

基于属性的测试可能是您的解决方案。基本上,这个想法是让一个框架生成各种输入数据(随机、边缘情况),然后将其输入到您的实现中。

确实,对于随机数据,您最终可能会发现测试用例在每次运行时表现不同。但至少测试框架通常会告诉您在测试失败时使用了哪个输入,您可以进一步了解失败的原因。不能保证你的方法在 100% 的情况下都有效,但至少你得到了一些覆盖,总比没有好。

通常,这样的框架还允许您将生成的数据限制为对您的实施有意义的集合。或者您可以实现自己的生成器,为您的测试提供数据。

对于 Java,例如JUnit-Quickcheck 与 JUnit 集成:http://pholser.github.io/junit-quickcheck/site/0.6.1/

关于单元测试/集成测试等之间的差异已经写了很多。也许看看这里:What is the difference between integration and unit tests?

【讨论】:

    【解决方案2】:

    如何以系统的方式随机输入测试方法?

    在一般情况下,从最严格的意义上说,您不能。 “严格意义上”我的意思是:验证输出的正确性,无论呈现哪个输入。

    假设有可能,“严格性”意味着您的测试用例可以计算函数在每个(随机)输入上的结果。这意味着您将需要编写一段代码来复制要测试的方法——理论上可行,但会导致矛盾的情况:

    • 假设您在被测方法中发现了多个错误。什么是最便宜的纠正方法?当然,用测试代码代替方法代码

    • 现在测试人员(当前实现的方法的作者)需要……什么?……写另一个函数的“化身”来测试她自己的实现?

    但是,"fuzzing" 仍然是一个有效的方法:除了严格意义上的从不;测试期望结果暴露某些特征/不变量/等,无论输入是什么,都可以定义/检查。例如,“该方法永远不会抛出”,或“返回的数组与输入数组的长度相同(或两倍大小,或所有元素都是奇数,或其他任何东西”或“结果总是一个正确的 HTML 页面,通过W3C markup validator"。

    系统方式使用随机输入进行测试?

    伙计,你在这里几乎有一个矛盾的说法,比如“诚实的政治家”或“2016 年制造的飞机安全 Galaxy 7 Note”。如果测试是“系统的”,则意味着“有一个(规则)系统来管理测试的进行方式”——与“随机输入”几乎完全相反。

    调和两者的诀窍:您仍然有一个(基于规则的)系统来对您的输入进行分类(例如 equivalence partitioning ),除了您选择代表而不是为您的类别选择某个(恒定的)代表随机。我要重复一遍:在每个类别中,你随机选择你的代表; (而不是“选择一个随机输入并查看它属于哪个类别”)。
    这有什么用?没有太大的附加值,因为根据系统/等效性,选择代表与选择其他代表一样好。

    对不起,我的 QA 伙伴,作为测试人员,您在设计和计划测试方面的责任并没有失控(无论您是否使用随机技术来生成输入)。

    如果每次都是随机的,任何错误都不会重现。我可以将随机输入打印到屏幕上,但这对于每个功能都会变得混乱。有什么建议?

    这是避免随机输入的一个轻率理由如果认为随机输入是必要的:如果简单的流动文本格式难以阅读,只需使用一些工具直观地组织测试日志。

    例如输出您的测试日志,格式为具有特定结构的 JSON,并使用/编写可视化工具来表示/探索/折叠/展开它,这样人类的探索就不会对身体的后部造成痛苦。
    如果您的工作是自动化测试,那么您应该能够编写代码,不是吗?

    另外,如果整个程序都在测试,它仍然是单元测试吗?

    “整个程序正在测试”到底是怎么回事?这个“全系统测试”的具体目标是什么?
    “单元测试”(甚至是超过 10000% 覆盖率的单元测试)与“功能测试”或“集成测试”或“性能测试”或“可用性测试”或“本地化测试”之间存在区别”(这包括 UI/错误消息的语法)-所有后者都属于“整个程序测试”,而不是单元测试。

    提示:在定义测试类型时,设计/执行测试时考虑的特定目标优先于测试中使用的方法;我见过使用 GUI 测试工具手动执行的测试,其中测试人员手动将值写入 单元测试下面的 SDK。

    另一方面,有一些类别的非单元测试可能利用单元测试技术(例如,Web 或 REST 服务 - 将其包装并呈现为代理功能 API 和那么你可以使用 JUnit/TestBG 或任何你喜欢的单元测试框架来编写你的测试。然而,你正在做功能或集成测试)。

    【讨论】:

      猜你喜欢
      • 2017-04-16
      • 1970-01-01
      • 1970-01-01
      • 2023-04-08
      • 1970-01-01
      • 2016-04-11
      • 2018-06-15
      • 1970-01-01
      • 2021-09-03
      相关资源
      最近更新 更多