Skip to Content

For me Test driven programming in XSLT is a challenge. I tried to follow Thomas’ hint in the discussion of my first TDD-blog and create test cases first but when writing XSLT programs I got into trouble:

  • How do I write test cases for XSLT? Should I store them into the database or insert them into an existing transformation?
  • How do I perform regression tests?

There are good and news: I found solutions for those problems and I think we can code XSLT by creating test cases first. So enrich our XSLT programs by test code as well as test data. And this is how it works.

Finding the right Modularization

An XSLT program consists of templates and in case of XSLT 2.0 functions. So I suggest to code each named templates and functions within an own XSLT program. Those XSLT programs are imported into the transformation that uses the functions and named templates with the command xsl:include.

Here is an example: I want to create a named template add. Therefore I create an own XSLT program – containing the testcase (and testdata). Afterwards I will code that template add.

<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:test="http:ttrapp.gmxhome.de/test/xslt">
  <test:main/>
  <xsl:template match="test:main">
    <xsl:variable name="result">
      <xsl:call-template name="add">
        <xsl:with-param name="a" select="1"/>
        <xsl:with-param name="b" select="1"/>
      </xsl:call-template>
    </xsl:variable>
    <xsl:choose>
      <xsl:when test="number($result) and $result = 2"/>
      <xsl:otherwise>
        <xsl:value-of select="concat('Fehler: 1 + 1 = ', $result)"/>                       
      </xsl:otherwise>
    </xsl:choose>    
  </xsl:template> 
</xsl:transform>

Now I apply run this transformation with itself as an input. The template test:main is active because there is an element   <test:main/> within this transformation.As we expected we get an error because the template with name add is not implemented yet.

So we implement it quickly. It has two parameters and the result is an addition: 

<xsl:template name="add">
  <xsl:param name="a"/>
  <xsl:param name="b"/>
  <xsl:value-of select="a+b"/>
</xsl:template>

Nor our XSLT-program is running but we get an error: “Fehler: 1 + 1 = NaN”. Ok. The correction is simple:

<xsl:template name="add">
  <xsl:param name="a"/>
  <xsl:param name="b"/>
  <xsl:value-of select="$a+$b"/>
</xsl:template>

With this Unit test I described the program behaviour and can perform regression tests. I know that people work this way so above programming style is XSLT-foklore.

The problem is that it makes the transformations longer and harder to understand. And with the number of named templates they get slower but I did not make any perfomance checks. Another possibility would be creating own XSLT-programs which include the XSLT-programs conatining templates. This would solve any performance problems, but I think keeping testcases together with templatesis better because of missing use accesses for XSLT programs and Simple Transformations.

In ABAP I can read in TADIR the XSL-Transformations. For each transformation I check whether it contains an element in the namespace http://ttrapp.gmxhome.de/test/xslt and run the transformation with itself as input. I could define that the result of a testcase in namespace like http://ttrapp.gmxhome.de/test/xslt is a set of BAL-messages in asXML and could automize this behaviour by writing an SCI-test.

In my Open Source XML-libary I implemented a a small framework you can use for test automatization in ABAP. In fact I chose a namespace urn:axl-project/test for that purpose.

To report this post you need to login first.

2 Comments

You must be Logged on to comment or reply to a post.

  1. Thomas Alexander Ritter
    Hi Tobias,

    looks like an interesting approach. I have not seen stuff like that before. However one naive question which pops up straight away: Why not using traditional unit tests? I thought an XSLT program is all about transforming data so you have an input and output. Why do not you just compare the input and the output values? Is it the need for more detailed tests which tell you exactly where things go wrong?

    cheers Thomas

    (0) 
    1. Tobias Trapp Post author
      Hi Thomas,

      Unit Testing in XSLT is not my invention – there are a lot of approaches, f.i. http://xsltunit.org/ . I followed another approach to create test code in own templates that contain input an checks.

      But to your question: It depends on the degree of modularization of your XSLT programs – especially if you develop named templates and even functions that are more complicated. In http://code.google.com/p/axl-project/ I have two examples (removing duplicate nodes and as well an implementation of the EXSLT function regex:test).

      Those (external) functions are a really good example: You won’t be able to implement and maintain a stable library like http://www.exslt.org/ without any test cases. In fact my approach is nothing more than a naming convention for test code and data.

      Here is another example for reusing named templates and functions in XSLT: In http://code.google.com/p/axl-project/ I ported Schematron to ABAP. Of course you can reuse the above mentioned regex:test in Schematron. But this requires that regex:test can be tested as a unit, otherwise I can’t guarantee the stability of my enhanced Schematron.

      So my answer is: If your XSLT program is a monolith then your whole transformation is a testable unit. If you develop modular XSLT by creating a set of (perhaps reusable) templates and functions than unit testing becomes important in my opinion.

      Cheers Tobias

      P.S.: At the moment I’m writing a small framework for testing Simple Transformations and in this case I’m doing it as you proposed. Compared to XSLT Simple Transformations are much easier and don’t allow complicated XPath expressions or even the definition of own XPath functions using sap:external – so I chose another approach.

      (0) 

Leave a Reply