Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

php

phpunit

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

  • The above code will display 2 tests, 2 assertions, 2 failures. What?

  • If I make all the tests pass, then I'll get OK (2 tests, 3 assertions). Good.

  • If I only make all the tests pass except for assert2, I get 2 tests, 3 assertions, 1 failure. Good.

I don't get it, but PHPUnit's been around for ages, surely it has to be me?

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.)

like image 342
jontyc Avatar asked Apr 13 '11 15:04

jontyc


People also ask

Can a test case have multiple assertions?

you can have multiple asserts on the same object. they will usually be the same concept being tested.

Can you have multiple assertion in a Junit test?

For tests containing only a single Assertion, as is often the case, this is not an issue. But for tests that include multiple Assertions, you are limited in that your test will not run any Assertions after the first Assertion failure. The problem becomes more pronounced the more Assertions your test contains.

What will happen if a test has more than one assert?

Using multiple assertions in a single test means that your test is more complicated and will be harder to get right. The wrong way of using the multiple asserts in your test function: arrange the system under test. act, call the method you want to check.

Why is it recommended to have only one assert statement per test?

“One assertion per test” is a wise rule to keep in mind, because it helps you have tests that fail for a specific reason, and drives you to focus on a specific behavior at a time.


1 Answers

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.

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.

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 ;)

like image 118
edorian Avatar answered Oct 13 '22 23:10

edorian