3 mars 2011

PHPUnit - detect failing, skipped and incomplete tests

Sometimes when extending PHPUnit it might be useful to test assertions that are supposed to fail or mark the test as incomplete or skipped. However one wouldn't want the whole test case to fail when testing such assertions. Here is a simple way to achieve this.

Please be warned that this technique should be used carefully in order not to "mask" real failing tests.

To illustrate the method let's write a simple test case extension.

class CustomTestCase extends \PHPUnit_Framework_TestCase {

  // Failing assertion
  public function assertMeantToFail() {
    $this->assertTrue(false);
  }

  // Test incomplete assertion
  public function assertMeantToBeIncomplete() {
    $this->markTestSkipped();
  }

  // Test skipped assertion
  public function assertMeantToBeSkipped() {
    $this->markTestIncomplete();
  }

}

Now we would like to write a test case to check if the above assertions actually do what they are expected to do.

The point is that PHPUnit will use Exceptions to notify the test runner of a failing, skipped or incomplete test. Thus it is possible to intercept the correct Exception to check if the test does what we expect.

class CustomTestCaseTestCase extends CustomTestCase {

  public function testFailingTest() {
    try {
      $this->assertMeantToFail();
    } catch (\PHPUnit_Framework_ExpectationFailedException $ex) {
      // As expected the assertion failed, silently return
      return;
    }
    // The assertion did not fail, make the test fail
    $this->fail('This test did not fail as expected');
  }

  public function testSkippedTest() {
    try {
      $this->assertMeantToBeSkipped();
    } catch (\PHPUnit_Framework_SkippedTestError $ex) {
      // As expected the assertion was skipped, silently return
      return;
    }
    // The assertion did not mark the test skipped, make the test fail
    $this->fail('This test was not skipped as expected');
  }

  public function testIncompleteTest() {
    try {
      $this->assertMeantToBeIncomplete();
    } catch (\PHPUnit_Framework_IncompleteTestError $ex) {
      // As expected the assertion was marked as incomplete, silently return
      return;
    }
    // The assertion did not mark the test incomplete, make the test fail
    $this->fail('This test was not incomplete as expected');
  }

}

The above code is meant to work with PHP 5.3 and namespaces. To make it work on other PHP versions remove the \ at start of the class names.

I should not tell you, but...


Alternately you can use the @expectedException annotation to make a failing test succeed. Although this seems to be a very bad practice, because it can hide problems in your code, I present it here for sake of completeness.

/**
     * This test will succeed !!!
     * @expectedException PHPUnit_Framework_ExpectationFailedException
     */
    public function testSucceed()
    {
        $this->assertTrue(false);
    }

This last method does not work for incomplete or skipped tests.

Aucun commentaire:

Enregistrer un commentaire