Functions that return a map?

16 views
Skip to first unread message

David Birnbaum

unread,
Aug 8, 2020, 1:56:17 PM8/8/20
to XSpec
I am trying to write a test for a function that returns a map, I don't find any documentation at https://github.com/xspec/xspec/wiki/Writing-Scenarios#expectations for how to do that, and I haven't been able to create an expectation that matches what the test outputs, even when I copy (or, at least, think I am copying) the actual output. I am using the code pulled from https://github.com/xspec/xspec today (2020-08-08; parenthetically, is there a command-line option to get XSpec to tell me its version, so that I can report that in postings like this?). Can someone please advise me about how to write an expectation that will match the way a map is returned during testing? I've tried the following:

When I first run the test with a dummy expectation, just to see, from the error report, what it returns (that is, to see what XSpec returns as a serialization of a map), it shows me (copied and pasted from the HTML report; it came back as one long line, which I pasted as is, so you have to scroll horizontally to read it all):

Result
XPath /* from:

<pseudo-map xmlns="http://www.jenitennison.com/xslt/xspec">map{"stress-loc":(3,5),"stem":"трапеезн","paradigm":<paradigm index="1*a" truncate="2"><!-- sample: удобный --><form case="N" gender="m" number="sg">ый</form><form case="N" gender="n" number="sg">ое</form><form case="G" gender="m" number="sg">ого</form><form case="G" gender="n" number="sg">ого</form><form case="D" gender="m" number="sg">ому</form><form case="D" gender="n" number="sg">ому</form><form case="A" gender="m" animacy="i" number="sg">ый</form><form case="A" gender="m" animacy="a" number="sg">ого</form><form case="A" gender="n" animacy="i" number="sg">ое</form><form case="A" gender="n" animacy="a" number="sg">ого</form><form case="I" gender="m" number="sg">ым</form><form case="I" gender="n" number="sg">ым</form><form case="L" gender="m" number="sg">ом</form><form case="L" gender="n" number="sg">ом</form><form case="N" gender="f" number="sg">ая</form><form case="G" gender="f" number="sg">ой</form><form case="D" gender="f" number="sg">ой</form><form case="I" gender="f" number="sg">ой</form><form case="I" gender="f" number="sg">ою</form><form case="A" gender="f" number="sg">ую</form><form case="L" gender="f" number="sg">ой</form><form case="N" number="pl">ые</form><form case="G" number="pl">ых</form><form case="L" number="pl">ых</form><form case="D" number="pl">ым</form><form case="A" animacy="i" number="pl">ые</form><form case="A" animacy="a" number="pl">ых</form><form case="I" number="pl">ыми</form><form gender="m" number="sg" type="short"/><form gender="f" number="sg" type="short">а</form><form gender="n" number="sg" type="short">о</form><form number="pl" type="short">ы</form><form type="comp">ее</form></paradigm>,"index":"1*a","secstress-loc":()}</pseudo-map>


I then copy and paste this into the <x:expect> field in my test file:

<x:scenario label="Scenario for testing function package-variables">
   
<x:call function="adj:package-variables">
       
<x:param name="item"><item error="False" id="33752" version="1">
               
<stressed>тр<stress>а</stress>п<stress>е</stress>езный</stressed>
               
<type partOfSpeech="A">п</type>
               
<paradigm>1*a</paradigm>
               
<entry>тра/пе/зный</entry>
           
</item></x:param>
   
</x:call>
   
<x:expect label="Map with values"><pseudo-map xmlns="http://www.jenitennison.com/xslt/xspec">map{"stress-loc":(3,5),"stem":"трапеезн","paradigm":<paradigm index="1*a" truncate="2"><!-- sample: удобный --><form case="N" gender="m" number="sg">ый</form><form case="N" gender="n" number="sg">ое</form><form case="G" gender="m" number="sg">ого</form><form case="G" gender="n" number="sg">ого</form><form case="D" gender="m" number="sg">ому</form><form case="D" gender="n" number="sg">ому</form><form case="A" gender="m" animacy="i" number="sg">ый</form><form case="A" gender="m" animacy="a" number="sg">ого</form><form case="A" gender="n" animacy="i" number="sg">ое</form><form case="A" gender="n" animacy="a" number="sg">ого</form><form case="I" gender="m" number="sg">ым</form><form case="I" gender="n" number="sg">ым</form><form case="L" gender="m" number="sg">ом</form><form case="L" gender="n" number="sg">ом</form><form case="N" gender="f" number="sg">ая</form><form case="G" gender="f" number="sg">ой</form><form case="D" gender="f" number="sg">ой</form><form case="I" gender="f" number="sg">ой</form><form case="I" gender="f" number="sg">ою</form><form case="A" gender="f" number="sg">ую</form><form case="L" gender="f" number="sg">ой</form><form case="N" number="pl">ые</form><form case="G" number="pl">ых</form><form case="L" number="pl">ых</form><form case="D" number="pl">ым</form><form case="A" animacy="i" number="pl">ые</form><form case="A" animacy="a" number="pl">ых</form><form case="I" number="pl">ыми</form><form gender="m" number="sg" type="short"/><form gender="f" number="sg" type="short">а</form><form gender="n" number="sg" type="short">о</form><form number="pl" type="short">ы</form><form type="comp">ее</form></paradigm>,"index":"1*a","secstress-loc":()}</pseudo-map>
   
</x:expect>
</x:scenario>



Since this is what XSpec tells me the test returned, I expected that if I pasted it into the <x:expect> field and reran the test, the test would succeed. When I run the test, though, it still reports failure:

Expected result:
XPath /element() from:

<pseudo-map xmlns="http://www.jenitennison.com/xslt/xspec"
           
xmlns:adj="http://www.obdurodon.org/adj"
           
xmlns:x="http://www.jenitennison.com/xslt/xspec">map{"stress-loc":(3,5),"stem":"трапеезн","paradigm":<paradigm index="1*a"
             
truncate="2"><!-- sample: удобный -->
     
<form case="N"
           
gender="m"
           
number="sg">ый</form>
     
<form case="N"
           
gender="n"
           
number="sg">ое</form>
     
<form case="G"
           
gender="m"
           
number="sg">ого</form>
     
<form case="G"
           
gender="n"
           
number="sg">ого</form>
     
<form case="D"
           
gender="m"
           
number="sg">ому</form>
     
<form case="D"
           
gender="n"
           
number="sg">ому</form>
     
<form case="A"
           
gender="m"
           
animacy="i"
           
number="sg">ый</form>
     
<form case="A"
           
gender="m"
           
animacy="a"
           
number="sg">ого</form>
     
<form case="A"
           
gender="n"
           
animacy="i"
           
number="sg">ое</form>
     
<form case="A"
           
gender="n"
           
animacy="a"
           
number="sg">ого</form>
     
<form case="I"
           
gender="m"
           
number="sg">ым</form>
     
<form case="I"
           
gender="n"
           
number="sg">ым</form>
     
<form case="L"
           
gender="m"
           
number="sg">ом</form>
     
<form case="L"
           
gender="n"
           
number="sg">ом</form>
     
<form case="N"
           
gender="f"
           
number="sg">ая</form>
     
<form case="G"
           
gender="f"
           
number="sg">ой</form>
     
<form case="D"
           
gender="f"
           
number="sg">ой</form>
     
<form case="I"
           
gender="f"
           
number="sg">ой</form>
     
<form case="I"
           
gender="f"
           
number="sg">ою</form>
     
<form case="A"
           
gender="f"
           
number="sg">ую</form>
     
<form case="L"
           
gender="f"
           
number="sg">ой</form>
     
<form case="N"
           
number="pl">ые</form>
     
<form case="G"
           
number="pl">ых</form>
     
<form case="L"
           
number="pl">ых</form>
     
<form case="D"
           
number="pl">ым</form>
     
<form case="A"
           
animacy="i"
           
number="pl">ые</form>
     
<form case="A"
           
animacy="a"
           
number="pl">ых</form>
     
<form case="I"
           
number="pl">ыми</form>
     
<form gender="m"
           
number="sg"
           
type="short" />
     
<form gender="f"
           
number="sg"
           
type="short">а</form>
     
<form gender="n"
           
number="sg"
           
type="short">о</form>
     
<form number="pl"
           
type="short">ы</form>
     
<form type="comp">ее</form>
   
</paradigm>,"index":"1*a","secstress-loc":()}</pseudo-map>


Can someone please advise me about what I appear to have misunderstood about writing expectations for functions that return maps?

AirQuick

unread,
Aug 8, 2020, 3:17:04 PM8/8/20
to xspec...@googlegroups.com
You can test a function returning a map. Here is a simple example:

<x:description stylesheet="test/do-nothing.xsl" xmlns:x="http://www.jenitennison.com/xslt/xspec">
<x:scenario label="When a function returns a map">
<x:call function="exactly-one">
<x:param
select="
map{
'key1': 'value1',
'key2': 'value2'
}"
/>
</x:call>
<x:expect label="Expecting the (semantically) same map should be Success"
select="
map{
'key2': 'value2',
'key1': 'value1'
}" />
<x:expect label="Expecting a different map should be Failure"
select="
map{
'key1': 'value1',
'key2': 'value2222'
}"
/>
</x:scenario>
</x:description>

But your map seems complex and cannot be expressed simply in x:expect/@select. You may want to test each map entry rather than testing the whole map at once:

<x:expect label="Keys" test="map:keys($x:result)" select="'stress-loc', 'paradigm', ..."
xmlns:map="http://www.w3.org/2005/xpath-functions/map" />
<x:expect label="stress-loc" test="$x:result?stress-loc" select="(3,5)" />
<x:expect label="paradigm" test="$x:result?paradigm>
<paradigm>...</paradigm>
</x:expect>
...

But you may still want to test the whole map at once. In that case, you can write a complex expected map in another stylesheet specified by x:helper:

my-vars.xsl:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet exclude-result-prefixes="#all" version="3.0" xmlns:myv="my-helper-variables"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:variable as="map(*)" name="myv:expect">
<xsl:map>
<xsl:map-entry key="'key1'">
<foo />
</xsl:map-entry>
... more complex entries ...
</xsl:map>
</xsl:variable>
</xsl:stylesheet>

XSpec:

<?xml version="1.0" encoding="UTF-8"?>
<x:description stylesheet="test/do-nothing.xsl" xmlns:myv="my-helper-variables"
xmlns:x="http://www.jenitennison.com/xslt/xspec">
<x:helper stylesheet="my-vars.xsl" />
<x:scenario label="When a function returns a complex map">
<x:call ...>...</x:call
<x:expect label="Expecting the same complex map defined in a helper stylesheet"
select="$myv:expect" />
</x:scenario>
</x:description>

See https://github.com/xspec/xspec/wiki/Integrating-Your-Own-Test-Helpers for x:helper. Note that x:helper is available only on XSpec v2.0 (or the very recent master branch).


> is there a command-line option to get XSpec to tell me its version, so that I can report that in postings like this?

Unfortunately, no...


> When I first run the test with a dummy expectation, just to see, from the error report, what it returns (that is, to see what XSpec returns as a serialization of a map), ...

<psuedo-*> in the report is not an exact copy of the result. It's an indirect fallback representation of the result.
See https://github.com/xspec/xspec/wiki/Understanding-Test-Results#pseudo-

David Birnbaum

unread,
Aug 8, 2020, 4:39:46 PM8/8/20
to XSpec
Thank you for the quick response. Testing the keys and the value of each key in my map does what I need, and it works as advertised, so I didn't try x:helper, but it is good to know that it's there for when it is needed.

Since XSpec outputs some general reporting information at the beginning anyway (Creating Test Stylesheet... Running Tests... Testing with SAXON EE 10.0), is there a reason not to output also the XSpec version? I'd be happy to create a feature request as an issue in the repo, since it seems as if it could be useful for reporting and debugging, but your response to my initial question makes me wonder whether the decision not to report the XSpec version was intentional, and for a reason I haven't understood. 

AirQuick

unread,
Aug 9, 2020, 9:56:50 PM8/9/20
to xspec...@googlegroups.com
> is there a reason not to output also the XSpec version?

Probably just because it was not necessary. Only a handful versions were there in the past.

I agree with you on its usefulness so I opened https://github.com/xspec/xspec/pull/1146.
Reply all
Reply to author
Forward
0 new messages