V
V
Vladimir Chernyshev2011-01-30 08:34:47
HTML
Vladimir Chernyshev, 2011-01-30 08:34:47

TDD - how to test HTML output? Regulars?!?

Inspired by "I don't write unit tests because..." are excuses . I decided to try using TDD again.
There is a certain MVC web application. Let's assume that models and controllers are covered by tests. And here is how to test views, templates, layouts, the result of which is a direct output to stdin. It is clear that the output can be intercepted through ob_*, but how to test HTML code in general (native PHP templates)?
I tried this:
On the main page there should be a link to user/new (registration). Wrote a test (PHPUnit):

function testRegisterLinkForAnonymousPresent()<br>
  {<br>
    $app = new App();<br>
    $this->expectOutputRegex("#<a.+href='/user/new'.*>.+</a>#");<br>
    $app->run();<br>
  }

I configured the output of this link on the main page - the test passed.
The next step - the registration form with the action /user and the post method should be displayed on /user/new. Wrote a test:
function testRegisterFormPresentAndValid()<br>
  {<br>
    $app = new App();<br>
    $request = new Request('/user/new');<br>
    $app->setRequest($request);<br>
    $this->expectOutputRegex("#<form.+action='/user'.+method='POST'.*></form>#");<br>
    $app->run();<br>
  }

I made a form, the test passed, but then I noticed that I typoed it in the template
<form action='/user'bmethod='POST'><br>
</form>

I started thinking about the regular expression and realized that it was wrong in principle - the attributes can be in a different order, a space is required after the form, etc. I started drawing a two-story one, then it smoothly began to flow into a three-story one. But it has not yet reached the check of fields, the order of which can also be arbitrary. Actually, here I started to google how to get out of the situation, I learned a lot about TDD, but I didn’t really find anything specifically on the subject.
Tell me, please, where to dig?
Regulars, IMHO, do not really check complex structures. So far two options:
- Check tags not entirely, but in parts: in one test / assertion, check that there is a form tag in principle, in the second, that it has an action attribute with the desired value, in the third, that there is a method with POST, in the fourth, that there is an input tag inside form. To avoid three-story expressions, you can cut out the necessary pieces in parallel with the check, and only then check only them, for example "#<form(.*)>(.*)#"
— Parse HTML and check tags/attributes/values ​​already in the tree in the object form.
PS This is not functional testing, despite the fact that the whole application seems to be checked, it just happened, I haven’t done refactoring yet to check the template separately - you need to check the work of the unit, the result of which is the HTML code for the presence of the desired combination of tags / attributes /values/text.
updated:
In the process of picking, Zenda found practically undocumented PHPUnit functions assertSelectCount(), assertSelectEquals, assertSelectRegExp(), now the test looks like this:
function testRegisterLinkForAnonymousPresent()<br>
  {<br>
    ob_start();<br>
    $app = new App();<br>
    $app->run();<br>
    $result = ob_get_contents();<br>
    ob_end_clean();<br><br>
    $this->assertSelectEquals('a[href="/user/new"]', 'Register', 1, $result);<br>
  }

Probably need to extend PHPUnit_Extensions_OutputTestCase class to get rid of ob_*

Answer the question

In order to leave comments, you need to log in

5 answer(s)
K
Konstantin Kitmanov, 2011-01-30
@k12th

DOM methods, CSS/XPath selectors. Regulars are not suitable for parsing html, this is not news for a long time.

A
Antelle, 2011-01-30
@Antelle

You can check with a validator , then such a cant would show.

G
Gibbzy, 2011-01-30
@gibbzy

you can use selenium he can do it.
When I used ZendFramework, I used the Zend_Dom_Query component,
it can also be used separately from ZF, it supports xpath and css queries, this is very convenient regarding regular expressions.
framework.zend.com/manual/en/zend.dom.query.html

G
gro, 2011-01-30
@gro

To the maximum, separate the layout from the code, preferably using some kind of template engine instead of native-php.
Then the formation of the html code based on the input data will correspond to the simplest logic, which is not particularly necessary to test.
To test the formation of these same input data.

V
VBart, 2011-01-31
@VBart

You can read the md5 sum of the entire page, or its individual parts, by comparing with the standard.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question