inv*_*sal 4 php phpunit unit-testing
我有返回 0 到 6 之间的三个随机元素数组的函数。它确保所有元素不能具有相同的值(您可以有两个具有相同值的元素,但不能是三个)。下面是一个示例代码。
public function getRandom() {
$array = array(0, 0, 0);
do {
$array[0] = rand(0, 6);
$array[1] = rand(0, 6);
$array[2] = rand(0, 6);
} while(($array[0] == $array[1]) && ($array[0] == $array[2]));
return $array;
}
Run Code Online (Sandbox Code Playgroud)
我对单元测试有点陌生,唯一能想到的就是测试这个
我想知道是否有任何方法或我的哪种方法更适合这种情况。
正如您猜对的那样,您无法真正可靠地测试随机性。
控制随机性的问题显示了您架构的弱点:您有一个要测试的类和方法,但在测试过程中无法控制正在调用的函数 ( rand())。
起初听起来可能很奇怪,但是如果你想用“受控”随机性进行测试,你需要以某种方式模拟随机函数,所以你需要一个围绕该 PHP 函数的包装器,它允许在测试期间拦截调用并返回定义的测试值时间。
想一想:如果您有一个具有随机性方法的类,并且该类的一个实例被注入到您的测试类中以提供随机值,您可以在测试期间模拟该对象并定义返回值. 任务完成。:)
现在,实例化具有单个方法的单个对象听起来很奇怪,该方法rand()将所有调用传递给同名的 PHP 函数。更奇怪的是需要在运行时将该对象传递给测试类以使其工作。但是您不必具有该运行时依赖项。您还可以重构您的测试类,以查看是否注入了随机性提供程序并使用它,如果没有,则rand()直接使用。
如果你想减少你的类的返工,有一个技巧来覆盖内置的 PHP 函数:如果你的类在一个命名空间内并调用一个本地 PHP 函数,那么该函数将首先在该命名空间内搜索。如果您rand()在与测试类相同的命名空间中声明一个在测试文件中命名的函数,该类将调用命名空间函数而不是 PHP 函数。然后,您只需要考虑如何预定义该模拟函数的返回值,但您可能可以使用全局变量或测试用例类的静态属性,该属性填充了预定义的“随机性”:
namespace MyNameSpace;
function rand() {
return array_shift(RandomTest::$randomValues);
}
class RandomTest extends PHPUnit_Framework_TestCase {
public static $randomValues = array();
public function testSomeRandomness() {
self::$randomValues = array(0,0,0,0,1,2);
// ... test
}
}
Run Code Online (Sandbox Code Playgroud)
如果我有那个工作,我会选择真正的 PHPUnit 模拟对象,一个将它注入到类中的 setter,并将其编码为默认调用rand().