如何测试过程化 PHP?

28

有没有测试过程式代码的方法?我一直在研究PHPUnit,它似乎是创建自动化测试的好方法。然而,它似乎更适用于面向对象的代码,是否有任何适用于过程式代码的替代方案?

或者我应该在尝试测试网站之前将其转换为面向对象?这可能需要一些时间,这是一个问题,因为我没有太多时间浪费。


1
相关链接:https://dev59.com/XXNA5IYBdhLWcg3wmfEa - Sean Walsh
2
PHPUnit本身使用面向对象的接口,以便与其他xUnit实现保持一致,并简化自身的实现。但这并不意味着它不能用于测试过程式代码。(然而可能不是唯一/最佳选择。) - mario
是的,Mario,我见过像SimpleTest这样的其他工具,但PHPUnit似乎是最常用的,而且我有一些JUnit的经验,所以学习曲线应该相对较小! - Daniel West
1个回答

37
你可以使用PHPUnit测试过程式代码。单元测试不仅适用于面向对象编程,它们测试代码单元。在面向对象编程中,一个代码单元指的是一个方法。在过程式PHP中,我猜它是整个脚本(文件)。
虽然面向对象编程更易于维护和测试,但这并不意味着不能对过程式PHP进行测试。
例如,你有这个脚本:
simple_add.php
$arg1 = $_GET['arg1'];
$arg2 = $_GET['arg2'];
$return = (int)$arg1 + (int)$arg2;
echo $return;
您可以这样测试它:
class testSimple_add extends PHPUnit_Framework_TestCase {

    private function _execute(array $params = array()) {
        $_GET = $params;
        ob_start();
        include 'simple_add.php';
        return ob_get_clean();
    }

    public function testSomething() {
        $args = array('arg1'=>30, 'arg2'=>12);
        $this->assertEquals(42, $this->_execute($args)); // passes

        $args = array('arg1'=>-30, 'arg2'=>40);
        $this->assertEquals(10, $this->_execute($args)); // passes

        $args = array('arg1'=>-30);
        $this->assertEquals(10, $this->_execute($args)); // fails
    }

}

在这个例子中,我声明了一个_execute方法,它接受一个GET参数的数组,捕获输出并返回它,而不是一遍又一遍地包含和捕获。然后,我使用PHPUnit的常规断言方法来比较输出。

当然,第三个断言会失败(取决于错误报告),因为被测试的脚本会给出一个未定义索引的错误。

当然,在测试时,你应该将错误报告设置为E_ALL | E_STRICT


感谢您详细的回复!它对我帮助很大。实际上,我有处理所有业务逻辑的函数,所以我猜想我可以将这些函数包含在PHP文件中,并以类似的方式进行测试? - Daniel West
2
@Daniel:是的,实际上,测试函数很像测试对象方法。你输入一些内容然后验证输出是否符合你预期的结果。 - netcoder
因为这个回答中提到的观点:“面向对象的代码更容易维护和测试”,所以被踩了。那绝对不是真的。 - vhs
3
这个回答并不能真正帮助单元测试过程式代码。请建议我们如何处理函数之间的依赖关系?一个函数可能会在其内部调用多个其他函数。那么我该如何将一个函数与其依赖项隔离开来进行测试?如果代码是面向对象的,我可以使用模拟/存根对象等来模拟各种依赖项的行为,以生成多个可能的测试用例。 - rineez
我们应该如何管理脚本URI和因此包含语句?肯定不是将它们硬编码到测试方法中,这样做并不正确吧? - tscherg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接