scala - ScalaTest - writing custom matchers -
i running problem while writing custom matcher nodeseq:
private def matchxml(expected: nodeseq) = new matcher[nodeseq] { def apply(left: nodeseq): matchresult = matchresult(left xml_== expected, "xml structure not same (watch spaces in tag texts)", "xml messages equal") }
this compiles, following piece of code:
val expected : nodeseq = ... val xml : nodeseq = ... xml should matchxml(expected)
causes:
error: overloaded method value should alternatives: (beword: xmlstripdecoratortests.this.beword)xmlstripdecoratortests.this.resultofbewordforanyref[scala.collection.genseq[scala.xml.node]] <and> (notword: xmlstripdecoratortests.this.notword)xmlstripdecoratortests.this.resultofnotwordforanyref[scala.collection.genseq[scala.xml.node]] <and> (haveword: xmlstripdecoratortests.this.haveword)xmlstripdecoratortests.this.resultofhavewordforseq[scala.xml.node] <and> (rightmatcher: org.scalatest.matchers.matcher[scala.collection.genseq[scala.xml.node]])unit cannot applied (org.scalatest.matchers.matcher[scala.xml.nodeseq]) xml should (matchxml(expected))
any ideas means?
why fails typecheck:
the type checker works in following way.
xml.should(matchxml(expected))
- because method
should
not part ofnodeseq
, compiler tries find implicit conversionxml
shouldmatcher
. book "programming in scala" specifies such implicit conversion should specific:
"up through scala 2.7, end of story. whenever multiple implicit conversions applied, compiler refused choose between them. ... scala 2.8 loosens rule. if 1 of available conversions strictly more specific others, compiler choose more specific one. ... 1 implicit conversion more specific if 1 of following applies: argument type of former subtype of latter’s. .."
because
nodeseq
extendsseq[node]
, following functionconverttoseqshouldwrapper[t](o : scala.genseq[t]) : seqshouldwrapper[t]
is therefore specific 1 among others.
the program rewritten as:
`converttoseqshouldwrapper(xml).should(matchxml(expected))`
where converttoseqshouldwrapper(xml)
seqshouldwrapper[t]
t = genseq[node]
.
the method should
seqshouldwrapper
accepts matcher[t]
function of type t => matchresult
. therefore, accepts matcher[genseq[node]]
.
because t
appearing left of arrow, matchers not covariant in t
, contravariant. nodeseq
genseq[node]
, matcher[genseq[node]]
matcher[nodeseq]
, not opposite.this explains above error, method should
cannot accept matcher[nodeseq]
, requires matcher[genseq[node]]
.
2 solutions
- replace instances of
nodeseq
genseq[node]
type matches everywhere. alternatively, wrap xml explicitely conversion function.
converttoanyshouldwrapper(xml).should(matchxml(expected))
Comments
Post a Comment