Hi Folks,
I have an XSLT program that, among other things, transforms elements such as this:
<MAG_VAR>E009383</MAG_VAR>
into this:
<magneticVariation>
<magneticVariationEWT>East</magneticVariationEWT>
<magneticVariationValue>10.5</magneticVariationValue>
</magneticVariation>
The XSLT program contains a function that does the transformation:
<xsl:function name="f:magneticVariation" as="element(magneticVariation)">
<xsl:param name="MagVar" as="element(MAG_VAR)" />
...
</xsl:function>
I want to test the function to ensure it works correctly and also to ensure that if, in the future, someone modifies my XSLT code, they will be able to run some tests to see if their changes result in breaking the function. In other words, I want some unit tests and a way to automate the running of those unit tests.
So the first thing I need is a standard way of expressing unit tests. I found XSpec. It is a standard XML language for expressing unit tests. You can read all about XSpec – what it is, how to install it, how to use it to create unit tests – here:
https://github.com/xspec/xspec/wiki/What-is-XSpec
I created a test to check that the function correctly transforms E to East. Below is the XSpec document (waypoint.xspec). The test case is described via a scenario: The <x:call> element describes the input, which is a <MAG_VAR> element. The <x:expect> element describes the expected output of the XSLT function.
<x:description xmlns:x="http://www.jenitennison.com/xslt/xspec"
xmlns:f="function"
stylesheet="waypoint.xsl">
<x:scenario label="Check that that XSLT function correctly transforms E to East">
<x:call function="f:magneticVariation">
<x:param>
<MAG_VAR>E009383</MAG_VAR>
</x:param>
</x:call>
<x:expect label="Expect: magneticVariationEWT = East">
<magneticVariation>
<magneticVariationEWT>East</magneticVariationEWT>
<magneticVariationValue>10.5</magneticVariationValue>
</magneticVariation>
</x:expect>
</x:scenario>
</x:description>
I installed XSpec by following these (excellent) instructions:
https://github.com/xspec/xspec/wiki/Installation-on-Windows
Then I ran the unit test:
xspec waypoint.xspec
XSpec found an error in my XSLT function – my function incorrectly converts E to east (should be East). The output of the XSpec tool is a nice report of the error:
<image001.png>
That is fantastic.
The XSpec language is simple yet powerful. The XSpec tool is easy to use, easy to install, and generates awesome reports.
Next, I want to automate the running of my unit tests. Maven is a nice tool for this. I found that there is an XSpec plugin for Maven called the XSpec Maven Plugin. Here’s info about the plugin:
https://github.com/xspec/xspec-maven-plugin-1
To create a Maven project, I typed this at the command line:
mvn -B archetype:generate -DgroupId=org.mitre.waypoints -DartifactId=waypoints -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4
That created a waypoints folder along with several subfolders.
I put my XSpec test (waypoints.xspec) in this folder: waypoints/src/test/xspec
I put my XSLT program (waypoints.xsl) in this folder: waypoints/src/main/xsl
In the waypoints folder is pom.xml (POM = Project Object Model). I show pom.xml below. The parts in yellow are what I added, the rest was auto-generated by maven. (Thanks to Christophe Marchand for helping me with this.)
To run all unit tests, I typed this at a command prompt (in the directory that contains pom.xml):
mvn test
Here is a screenshot of the Maven test:
<image002.png>
XSpec, XSpec Plugin to Maven, and Maven combine to enable seamless, automated unit testing of XSLT programs.
Awesome!
/Roger
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.mitre.waypoints</groupId>
<artifactId>waypoints</artifactId>
<version>1.0-SNAPSHOT</version>
<name>waypoints</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>io.xspec.maven</groupId>
<artifactId>xspec-maven-plugin</artifactId>
<version>2.0.0</version>
<dependencies>
<dependency>
<groupId>net.sf.saxon</groupId>
<artifactId>Saxon-HE</artifactId>
<version>10.1</version>
</dependency>
<dependency>
<groupId>io.xspec</groupId>
<artifactId>xspec</artifactId>
<version>1.6.0</version>
</dependency>
</dependencies>
<configuration>
<generateSurefireReport>true</generateSurefireReport>
<saxonOptions></saxonOptions>
</configuration>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>run-xspec</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>io.xspec.maven</groupId>
<artifactId>xspec-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>