views:

70

answers:

3

I am getting my head around PHPUnit, and trying to build a test case for an existing class.

The class is a static configuration class, getting, setting and listing configuration options that will be available in the application.

The class is very strictly built. If I try to set a configuration setting with an incompatible value, or a configuration setting that does not exist, a E_USER_ERROR is thrown, halting the execution of the script. Even if it's not the fine art of error handling, it works fine for the purposes of this class. An error in that class is always the result of a programming error, and never of bad user input.

This has the great advantage that you don't have to worry about how error messages are handled or logged, which keeps the code slim. Output the message (or not, in production), die(), done.

However, with Unit tests, I don't see how I can continue to work with classic PHP errors. I will have to convert the functions to return success flags, or throw exceptions.

Am I correct?

Or is there a way in PHPUnit to expect errors, as there is to expect Exceptions? I can't see any straight away.

+1  A: 

I don't know the details of your implementation, but couldn't you raise a normal (custom) exception (which can be tested) and have a global exception handler in your app that will throw the proper E_USER_ERROR based on these (custom) exceptions?

Check set_exception_handler for more information on setting this global exception handler.

wimvds
If I understand it right, this would make the class work in a unit test, while retaining the original behaviour. Sounds good to me! +1
Pekka
As I understood it, you'd have to alter your class in order to throw exceptions.
middus
BTW Apparently PHPUnit should be able to test for errors, notices and warnings as well : http://www.phpunit.de/manual/3.2/en/writing-tests-for-phpunit.html#writing-tests-for-phpunit.errors (I'm new to PHPUnit :p).
wimvds
@Wim you are right, didn't see that. I'm going to try that out.
Pekka
+1  A: 

Couldn't you define an error handler (via set_error_handler) that will treat any error that cannot be handled by PHPUnit (such as E_USER_ERROR) as a failure of the unit test?

(Inspired by WordPress' tests)

middus
Aah interesting, this is like @Wim's suggestion but the other way round, with the advantage that I wouldn't have to touch the existing class. Very nice, I think I'll try that first!
Pekka
+4  A: 

From the PHPUnit manual:

By default, PHPUnit converts PHP errors, warnings, and notices that are triggered during the execution of a test to an exception. Using these exceptions, you can, for instance, expect a test to trigger a PHP error as shown in Example 4.8.

class ExpectedErrorTest extends PHPUnit_Framework_TestCase
{
    /**
     * @expectedException PHPUnit_Framework_Error
     */
    public function testFailingInclude()
    {
        include 'not_existing_file.php';
    }
}

Same works for exceptions of course.

Edit: didn't see this was already mentioned in the comments, but I'll leave it here for reference in case someone looks for the same question and doesn't read the comments

Gordon
Yup, @Wim had already pointed out that paragraph, I totally overread that. Brilliant, I won't have to change anything.
Pekka
+1 for not being as blind as the rest of us ;).
middus
@Pekka sorry, didn't see it. Since you seem to be asking a number of PHPUnit questions lately, here is one introduction that might be of use to you http://www.phphatesme.com/blog/qualitatssicherung/phpunit-eine-einfuhrung/ (german)
Gordon