> 1. Testing variables
> So I have some global variables that construct nodesets, which are then
> used for various tasks throughout the transformation. AFAIK, XSpec
> provides no way to test these, so am I supposed to refactor so that the
> xsl:variable declaration calls a named template, which *is* testable?
> Is this good practice, or just a workaround to be able to successfully
> add XSpec to the mix?
If you mean to verify a global variable value, you can put it in @test. For example,
<x:scenario label="When applying templates to a dummy empty context">
<x:context/>
<x:expect label="$my-global-var should be a foo element containing a bar element"
test="$my-global-var">
<foo>
<bar/>
</foo>
</x:expect>
<x:expect label="$my-global-var should have one child node"
test="$my-global-var/child::node() => count()"
select="1" />
</x:scenario>
x:context in this example is just a dummy context only for making the scenario valid. Any other elements will do as long as it makes the scenario valid. For example,
<x:scenario label="When fn:false() or whatever function is called">
<x:call function="false" />
<x:expect label="$my-global-var should be a foo element containing a bar element"
test="$my-global-var">
<foo>
<bar/>
</foo>
</x:expect>
</x:scenario>
---
If you mean to test your transformation with various global variables, you can override a global variable with a global x:variable (
https://github.com/xspec/xspec/wiki/Writing-Scenarios#xspec-variables ). So if you have a stylesheet
<xsl:stylesheet ...>
<xsl:variable name="my-global-var" as="element(e)">
<e/>
</xsl:variable>
<xsl:template ...>
...
</xsl:stylesheet>
and an XSpec
<x:description ...>
<x:variable name="my-global-var" as="element(f)">
<f/>
</x:variable>
<x:scenario ...>
...
</x:description>
then $my-global-var throughout the test scenarios is not <e/> but <f/>.
---
If your global variable depends on the source document, you may have to refactor your stylesheet because XSpec does not set the source document at all. For example, with this stylesheet
<xsl:stylesheet ...>
<xsl:variable name="my-global-var" select="/foo/bar" />
...
</xsl:stylesheet>
this XSpec will crash
<x:description ...>
<x:scenario ...>
<x:expect label="$my-global-var should be a bar element"
test="$my-global-var">
<bar/>
</x:expect>
</x:scenario>
</x:description>
because select="/foo/bar" in the stylesheet is evaluated with no context (no source document) while running XSpec. In this case, you may want to refactor the stylesheet with a global variable (or a global parameter) which by default points to the source document
<xsl:stylesheet ...>
<xsl:variable name="source-document" as="document-node()" select="." />
<xsl:variable name="my-global-var" select="$source-document/foo/bar" />
...
</xsl:stylesheet>
and override it in the XSpec to provide the "source" document for testing purposes
<x:description ...>
<x:variable name="source-document" select="/">
<foo>
<bar/>
</foo>
</x:variable>
<x:scenario label="With a source document containing a foo element containing a bar element">
<x:expect label="$my-global-var should be a bar element"
test="$my-global-var">
<bar/>
</x:expect>
</x:scenario>
</x:description>
> 2. Calling named templates from matched templates
> As far as I understand there is no way in XSpec to provide a context for
> a named template, but in the transformation proper, the named template
> *does* of course have a context, passed to it from the matched template.
> Here I assume I need to pass the context to the named template with a
> parameter. I've never done that before. Again: is this just good
> practice in general, or is it a workaround? Does it impact execution
> times at all if you do this for hundreds of templates?
You can provide a context for a named template.
I updated Wiki "Named Template Scenarios" section (
https://github.com/xspec/xspec/wiki/Writing-Scenarios#named-template-scenarios ) to clarify that.
--
AirQuick