基于属性的PHP测试:比您写bug更快的代码破坏方式

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

基于属性的PHP测试:如何发现您甚至未曾想到的bug

\n\n

您是否曾感觉您的单元测试就像黑暗房间里的手电筒:只照亮您自己照射的方向?您为显而易见的情况编写测试,检查边界值,但仍在生产环境中发现bug。熟悉吗?

\n\n

欢迎来到基于属性的PHP测试的世界。这不仅仅是另一种时髦的方法论。这是一种范式转变:您不再设计具体的例子(基于示例),而是描述您的代码必须满足的属性,并让计算机生成数千个随机场景。

\n\n

在本文中,我们将探讨基于属性的PHP测试如何帮助发现经典测试遗漏的隐藏缺陷。您将看到真实的代码示例,了解Eris库,并理解为什么这种方法正成为严肃项目的标准。

\n\n

什么是基于属性的测试?

\n\n

这个术语来自函数式编程(感谢Haskell和QuickCheck库),但这个想法是通用的。与其编写:

\n\n
public function testAddition(): void\n{\n    $this->assertSame(4, add(2, 2));\n    $this->assertSame(0, add(-1, 1));\n    $this->assertSame(10, add(7, 3));\n}\n
\n\n

您需要表述一个属性:“对于任意整数$a和$b,加法结果add($a, $b)必须等于$b + $a(交换律)”。框架会生成数百个随机对并检查这个属性。

\n\n

区别是巨大的:您不再受限于自己的想象力。机器会找到您永远想不到的组合。例如,如果传入一个非常大的数字、零、负值或null会发生什么?

\n\n

基于属性 vs 基于示例:关键区别

\n\n
    \n
  • 基于示例:您编写具体的输入和预期的输出。快速、清晰,但只覆盖您预见到的情况。
  • \n
  • 基于属性:您描述不变量(属性)并使用随机数据生成器。覆盖未知场景,但需要更抽象的思维。
  • \n
\n\n

理想的方法是结合两者:基于示例用于记录典型情况,基于属性用于压力测试和发现边界错误。

\n\n

为什么基于属性的PHP测试是必备的?

\n\n

PHP是一种动态类型、弱类型语言。这意味着您的函数可能接收到任何东西:字符串而不是数字,对象而不是数组,在期望int的地方出现null。基于属性的PHP测试能很好地发现:

\n\n
    \n
  • 隐式假设 — “我以为这里总是传入正数”。
  • \n
  • 类型问题 — 函数在float上崩溃,尽管它期望int。
  • \n
  • 边界值 — 溢出、空数组、负索引。
  • \n
  • 违反契约 — 函数不保持不可变性或返回意外类型。
  • \n
\n\n

这对于教育项目和库尤其有价值,因为用户可能传入任何数据。如果您为他人编写代码,基于属性的测试就是您防止愚蠢错误的保险。

\n\n

Eris库:用于基于属性的PHP测试的工具

\n\n

PHP生态系统中有几个库,但最成熟的是Eris(Giorgio Sironi原始Eris的一个分支)。它与PHPUnit集成,并提供强大的生成器和缩减器(shrinking — 自动将示例缩减到重现错误的最小值)。

\n\n

通过Composer安装

博客

书籍推荐