
“To test or not to test” is a question that, by this time, should have been completely deprecated of a programer’s mind. Yes, I know, we all have programmed good pieces of software when the whole unit test concept wasn’t mainstream, but if you ever took the time to write a couple of good tests you know that they are a really good weapon against unexpected bugs.
So, some time ago we wanted to write some tests a for a couple of elgg plugins we were developing and were quite surprised to see that the tests had to run in the same database the site. Of course you don’t have to run them in the production site, but there were at least two important disadvantages in this approach:
- Broken tests would yield the installation unusable. In particular tests that would fail unexpectedly and halt a program execution (e.g. a PHP fatal error) would mean reloading the backup database.
- You have to be quite careful in the clean-up process to not leave garbage in the DB.
- As a result of tests failing or wrong clean-up processes it was hard to be sure about the initial state of the tests and how to load the fixtures, which sometimes are quite complex.
- Tests weren’t really independent, since they not only share the DB but also the application global state.
During this time we established a set of properties that we would like an elgg test framework to have:
- The tests should never touch the underlying DB.
- Each test should run in a separate process, invoking elgg engine/start before its setup. This would ensure a clean and independent startup for each test and avoid global-state sharing among tests.
- Each test should be able to define its own fixtures.
As a result QBElggTestsForPHPUnit was born. As its name suggest, this plugin is an extension of PHPUnit adapted to fit the previously stated characteristics. In a nutshell this plugin provides:
- DB independence. Whether we are talking about production, staging or development DB, the tests never hit the installation DB.
- Test independence. Tests are run with the –process-isolation modifier, which means that each test spawn its own process.
- Each test case can define its own fixtures, which are loaded before each test. Thus the developer doesn’t have to worry about clean up processes.
So, how does it work? Basically we define a test DB as part of the plugin configuration, which will be used instead of the real DB. When the test suit starts it reloads the DB structure, so that we can cope with a previous execution breaking the DB, even messing up the schema. Once this is done the fixtures are loaded, the elgg engine is started and the first test is ran. Before running the next test, the suite will reload only the tables that were modified by the previous test. This means that if the elgg_objects table wasn’t modified by the previous test, its fixture won’t be loaded again.
And that’s pretty much it. The plugin is currently in a private beta, but we hope to be able to release it soon.
