David Lundgren

Web Developer & Systems Administrator

PHPUnit and certainty of test cases with random data

Recently I was testing a function that generated slugs for an application. In order to make the slugs unique we would append the microtime to the slug if needed. After updating my data provider to account for using the microtime version of the slug I was receiving intermittent success for the test cases. Using microtime for generated data introduces a margin of error into the time between when the code is executed and when you compare the results.

I tried using microtime before and after the function call that generated the slugs, but I would still end up around ~0.0010 seconds behind the microtime that the slug generator was using. I could not figure out how to make these tests pass 100% of the time, within reason.

If you can’t control the generator for tests that involve random data you have 2 options:

  1. refactor to remove the randomness
  2. live with a degree of certainty

For the purposes of generating a slug with appended microtime, I determined that the degree of certainty was that the slug’s microtime at the seconds level will either be equal to or at most one second before the microtime of the test cases microtime call. If it is greater than 1 second difference then there is definitely a problem. The 1 second threshold could most likely be reduced (for example to 0.0010 seconds) if desired, but I needed to get the test written in a timely manner and a 1 second degree of certainty was acceptable at the moment.

Zend Framework 1.11 + PHPUnit 3.6 unit testing

At work we are up to date with PHPUnit  at 3.6, yet officially ZF1 will only support PHPUnit 3.4. Looking through the code there is some support for PHPUnit 3.5, but I actually make use of the additional assertions that PHPUnit 3.6 provides. Initially I had intended on just extending the Zend_Test PHPUnit classes but I quickly ran into the problem where the ZF classes didn’t implement methods in the interfaces when they were brought into the PHP interpreter. I then thought about copying over the Zend_Test classes and renaming them, this would have created a maintenance issue since we don’t want to maintain our own fork of the Zend_Test classes.

My final solution was simply to create my own DatabaseTestCase. This is what I came up with:
Continue reading