Hi, i’m writing tests to cover existing code and i can’t figure out how to deal with datetimes when testing db fixtures using phpunit.
For example, assume an Article object has a date inserted property, represented in the database as a datetime. Using a flat XML file as a seed i specified the values to test against, but when the test is run a different date is created compared with the seed even by a minute or so, or if the tests are run at a later date as part of a suite.
…where the tested method is inserting a new article entry (id 3) into the database. It would be simple to remove the datetime element from the test but a specific item that i am testing is that when a new Article element is created, it has no date created, but is assigned one when it is successfully inserted. So when the test is run, unless the date is specifically “2011-14-01 14:33” (as defined in the fixture) the test will fail.
Use variables in your dataset, e.g.
date_inserted = “NOW” or date_inserted = “TOMORROW” depending what you need for testing.
Then in your test case, use PHPUnit_Extensions_Database_DataSet_ReplacementDataSet and specify replacements for those variables, e.g. array(‘NOW’ => date(‘d.m.Y H:i:s’)) and so on.
DbUnit uses str_replace for replacements, but I changed that to preg_replace, so I can do more robust replacements (e.g. removing fractions from postgresql timestamps etc.).
Write some wrapper methods to ease the pain. For example, I replace some values in all my datasets automatically (‘NULL’ => null, ‘TRUE’ => true etc) and add additional replacements when needed.
Thanks for the quick reply. That sounds exactly like what i’m looking for, although i can see nothing in the documentation about the ReplacementDataset class. Do you have any links to some articles, or use cases? And do i apply the ReplacementDataSet to just the test fixture, or the seed also?
$xml_dataset = $this->createFlatXMLDataSet($xmlFile);
$xml_dataset_fixed = new PHPUnit_Extensions_Database_DataSet_ReplacementDataSet($xml_dataset, array('NOW' => date('d.m.Y')));
// let's assume the date is filled in by the db, because of add_date = default now()
$users_model->insert(1, 'John');
$db_dataset = $this->getConnection()->createDataSet(array('users'));
$this->assertDataSetsEqual($xml_dataset_fixed, $db_dataset);
That’s basically it. The second argument to PHPUnit_Extensions_Database_DataSet_ReplacementDataSet is full replacement table, the third is substr replacement for more fancy matching (although I changed the source code to preg_replace, so I could pass regexes)
You can do the same with any other datasets, including database ones.
The code becomes monstrous with all those classes in your test methods.
I basically extend PHPUnit_Extensions_Database_TestCase and add a few shortcut methods for replacements and filters.