PHPUnit:强制显示断言的值

16

在PHPUnit测试失败时,会显示实际值和期望值。
但是当测试通过时,这些信息并不会显示。

如何强制PHPUnit始终显示期望和实际的断言结果?


1
这是一个不寻常的请求。大多数人不会想要这样做。因此,PHPUnit 不会实现类似的功能。你必须自己动手实现。 - ryeguy
1
不相关的问题,但是你为什么需要那个?“通常情况下”,在测试期间不应该产生输出,因为它们的目的是自动执行(如果一切顺利,人类不应该阅读输出)。 - Matthieu Napoli
2
有时候,输出一些实际值而不是“无”,会更好地展示它们。 “难道你看不见吗?它运行正常!”,“我什么都看不到……”。 - takeshin
那么 "echo" 和 "var_dump" 就是你的好朋友了吧?(也许你想显示 所有 断言) - Matthieu Napoli
6个回答

17

运行中

phpunit --testdox

将显示每个测试名称。 因此,作为解决方法,您可能可以将期望和实际断言结果合并到测试名称中...尽管这只是一种解决方法...


3

由于您很可能使用$this->assert...()调用断言,因此可以在测试用例中重写这些方法。下面是一个快速示例:

class YourTestCase extends PHPUnit_Framework_TestCase {
    ...
    static private $messages = array();
    ...
    static public function assertSame($var1, $var2, $message = '') {
        parent::assertSame($var1, $var2, $message);
        // assertSame() throws an exception if not true, so the following
        // won't occur unless the messages actually are the same
        $success = print_r($var1, true) . ' is the same as '
                 . print_r($var2, true);
        self::$messages = array_merge(self::$messages, array($success));
    }

    static public function tearDownAfterClass() {
        echo implode("\n", self::$messages);
    }
}

当然,tearDownAfterClass()可能不够晚,不能像断言失败那样。

是的,我也考虑过这个问题,但我还没有找到适用于所有断言的基本方法。 - takeshin
哦!我明白了。但是我还在想:如果存在的话,那是否合理呢?不同的断言具有不同的语义和不同的参数。试图将它们全部归结为一个方法,难道不会削弱(或更糟)您想要的反馈的效果吗? - pinkgothic
我想要的唯一明智选择是一个命令行开关。而且实现这个会有点麻烦。 - takeshin

3

我来到这篇文章是想找类似的东西。 我有这个测试用例:

/**
 * test routing logic (numbers method returns an array of numbers and expected outputs to test)
 * @dataProvider numbers
 */
function testRoute($input,$expected)
{
   $route = new Route($input,'',false);
   $route->route();
   $this->assertEquals($expected,$route->routingResult);
}

我的数字方法如下:

/**
 * read pairs of numbers (input <tab> expected) from tests.input separater by tab
 * return an array like this: array(array(number1,expected1), array(number2,expected2), ...)
 * provide this array to my tests by returning it
 */
function numbers()
{
    $testcases = file('tests.input');
    $tests = array();
    foreach($testcases as $test_case)
    {
        list($input,$output) = explode("\t",$test_case,2);
        $tests[] = array(trim($input),trim($output));
    }
    return $tests;
}

当你使用phpunit时,你会得到类似这样的输出结果:
 Starting test 'RouteTest::testRoute with data set #0 ('8596000000', 'rejected (dp not found)x')'.
 F
 Starting test 'RouteTest::testRoute with data set #1 ('8596000001', 'rejected (rejected by scheme)')'.
 .
 Starting test 'RouteTest::testRoute with data set #2 ('8596000003', '1599000003')'.
 .

除非测试失败,否则它不会告诉您已测试函数的实际结果,但至少您可以看到所有断言的值。


2
要么创建自己的Assertion类并使其像代理一样行事,将值输出后再委托给实际的断言类,例如:(创建自定义PHPUnit断言)
$this->assertWithLogging('assertion', $expected, $actual, $message);

或者覆盖 PHPUnit 的类(我认为这将非常棘手),或者只需执行

$this->assertSame($expected, $actual, $message);
echo "$expected is $actual";

这样做也不太好看,因为在通过CLI运行时会破坏输出。如果您恰好使用Zend Studio,则可以在“Debug Output”选项卡中查看输出。

另一种方法是使用TestListeners,但我对它们了解不够,无法提供详细信息。看起来您可以钩入测试过程。


为了实现这一点,我可能只需修改 PHPUnit_Assert,但我希望有一些命令行开关可以按需使用此功能... - takeshin
@takehin 修改核心库 总是 不明智的做法。下次更新 PHPUnit 时,所有修改都会消失。这就是为什么我建议使用扩展或自定义断言。 - Gordon
你说得对,Gordon。但那只是一个假设的想法。我并不打算重写PHPUnit或在任何地方都放置var_dumps,只是在需要查看调试信息时使用一下 :) - takeshin

0

另一件事可能是编写自己的监听器。这样,您可以提供所需的输出并将断言留给phpunit。我想这可能是最简单和最可定制的方法。


0

实际上,您可以在assert???方法中直接使用$message值,并在该字段中放置任何内容。我通常使用它来显示预期值和实际值以及断言的唯一名称(假设我在给定的测试中有多个断言)。


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