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

jon*_*tyc 17 php phpunit

我在PHPUnit中看到的下一个奇怪之处:

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

    public function testDummy2() {
        $this->assertTrue(false, 'assert3');
    }
}
Run Code Online (Sandbox Code Playgroud)

一旦第一个断言在测试中失败,则忽略测试的其余部分.

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

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

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

  • 如果我只通过除assert2之外的所有测试,我得到2个测试,3个断言,1个失败.好.

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

计数不仅不是我期望的,而且只显示上面代码中第一个失败断言的错误消息.

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

edo*_*ian 33

首先:这是预期的行为.

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

举个例子,反之则非常讨厌*:

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

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

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

再举一个例子:

当"断言数组的大小为X,然后断言它包含a,b和c "时,如果大小为0,则不关心它不包含这些值的事实.

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


还有另外一个注意事项,也有人争辩说你应该只One Asssertion per Test case在我不练习的时候(而且我不确定我是否喜欢它)我想注意它;)


小智 10

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

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

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

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

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

  • 谢谢你,即使是两年之后,这就是像我这样的人多年后得到答案的方式;-) (2认同)