简体   繁体   English

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

[英]PHPUnit: Multiple assertions in a single test, only first failure seen

The next weirdness I'm seeing with 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');
    }
}

As soon as the first assertion fails in a test, the rest of the test is ignored. 一旦第一个断言在测试中失败,则忽略测试的其余部分。

So (with a simple call of phpunit DummyTest.php ): 所以(通过简单调用phpunit DummyTest.php ):

  • The above code will display 2 tests, 2 assertions, 2 failures. 上面的代码将显示2个测试, 2个断言, 2个失败。 What? 什么?

  • If I make all the tests pass, then I'll get OK (2 tests, 3 assertions). 如果我通过所有测试,那么我会好的(2个测试,3个断言)。 Good. 好。

  • If I only make all the tests pass except for assert2, I get 2 tests, 3 assertions, 1 failure. 如果我只通过除assert2之外的所有测试,我得到2个测试,3个断言,1个失败。 Good. 好。

I don't get it, but PHPUnit's been around for ages, surely it has to be me? 我不明白,但是PHPUnit已经存在了很长时间,当然它必须是我吗?

Not only are the counts not what I'd expect, only the error message for the first failed assert in the code above is displayed. 计数不仅不是我期望的,而且只显示上面代码中第一个失败断言的错误消息。

(BTW, I'm analyzing the xml format generated by PHPUnit for CI rather than testing real code, hence the practice of multiple assertions in the one test.) (顺便说一句,我正在分析PHPUnit为CI生成的xml格式,而不是测试实际代码,因此在一次测试中实现了多个断言。)

First off: That is expected behavior. 首先:这是预期的行为。

Every test method will stop executing once an assertion fails. 一旦断言失败,每个测试方法都将停止执行

For an example where the opposite will be very annoying* : 举个例子, 反之则非常讨厌*

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

if phpunit wouldn't stop after the first assertion you'd get an E_FATAL (call to a non member function) and the whole PHP process would die. 如果phpunit在第一次断言后不会停止,你将得到一个E_FATAL(调用非成员函数),整个PHP进程就会死掉。

So to formulate nice assertions and small tests it's more practical that way. 因此,为了制定好的断言和小测试,这种方式更实用。

For another example: 再举一个例子:

When "asserting that an array has a size of X, then asserting that it contains a,b and c " you don't care about the fact that it doesn't contain those values if the size is 0. 当“断言数组的大小为X,然后断言它包含a,b和c ”时,如果大小为0,则不关心它不包含这些值的事实。

If a test fails you usually just need the message "why it failed" and then, while fixing it, you'll automatically make sure the other assertions also pass. 如果测试失败,您通常只需要消息“为什么它失败”然后,在修复它时,您将自动确保其他断言也通过。


On an additional note there are also people arguing that you should only have One Asssertion per Test case while I don't practice (and I'm not sure if i like it) I wanted to note it ;) 另外还有一些人认为, One Asssertion per Test case时你应该只有One Asssertion per Test case而我不练习(而且我不确定我是否喜欢它)我想注意它;)

Welcome to unit testing. 欢迎进行单元测试。 Each test function should test one element or process (process being a series of actions that a user might take). 每个测试函数都应该测试一个元素或进程(进程是用户可能采取的一系列操作)。 (This is a unit, and why it is called "unit testing.") The only time you should have multiple assertions in a test function is if part of the test is dependent on the previous part being successful. (这是一个单元,为什么它被称为“单元测试”。)在测试函数中唯一应该有多个断言的时间是测试的一部分是否依赖于前一部分的成功。

I use this for Selenium testing web pages. 我将它用于Selenium测试网页。 So, I might want to assert that I am in the right place every time I navigate to a new page. 所以,我可能想要断言每次导航到新页面时我都在正确的位置。 For instance, if I go to a web page, then login, then change my profile, I would assert that I got to the right place when I logged in, because the test would no longer make sense if my login failed. 例如,如果我进入网页,然后登录,然后更改我的个人资料,我会断言我在登录时到了正确的位置,因为如果登录失败,测试将不再有意义。 This prevents me from getting additional error messages, when only one problem was actually encountered. 当实际遇到一个问题时,这可以防止我收到其他错误消息。

On the other side, if I have two separate processes to test, I would not test one, then continue on to test the other in the same function, because an error in the first process would mask any problems in the second. 另一方面,如果我有两个单独的进程要测试,我不会测试一个,然后继续在同一个函数中测试另一个,因为第一个进程中的错误会掩盖第二个进程中的任何问题。 Instead, I would write one test function for each process. 相反,我会为每个进程编写一个测试函数。 (And, if one process depended on the success of the other, for instance, post something to a page, then remove the post, I would use the @depends annotation to prevent the second test from running if the first fails.) (并且,如果一个进程依赖于另一个进程的成功,例如,将某些内容发布到页面,然后删除帖子,我会使用@depends注释来阻止第二个测试在第一个测试失败时运行。)

In short, if your first assert failing does not make the second one impossible to test, then they should be in separate functions. 简而言之,如果你的第一个断言失败并不能使第二个失败,那么它们应该在不同的函数中。 (Yes, this might result in redundant code. When unit testing, forget all that you have learned about eliminating redundant code. That, or make non-test functions and call them from the test functions. This can make unit tests harder to read, and thus harder to update when changes are made to the subject of the tests though.) (是的,这可能导致冗余代码。当进行单元测试时,忘记了所有关于消除冗余代码的知识。那么,或者使用非测试函数并从测试函数中调用它们。这会使单元测试更难读,因此,当对测试主题进行更改时,更难以更新。)

I realize that this question is 2 years old, however the only answer was not very clear about why. 我意识到这个问题已经有2年了,但是唯一的答案并不是很明确。 I hope that this helps others understand unit testing better. 我希望这有助于其他人更好地理解单元测试。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM