Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked

Testing Template, or should I write a diff for TT templates?

by EvdB (Deacon)
on Nov 14, 2003 at 17:46 UTC ( #307122=perlquestion: print w/replies, xml ) Need Help??

EvdB has asked for the wisdom of the Perl Monks concerning the following question:

This could possibly go into SoPW, but it is more of a musing so here goes:

The problem I wish to address is content generated by Template from templates. I can envisage a situation where the perl code and the underlying templates are created and tested. Then in the future a web designer comes alnog and makes changes to the templates. Then the designer wants to check that they have not changed the functionality of the template in any way, which is a good thing. However they do not know Template beyond the very basics and know nothing of perl.

For example, how could a designer check that their modifications to the following are OK:

*** insert the introduction here *** [% FOREACH item = items %] id: [% %] name: [% %] quantity: [% item.quantity %] unit_price: [% item.unit_price FILTER format ( '%.2f' ) %] total_price: [% item.quantity * item.unit_price FILTER format ( '%.2f' + ) %] [% END %] ** insert thank you here ***
The template above could be easily processed and then tested against expected data (regression testing) to ensure that it works.

My proposed solution to this is that there should be two sets of templates: one is used to generate the content in production, the other is used to test that the production templates behave as expected. These two sets of templates would be identical in terms of their functionality.

During testing the two sets of templates are compared to see if they are functionally the same - hence the diff for templates. However it is not straight forward to write a script which strips out everything but the Template commands.

I have the following thoughts / questions:

  • Is this the right way to go about it. There will still need to be testing of the finished scripts to check that forms etc work but this catches errors earlier.
  • Are there any tools that do this - ie compare two templates to see if they are the same?
  • TIMTOWTDI: is there another (better) way?

I hope that this little musing of mine increases the ways to test, which for Templates currently appears to be quite few.

--tidiness is the memory loss of environmental mnemonics

Replies are listed 'Best First'.
Re: Testing Template, or should I write a diff for TT templates?
by hardburn (Abbot) on Nov 14, 2003 at 17:56 UTC

    I was actually thinking about this problem this morning (though with regard to HTML::Template, though it should be possible to generalize it to any template system).

    The problem with keeping two sets of templates (production and debugging) is that a change in the variables sent means you have to update both templates. Ick.

    Instead, the template module should take a 'debug' option. When activated, the template system will still open the template files and parse them (thus allowing things like HTML::Template's strict mode to work). However, instead of outputing the filled-in template, the system outputs a plaintext version containing the data structure that would otherwise be used to fill-in the template, and is thus easy to parse. Simply dumping with Data::Dumper would be OK (though that would make it harder to parse with anything except Perl). YAML would be a better choice.

    I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
    -- Schemer

    : () { :|:& };:

    Note: All code is untested, unless otherwise stated

      I thought of this as a solution and it is a good one, although I see a few problems:
      • It does not address the processing of data done in the template, such as total_price: [% item.quantity * item.unit_price FILTER format ( '%.2f' ) %].
      • It does not take into account editing of the template by someone not familiar with templates.
      • If the base templates are the responsibility of coder and the production ones the responsibility of the designer it will quickly point out where the problem is when there is one.
      • It creates an added complication in the code (albeit a tiny one) of creating the debug option in the template processing.
      That said I think that this would be an excellent additional check that I will add to my code - thank you. I too am a big YAML fan.

      I don't think that keeping the two sets of templates current would be that great a problem - although it will be annoying when the designer swaps the order of directives. This test is mainly geared towards preventing the designer from breaking the template, rather than proving the template.

      --tidiness is the memory loss of environmental mnemonics

        Having two sets of templates is a bad idea from a testing standpoint. Testing is used to determine that the system behaves as you expect. It is more important that the production templates produce the right output. The test templates are something else that need to be maintained and they don't test that the production templates haven't been broken.

        There are two things that should be tested with templates. First, is that the program is passing the right data to the template. This is an interface question. This could be tested by writing a test template that just exercises the data. A better option is to have the tests directly examine the data.

        The second thing is that the templates produce the right output. Checking the output of the test template doesn't detect that the designer broke the production templates. A better test is to use pass test data to the production template. YAML would work very well for storing the test data. And then compare the output to a sample.

        Another possibility is to parse the production templates to produce the test templates. For example, removing all the HTML just leaves the directives. This could be compared to a sample whihc are basically the test templates you are talking about. This catches if the designer is not allowed to change the directives. If you are more concerned that the template directives work, then these could be run against the test data and the results compared to a sample.

        It does not address the processing of data done in the template, such as total_price: [% item.quantity * item.unit_price FILTER format ( '%.2f' ) %].

        Since the template system is still reading the template file anyway, it could process such directives at that point and save the values for output later. That is, if your template system even allows programatically-generated fields in the template (HTML::Template doesn't in its main implementation).

        It does not take into account editing of the template by someone not familiar with templates.

        Shouldn't matter. By the time non-coders see the data, debug mode should have already been shut off.

        I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
        -- Schemer

        : () { :|:& };:

        Note: All code is untested, unless otherwise stated

•Re: Testing Template, or should I write a diff for TT templates?
by merlyn (Sage) on Nov 14, 2003 at 18:11 UTC
    The fact that it uses a templating engine is merely a distraction. What you actually have is a system that outputs certain text.

    Consider it a black box. For some given set of inputs, it should produce an acceptable output text.

    What defines that acceptability? That's what you test. If you use a regex-based engine or a literal match, that's up to you. If someone checks in a template that fails that test, then you either fix the template or fix the test.

    For example, you could have as one of your acceptance standards that it forms valid XML. So part of your test, you parse the XML. If it fails, that's not acceptable.

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.

      Do you mean something like this:
      Template: blah blah [% %] blah, blah. Test data: $$vars{user}{name} = "<<<<<< >>>>>>" Template produces: blah blah <<<<<< >>>>>> blah, blah. Testing code: ok( $output =~ m/<<<<<< >>>>>>/ );
      However this method could easily lead to very involved tests for complicated pages - and testing the test code could become trickier than testing the template.

      Also if I have understood you correctly it will make it difficult to test real world data. As I see it the only really good way to test the templates is to create simplified ones and then to check the output against known good results - even if that is more labour intensive.

      --tidiness is the memory loss of environmental mnemonics

Re: Testing Template, or should I write a diff for TT templates?
by PodMaster (Abbot) on Nov 14, 2003 at 19:11 UTC
    Basically, testing your templates and your application shoud be two separate things. You should use your app-testing-templates (core-templates) to test your actual templates, ie designer-processed-templates (production-templates).
    • First do a syntaxt check (making sure there are no template language errors).
    • Then check all the required template elements are present, that is, if the a core-template looks like
      [% IF FOO %] blah blah [% FOO | html %] [% END %] blah blah blah
      then the production-template must also contain an "IF FOO" block inside which the variable "FOO" is filled in, and filtered through "html".
    So, I envision somebody writing Template::Test::Structure ( which comes with the commandline frontend tstest ), which would make sure template-new is structurally equivalent to template-original, warning the user of any differences, as in
    tstest new original new:34: variable FOO doesn't use FILTER `html' like original:44: in b +lock "IF FOO" new: missing variable BAR like original:66
    This is all the template designer should be interested in (a structurally valid template), unless, like merlyn said, they also need to make sure the template is valid xml, which they can go ahead and test by running the application test suite or whatever...

    See also Unit Testing Generated HTML

    MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
    I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
    ** The third rule of perl club is a statement of fact: pod is sexy.

Re: Testing Template, or should I write a diff for TT templates?
by jeffa (Bishop) on Nov 14, 2003 at 20:27 UTC

    Sounds like a Big Can of Worms™ to me. I would simply enforce that all changes be committed to a CVS system so that in case a designer breaks the interface you can roll back. Also, you have two webservers ... one in-house development server and a live production server. All changes are made to the devel server and nothing is rolled out until it has been tested and is correct.

    Also, i think that writing test cases of expected HTML output is a waste of time as well.* Hell, is it even practical? I mean, i envision a case where a designer needs to reposition the data. Are you going to require that (s)he get a back-end coder to change the test suite just so the template will check out? Better to test that data is correct and let the designer put it where ever they need. And if they screw up, you simply back out an older revision from CVS.

    CVS and a seperate development server are what we use here at work. Sure, a test suite that ensures modifications won't break would be nice, but the time it takes to develop and keep it up to date surely is not worth the time you will have to invest.


    * unless i'm writing tests for DBIx::XHTML_Table ...
    (the triplet paradiddle with high-hat)

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://307122]
Approved by Courage
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (2)
As of 2023-01-28 00:08 GMT
Find Nodes?
    Voting Booth?

    No recent polls found