Why does Phpunit not consider early return in method in code Coverage?

Asked

Viewed 38 times

2

I have a code that I am testing with Phpunit being that in the tested method there is an early return with null under certain condition. However, Phpunit does not consider this part of the code to be covered by the test and I cannot find out why, nor how to include this in code coverage analysis.

The code in question is:

public function __get(string $name)
    {
        if ($this->hasObservable($name) === false) {
            //Exception
        }
        
        if(key_exists($name, $this->values) === false){
            return null;
        }
        
        return $this->values[$name];
    }

The test code is as follows::

public function testMagicGetReturnNull()
    {
        self::$observer->register('test5', 'testingCallbackFunction');
        $this->assertNull(self::$observer->test5);
    }

The report generated by Phpunit indicates that it is the line with return null; that is not covered:

PHPUnit/Code coverage

The test passes, since the returned value is null, but I don’t know why that part of the code doesn’t seem to be being covered.

The full code (from the commit to the moment of this question) is here.

  • Where you’re testing that the key doesn’t exist?

  • In class I have a property $value. In it through __set() i add the value null (with a key). No __get() it must test if a given key exists. If it does not exist it returns null.

  • But where does the forehead null?

  • On the test, on the line $this->assertNull(self::$observer->test5);.

  • But what I understand is that there is no null.

1 answer

4


Code coverage means testing all possibilities, all code paths, make all situations have been simulated. The ideal is 100%, but in practice this is difficult to obtain, and can complicate a lot. In general low percentages are easy, as it goes up complicates, when it goes from 90, 95, 98 begins to get very complicated, at least in most cases.

To give this coverage you have to make the conditional paths happen. You have to test by making it between us ifs. It is not enough to make the assessment of the condition, you have to enter to consider that covered that line.

In the case, at least in what is in the question, there is a test that makes you enter the line that is in red, the evaluation is done (the green line), but it always results in false and does not enter there, never, therefore it is out of the cover.

You need to do a test that drops there. Of course the test should indicate that there is a failure, but the code needs to be executed in the test. The test is there to indicate if what is expected in that situation happens. If the code exists you expect it to happen in some situation, even if abnormal. If it were impossible to happen the code should not exist. You test to see if the abnormal situation gives the expected result, even if it is a problem, but the action must be the right one for an abnormal situation. I don’t know, try to use the property teste6. Testing has to try everything that could actually happen at the time it is running.

And testing should not test things that are impossible to happen.

A common mistake I see people making in tests is that a well-done test can eliminate the possibility of production error. If this actually happens then you don’t need code to handle the error, which is good, makes the code faster, cleaner. But many people leave the error handling there in the code by way of doubt. Either you trust the test or do not trust.

It doesn’t mean that every test can guarantee that something will always work, but some can. I especially like tests that avoid error handling codes at runtime.

This one doesn’t look like it can be deleted, so just test that this part of the code is working properly when using it the wrong way, because that’s what it does, it treats misuse. In another language this treatment wouldn’t be necessary and the test much less, so people talk wrong about dynamic typing being more productive, it’s only if you’re prototyping, doing scripts simple or if you do not want robustness in your application.

  • Living and learning. Perfect answer. Showed the reasoning I was not doing. In case the code would return null on two occasions: if the key was not defined or if there was no value definition, since all keys have by default null. Plus, I learned one more thing: if you trust tests, you don’t need error handling. Always learning from @Maniero. Thanks for the lesson.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.