(Unit) Test驱动开发

3

我对TDD和单元测试并不是很熟悉,因此有些问题。 我有这个用PHP编写的遗留函数

function foo(){
   x = bar();
   y = baz();
   if (x > y)
     return 'greater';
   return 'lesser';
}

如果 bar() 返回的值 x 总是大于 baz() 返回的值 y,那么我将永远无法测试“较小”的返回语句。为了涵盖所有测试用例并实现100%的代码覆盖率,我该怎么办?在遗留代码中,重新定义 foo() 作为 foo(x, y) 进行依赖注入钩子不是一个选项。

1
如果函数总是返回相同的结果,那么它的目的是什么? - JJJ
让我更正一下。那个函数只在圣诞节前返回一个更大的值 :) - pranay
将函数结果注入并不是依赖注入。这只是遵循面向对象编程规则的表现,即每个方法必须只做一件事情(因此完全依赖于其他方法)。恐怕唯一测试所有情况的方法是将foo()重新定义为foo(x, y)。 - Atrakeur
2个回答

1
我假设foobarbaz都是全局函数。(如果它们是类的一部分,则应使用PHPUnit的模拟功能)。
我之前在博客中介绍了如何使用pecl扩展来替换内置函数: http://darrendev.blogspot.jp/2012/07/mock-socket-in-php.html 本文展示了一个非常有趣的替代方法,使用命名空间: http://marcelog.github.io/articles/php_mock_global_functions_for_unit_tests_with_phpunit.html 看起来你需要在文件中加入顶部的命名空间声明来包装你的旧代码。我不知道这是否会成为你的障碍。

谢谢,使用命名空间来覆盖全局函数是一个不错的选择! - pranay

0

由于bar()和baz()不接受输入参数,它们要么返回一个常量(你可以立即重构foo()为{ return 'greater' }),要么依赖于一些外部变量。在这种情况下,可以这样做:

 function testFooReturnsGreater() {
     setEnvironmentSoBarIsGreaterThanBaz()
     assert ("greater".equals(foo())
 }

 function testFooReturnsLesser() {
    setEnvironmentSoBarIsLesserThanBaz()
    assert("lesser".equals(foo())
}

因为你说除非是圣诞节,否则 bar() > baz(),所以 setEnvironmentxxx() 的装置需要改变程序对当前日期的概念(希望你可以模拟而不是使用实际的系统时钟)。


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