phpunit: Tests without assertions does not generate coverage

Q A
PHPUnit version 6.5.6
PHP version 7.0.27
Installation Method Composer

I have a test that does not do an assertion (it tests a guard that throws an exception if it fails). This test doesn’t provide coverage for the code it runs. If I add $this->assertTrue(true); at the end of the test coverage is provided.

/**
 * @doesNotPerformAssertions
 */
public function testVerifyActivityAccessSameUserAllowed()
{
    $user = $this->userFactory->create();

    app(UserVerifier::class)->verifyActivityAccess($user, $user);
}

phpunit is run like

vendor/bin/phpunit --coverage-html cov path/to/test.php

composer_info.txt

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 20 (5 by maintainers)

Commits related to this issue

Most upvoted comments

The documentation for @doesNotPerformAssertions states that the test is no longer considered risky. Should it not then also generate coverage?

I agree that it makes sense that @doesNotPerformAssertions would lead to code coverage generation.

@sebastianbergmann If I have a validator that only consists of a throw statement within an if-statement, how should one test - and get coverage - for the positive case? For example, how should I test the positive case for this code?

function verifyPositive(int $number) {
    if ($number <= 0) {
        throw new Exception('Number is not positive');
    }
}

I have several classes which only contains methods like this, would love to see my coverage turn green.

Please reopen en reconsider ❤️

This is neither a discussion nor a support forum, sorry.

I think the reason why assertTrue(true) is usually done is to assert that the tested code does not throw an exception. See issue question here or this test for example.

Something contrary to expectException() should solve all valid use cases (correct me if I’m wrong, I tried to gather all valid examples of assertTrue(true)). I’m thinking of something like expectExceptionNotThrown().

The purpose of $this->expectNotToPerformAssertions(); (and @doesNotPerformAssertions) is to suppress the risky test warning. It is my opinion that a test that does not perform assertions should not result in code being marked as being tested (covered by a test).

IMHO it’s possible that a class is being tested without assertions, for example a factory. If I try to assert that the result of a factory is an instance of a specific class, psalm will throw an error: why are you checking that an already known class (hinted from the return type) is of that type? So, I can choose to suppress psalm, or I can choose to test something random, just for having the test go green!

@sebastianbergmann If I have a validator that only consists of a throw statement within an if-statement, how should one test - and get coverage - for the positive case? For example, how should I test the positive case for this code?

function verifyPositive(int $number) {
    if ($number <= 0) {
        throw new Exception('Number is not positive');
    }
}

For anyone wondering how to solve the problem: My general solution is to wrap code in try-catch and expect the exception to be null. I am not sure about psalm, but most strict settings of phpstan does not complain.

$exception = null;
try {
	$authorizer->allow('role', 'unknown');
	$authorizer->deny('role', 'unknown');
} catch (Throwable $exception) {
	// Handled below
}

self::assertNull($exception);