你能在 phpunit 中测试参数的边界吗?

Can you test the bounds of a parameter in phpunit?

假设我有以下方法:

public function setDeliveryDay(int $deliveryDay)
{
    $this->deliveryDay = $deliveryDay;
}

我想写一个测试来确保这个 setter 只允许 ISO-8601 值(所以 17),我该如何实现?

似乎唯一真正的方法是分别测试低于或高于 1 和 7 的每个可能的整数?

当然这是不明智的,尤其是当您希望它抛出异常时。

起初我测试了下界:

$this->expectException(\InvalidArgumentException::class);
$obj->setDeliveryDay(0);

在另一个测试中上限(因为expectException每次测试只支持一个异常):

$this->expectException(\InvalidArgumentException::class);
$obj->setDeliveryDay(8);

当然这不会阻止有人将其设置为 -1 或 -842 或 9 或 3835 等等。

是否有我在这里缺少的断言类型或公认的测试边界的最佳实践?

除非你转向 "quickcheck" 之类的测试,否则你无能为力。 QuickCheck 是一种最初来自 haskell 世界的测试方法,但似乎也有 php library。它们都是关于 "property based testing":

Generative testing, also called property-based testing, is about describing the behaviour of your system in terms of properties that should hold true for all possible input.

换句话说:这种框架的思想是确保有效的输入通过; 任何错误输入失败。

如果你不想走那条路......我会这样做:

  • 编写一个测试用例来测试循环中的几个有效值
  • 边界写另外两个测试用例
  • 编写另一个循环并尝试一堆无效值的测试用例(例如基于随机数)

最后一句话:当你选择 "random" 值时,确保在某处使用 种子 并记录它 - 以确保你可以稍后重现失败的测试上。

我要做的是为工作日创建一个简单的 ValueObject,它不公开数字并使用静态工厂方法来设置值。这样你就可以相当安全地通过该对象的类型提示传递正确的值。

在通过 int 测试您的代码时,我不会担心捕获所有不可能的值。你只测试预期的误用,所以我只会测试 0 但如果你想表示上限,你也可以测试 8 。如果不容易辨别哪些数字可能是有效的,哪些不是,您仍然应该将测试用例限制为最合理的测试用例,然后只测试更多的用例,例如对于3835,当你因为这个数字遇到bug时,为了保险起见,它不会再出现了。

如果您想捕获这些情况,您可能需要研究突变测试。或者,您可以传入随机测试值,例如rand(8, PHP_INT_MAX),但我不推荐这样做,因为它会导致不稳定的测试,并且更难跟踪使用了哪些值以及原因。