Test the HTML with DOM parser and PHPUnit
When testing code that returns HTML in PHP, I’ve been doing lazy checks with regular expressions.
But I decided to run test with DOM, because I had been feeling uneasy.
Initially, I tried to use DOMDocument::loadHTML
for it. But I got an error when the HTML contains the <section />
like following.
DOMDocument::loadHTML(): Tag section invalid in Entity, line: 1
So, I used following libraries and it looks good to me.
symfony/dom-crawler
symfony/css-selector
Install dependencies
To install those libraries, run composer command like following.
$ composer require symfony/dom-crawler symfony/css-selector --dev
Write a method that returns a DOM
First, prepare a method that returns DOM when passing HTML.
<?php class Sample_Test extends UnitTestCase { private function dom( $html ) { $dom = new Symfony\Component\DomCrawler\Crawler(); $dom->addHTMLContent( $html, "UTF-8" ); return $dom; } }
Write a test
test_html()
is the test to check the HTML. It is checking how many nodes that matches the CSS selector.
<?php class Sample_Test extends UnitTestCase { public function test_html() { $result = do_something(); $dom = $this->dom( $result ); $this->assertSame( 1, count( $dom->filter( '.col-3' ) ) ); $this->assertSame( 6, count( $dom->filter( 'section.item' ) ) ); } private function dom( $html ) { $dom = new Symfony\Component\DomCrawler\Crawler(); $dom->addHTMLContent( $html, "UTF-8" ); return $dom; } }
do_something()
is a function that returns HTML. I passed CSS selector to `$dom->filter()` and asserted the number of the nodes.
Test whether it is valid HTML
Unfortunately, dom-clawler can’t test whether it is valid HTML.
But, I guess we can check if we forget to close tag or so like following.
private function assertMaybeValidHTML( $html ) { $html = str_replace( 'section', 'div', $html ); $html = str_replace( 'aside', 'div', $html ); $dom = new DOMDocument(); $dom->loadHTML( '<html><body>' . $html . '</body></html>' ); }