-
Notifications
You must be signed in to change notification settings - Fork 33
Getting Started
This page demonstrates how to get started with XSpec. It runs through a tutorial that tests an XSLT stylesheet with XSpec. The examples are in the tutorial directory.
Make sure that XSpec is installed correctly by running the help message at the end of the installation process:
The tutorial directory contains an sample of XSLT stylesheet escape-for-regex.xsl to test and its sample XSpec test suite escape-for-regex.xspec.
The stylesheet file to test is specified in the @stylesheet attribute at the beginning of the XSpec file:
<x:description xmlns:x="http://www.jenitennison.com/xslt/xspec"
xmlns:functx="http://www.functx.com"
stylesheet="escape-for-regex.xsl">Navigate to your XSpec directory (e.g. ~/xspec/ for Mac/Linux or C:\xspec\ for Windows) and run the XSpec test suite with this command:
For Mac/Linux:
bin/xspec.sh tutorial/escape-for-regex.xspecFor Windows:
bin\xspec.bat tutorial\escape-for-regex.xspecNote that you invoke the XSpec script against the XSpec test file (*.xspec), not the stylesheet file (*.xsl).
The output in the shell should be similar to this:
Creating XSpec Directory at tutorial/xspec...
Creating Test Runner...
Checking for deprecated Saxon versions: Passed
Running Tests...
Testing with SAXON HE 10.9
No escaping
Must not be escaped at all
Test simple patterns
..When encountering parentheses
escape them.
..When encountering a whitespace character class
escape the backslash
result should have one more character than source
When processing a list of phrases
All phrase elements should remain
Strings should be escaped and status attributes should be added
FAILED
Formatting Report...
passed: 5 / pending: 0 / failed: 1 / total: 6
Report available at tutorial/xspec/escape-for-regex-result.html
Done.If everything worked, there should be a new xspec subdirectory in ~/xspec/tutorial (or C:\xspec\tutorial). It contains three files generated by XSpec:
-
escape-for-regex-compiled: the compiled XSpec test. -
escape-for-regex-result.xml: the test results in XML format. -
escape-for-regex-result.html: the human-readable HTML test report. Most of the time, this is the only file out of these three that you'll care about.
Open the HTML report at tutorial/xspec/escape-for-regex-result.html with your favorite web browser to see the test results. The HTML report should look like this:

As you can see, one of the tests has failed.
Open the fully commented escape-for-regex.xsl and escape-for-regex.xspec in your favorite XML editor to follow the rest of the tutorial.
The XSLT stylesheet contains a function functx:escape-for-regex and a matching template match="phrase".
The XSpec file has three top-level scenarios, which are contained in x:scenario elements. The first two test the function, and the third tests the matching templates.
The first scenario is simple, it just calls the function functx:escape-for-regex with the given parameter value and directly compares its result to our expected result. A function is invoked by using an x:call element, passing it a parameter using an x:param element. Our expectations about how the functions should behave are captured by x:expect elements:
<x:scenario label="No escaping">
<!-- call the function with the string 'Hello' -->
<x:call function="functx:escape-for-regex">
<x:param select="'Hello'"/>
</x:call>
<!-- check the result -->
<x:expect label="Must not be escaped at all" select="'Hello'"/>
</x:scenario>Scenarios can be nested and the second top-level scenario is an example as it contains two scenarios that test two aspects of the function functx:escape-for-regex. The first nested scenario is an equality test, just like the first top-level scenario. The second nested scenario is more interesting as it tests the output of a function against an XPath expression given in @test. Note that we can have as many expectations as we like within a scenario:
<x:scenario label="Test simple patterns">
<!-- call the function -->
<x:call function="functx:escape-for-regex" />
<!-- first sub-scenario -->
<x:scenario label="When encountering parentheses">
<!-- with a parameter -->
<x:call>
<x:param select="'(Hello)'"/>
</x:call>
<!-- check the result -->
<x:expect label="escape them." select="'\(Hello\)'"/>
</x:scenario>
<!-- second sub-scenario -->
<x:scenario label="When encountering a whitespace character class">
<!-- with another parameter -->
<x:call>
<x:param select="'\sHello'"/>
</x:call>
<!-- check the result -->
<x:expect label="escape the backslash" select="'\\sHello'"/>
<!-- we can have several checks on the same result -->
<x:expect label="result should have one more character than source"
test="string-length(.) = 8"/>
</x:scenario>
</x:scenario>The third top-level scenario tests the templates in the transform. An x:context element contains nodes we want to apply templates to. It has two expectations: the first a simple XPath test and the second demonstrates how we can directly compare the expected nodes to the actual result nodes by embedding the expected nodes as descendants of an x:expect element:
<x:scenario label="When processing a list of phrases">
<!-- apply template rules to this element -->
<x:context>
<phrases>
<phrase>Hello!</phrase>
<phrase>Goodbye!</phrase>
<phrase>(So long!)</phrase>
</phrases>
</x:context>
<!-- check the result -->
<x:expect label="All phrase elements should remain"
test="count(phrases/phrase) = 3"/>
<x:expect label="Strings should be escaped and status attributes should be added">
<phrases>
<phrase status="same">Hello!</phrase>
<phrase status="same">Goodbye!</phrase>
<phrase status="changed">\(So long!\)</phrase>
</phrases>
</x:expect>
</x:scenario>Although it's not shown here, both x:context and x:call elements have optional @href and @select attributes, which can be a very powerful way to define tests. @href is used to point to an external document, and @select is used to select certain nodes to test against.
One of the tests failed, so let's fix it. When a test fails in XSpec, the report shows both the actual result and the expected result side-by-side, with differences highlighted. From this report, we can see that the failed scenario is labelled "When processing a list of phrases" and the specific expectation that failed is labelled "Strings should be escaped and status attributes should be added." The difference is that the @status attributes contain the wrong values. Change the @status attribute constructor to read:
<xsl:attribute name="status" select="if (. = $escaped-text) then 'same' else 'changed'" />Save the XSLT stylesheet and re-run the XSpec test. All tests should pass:

There are many ways to integrate XSpec into your workflow. Here are a few tips:
-
Add the XSpec executable directory to your system path. For example, if XSpec is installed in
~/xspec, add this to your~/.bashrc:PATH=$PATH:~/xspec/bin
In Windows:
PATH %PATH%;C:\xspec\bin
-
By default, XSpec stores its result documents in the subdirectory
xspecof the folder where the particular XSpec file that you are testing resides. You may want to change the variableTEST_DIRto the system temporary folder:export TEST_DIR=/tmp/xspecIn Windows:
SET TEST_DIR=%TEMP%\xspec
This works well when you don't want to clutter up your project folders with XSpec results.
-
Running XSpec with Ant is far faster and more feature-rich than the shell/batch scripts.
-
XSpec is integrated in the Oxygen XML editor.
If you have any questions about XSpec or want to discuss, contribute, and share information with the XSpec community, please go to our issue tracker.
For historical searches, the Google group might also be useful.
- Writing Scenarios
- Nesting Scenarios
- Focusing Your Efforts
- Global Context Item
- Selecting Nodes
- Whitespace-only Text Nodes
- Attribute Value Templates
- Text Value Templates
- Special Names
- Code Coverage
- XML Catalog Support
- Environment Variables
- Testing Dynamic Errors
- Integrating Your Own Test Helpers
- External Transformation
- Getting Started with XSpec and Schematron
- Writing Scenarios for Schematron
- Testing Schematron with Text Nodes
- Testing Schematron with Attributes
- Using Another Implementation of Schematron