Discussions

XML & Web services: How to test XSLT transformations?

  1. How to test XSLT transformations? (3 messages)

    I have played around with XSLT and used it in the early days (1999-2000) for a documentation product. I think it is very powerful but I have a problem with making good tests for it. It is simply a bit too hard to put nice unit tests around an XSLT transformation. This is especially scary when doing on-the-fly transformations. So my conclusion is to not use it for complex stuff. I would be interested in hearing differing opinions. If you use it for complex stuff - how do you make sure that it works? Is there possibly an XsltUnit framework somewhere?
  2. Interesting problem. I'm not aware of any XSLT specific testing tools. However, if the result of your XSLT is some form of XML that is defined in a Schema, you could use JAXB to create Java objects based on the resulting XML. These objects can be tested with JUnit like any object.
  3. That would work as long as the XML output validates against the schema. I will try that next time I encounter XSLT. Maybe there is a tool that makes sure that a certain transformation will only result in validated XML as long as the input also validates?

    One side issue is links. When links are generated based on some content it would be nice to make sure that there is something at the other end of the link. That would also be possible with the JAXB approach.

    Anyway - if the result is some form of HTML it will be harder to unit test.
  4. One useful trick for writing "testable" XSLT test individual templates by passing an XML fragment to the stylesheet.

    For example, consider the following template inside a stylesheet:

    <xsl:template match="foo">...</xsl:template>

    You can test just this template with this XML fragment:

    <foo>...data...</foo>

    In order for this to work, you need to be careful how you write your XSL. In particular, you should avoid having a template that matches the root node:

    <!-- This is bad -->
    <xsl:template match="/">...</xsl:template>

    The root-node-matching template forces your transform to follow a particular path, making it harder to test. Instead, your "starting point" for you XSL should match the root element:

    <!-- This is good -->
    <xsl:template match="root">...</xsl:template>

    This way, you transform will function correctly when passed it the full XML:

    <root>
      <foo>...data...</foo>
      <foo>...data...</foo>
    </root>

    It will also work correctly when you pass it just a fragment.

    If for some reason you must match against the root node (or are using a legacy XSL), you can write a "tester" XSL that imports your "testee" XSL and overrides the operations in the root-node-matching template:

    <!-- In tester.xsl -->
    <xsl:transform ...>
      <xsl:import href="testee.xsl" />

      <!-- Override and skip straight to the "foo" template -->
      <xsl:template match="/">
        <xsl:apply-templates select="//foo">
      </xsl:template>
    </xsl:transform>

    Finally, you can test the validity of your output by XML validation, as the other poster suggested. This is even easier of you use a validation technology like RNG or W3C XML Schema which allows you to validate against an arbitrary schema instead of the schema specified in your XML. Or, you can get your "tester.xsl" to add a dummy DTD declaration to your output XML ...

    Also, if you write your schemas carefully, you may be able to reuse the same schema to validate all of your output fragments and your complete output XML.

    One final idea (and I admit this one is grandious): if you input XML is specified by a schema, you ought to be able to parse the schema and automatically generate XML fragments with various boundary conditions as inputs for your tests. You should probably have to code the output tests by hand, though.