PHPUnit:单个测试中的多个断言,只见第一次失败

时间:2011-04-13 15:22:46

标签: php phpunit

我在PHPUnit中看到的下一个奇怪之处:<​​/ p>

class DummyTest extends PHPUnit_Framework_TestCase {
    public function testDummy() {
        $this->assertTrue(false, 'assert1');
        $this->assertTrue(false, 'assert2');
    }

    public function testDummy2() {
        $this->assertTrue(false, 'assert3');
    }
}

一旦第一个断言在测试中失败,测试的其余部分就会被忽略。

所以(通过简单调用 phpunit DummyTest.php ):

  • 上面的代码将显示2个测试, 2 断言, 2 失败。什么?

  • 如果我通过所有测试,那么 我会好的(2次测试,3次断言)。 好。

  • 如果我只通过所有测试 除了assert2,我得到2次测试,3 断言,1失败。好。

我不明白,但是PHPUnit已经存在了很长时间,当然它必须是我吗?

不仅计数不是我所期望的,还会显示上面代码中第一个失败断言的错误消息。

(顺便说一句,我正在分析PHPUnit为CI生成的xml格式而不是测试实际代码,因此在一次测试中实现了多个断言。)

2 个答案:

答案 0 :(得分:31)

首先:这是预期的行为。

一旦断言失败,每个测试方法都将停止执行

例如相反会非常恼人*

class DummyTest extends PHPUnit_Framework_TestCase {
    public function testDummy() {
        $foo = get_me_my_foo();
        $this->assertInstanceOf("MyObject", $foo);
        $this->assertTrue($foo->doStuff());
    } 
}

如果phpunit在第一次断言后没有停止,你会得到一个E_FATAL(调用非成员函数),整个PHP进程就会死掉。

因此,为了制定好的断言和小测试,这种方式更实用。

另一个例子:

当“断言数组的大小为X,然后声明它包含 a,b和c ”时,你不关心它不包含那些值的事实大小为0。

如果测试失败,您通常只需要“为什么失败”这一消息,然后在修复它时,您将自动确保其他断言也通过。


另外还有一些人认为你应该只有One Asssertion per Test case,而我不练习(而且我不确定我是否喜欢它)我想注意它;)

答案 1 :(得分:10)

欢迎进行单元测试。每个测试函数都应该测试一个元素或进程(进程是用户可能采取的一系列操作)。 (这是一个单元,以及它被称为“单元测试”的原因。)在测试函数中唯一应该有多个断言的时间是测试的一部分是否依赖于前一部分的成功。

我将它用于Selenium测试网页。所以,我可能想要断言每次导航到新页面时我都在正确的位置。例如,如果我进入网页,然后登录,然后更改我的个人资料,我会断言我在登录时到了正确的位置,因为如果登录失败,测试将不再有意义。当实际遇到一个问题时,这可以防止我收到其他错误消息。

另一方面,如果我有两个单独的进程要测试,我不会测试一个,然后继续在同一个函数中测试另一个,因为第一个进程中的错误会掩盖第二个进程中的任何问题。相反,我会为每个进程编写一个测试函数。 (并且,如果一个进程依赖于另一个进程的成功,例如,将某些内容发布到页面,然后删除帖子,我将使用@depends注释来阻止第二个测试在第一个测试失败时运行。)

简而言之,如果你的第一个断言失败并不能使第二个失败,那么它们应该在不同的函数中。 (是的,这可能导致冗余代码。当进行单元测试时,忘记了所有关于消除冗余代码的知识。那么,或者使用非测试函数并从测试函数中调用它们。这会使单元测试更难读,因此,当对测试主题进行更改时,更难以更新。)

我意识到这个问题已经过了2年,但唯一的答案并不是很明确。我希望这有助于其他人更好地理解单元测试。