phpunit testing xml output phpunit testing xml output xml xml

phpunit testing xml output


This came up as a search result I thought it could be approved on, for anyone who comes across this issue of testing a generated xml feeder function/class.

There are many ways to test out an xml output is correct, some easier than others.

I have recently completed a similar script to that which OP was asking about at this time.

If you had the following partial xml output from a function (let's call it $person->output()):

<person>    <eyes>blue</eyes>    <hair>        <style>curly</style>    </hair></person>

The first thought would be to use the code you have to generate the xml and place that into the test case to test to be sure that the xml has not changed, something like this:

function testWholeOutput() {    $person = new person();    $person->setEyes("blue");    $person->setHairStyle("curly");    $this-assertEquals(file_get_contents("data\pregenerated_xml.xml"), $person->output());}

Test passes, everyone is happy...however, this does not allow for the expansion of the xml. An additional issue is that you are literally testing what you are outputting in the first place, this may lead to some issues further down the line.

What happens if a new feature is put in which requires the knowledge of the hair colour? The test will break and you will need to do another xml output from the script in order to confirm the xml output is still working correctly.

Additionally if the test breaks then we have no idea where it broke, just that the new string is different to the old string.

The solution:phpUnit has a function to call assertTag() (and assertNotTag()) which will go through the xml and can assert if a tag exists, what the content is and confirm it is setup correctly. Something like the following will not break if more items are added to the xml output:

function testOutputPersonHasEyes() {    $person = new person();    $person->setEyes("blue");    $person->setHairStyle("curly");    $this->assertTag(        array('tag' => 'person',        'child' => array('tag' => 'eyes')            ),             $person->output());    }

The assertTag here is checking for a 'person' tag, which has a child tag 'eyes'. Now if you swap around the xml output to something like this:

<person>    <hair>            <style>curly</style>    </hair>    <eyes>blue</eyes></person>

You will still pass the above test, since this is still valid xml, and still valid output for any scripts which are consuming this xml.

Obviously you will need to write tests to make sure the content is as expected and that the other items are correct but the structure allows less false negative tests and less work in the long run, albeit at the detriment of some more time when developing.

For additional functionality, Tobias Schlitt wrote a great article on unit testing xml generation in phpUnit, and also provides another alternative to this by creating a dom object and using it a wrapper around the testcase class and testing using the php xPath, as well as a nice explanation on pros/cons on doing so.


There are usually two approaches:

  1. Hardcode expected XMLs as string variables in your test class and use those strings to compare with actual result.
  2. Create expected XMLs as regular file system files, yet belonging to your codebase (you treat them as resources). In test you load expected file, and once again compare it with result.

Both of those options are viable, however first approach (XML as hardcoded string variable) might get bit clumsy when XMLs are large - it's probably better to move them to separate file then.


It can be done using this phpunit component, phpunit-dom-assertions, which can be installed using composer.

Then use its assertSelectEquals() instead of phpunit's assertTag() (now depreciated) to test for the contents of a tag.

So, to check for an eyes tag within a person, instead of:

$this->assertTag(    array('tag' => 'person',    'child' => array('tag' => 'eyes')        ),         $person->output());}

Do this:

    $this->assertSelectCount(        'person > eyes',         true,        $person->output()    );

And to look specifically for brown eyes, do this:

    $this->assertSelectEquals(        'person > eyes',         'brown',        true,        $person->output()    );