trait Matcher[-T] extends (T) => MatchResult
Trait extended by objects that can match a value of the specified type. The value to match is
passed to the matcher's apply
method. The result is a MatchResult
.
A matcher is, therefore, a function from the specified type, T
, to a MatchResult
.
Creating custom matchers
If none of the built-in matcher syntax satisfies a particular need you have, you can create
custom Matcher
s that allow
you to place your own syntax directly after should
. For example, although you can ensure that a java.io.File
has a name
that ends with a particular extension like this:
file.getName should endWith (".txt")
You might prefer
to create a custom Matcher[java.io.File]
named endWithExtension
, so you could write expressions like:
file should endWithExtension ("txt") file should not endWithExtension "txt" file should (exist and endWithExtension ("txt"))
One good way to organize custom matchers is to place them inside one or more traits that you can then mix into the suites that need them. Here's an example:
import org.scalatest._ import matchers._
trait CustomMatchers {
class FileEndsWithExtensionMatcher(expectedExtension: String) extends Matcher[java.io.File] {
def apply(left: java.io.File) = { val name = left.getName MatchResult( name.endsWith(expectedExtension), s"""File $name did not end with extension "$expectedExtension"""", s"""File $name ended with extension "$expectedExtension"""" ) } }
def endWithExtension(expectedExtension: String) = new FileEndsWithExtensionMatcher(expectedExtension) }
// Make them easy to import with: // import CustomMatchers._ object CustomMatchers extends CustomMatchers
Note: the CustomMatchers
companion object exists to make it easy to bring the
matchers defined in this trait into scope via importing, instead of mixing in the trait. The ability
to import them is useful, for example, when you want to use the matchers defined in a trait in the Scala interpreter console.
This trait contains one matcher class, FileEndsWithExtensionMatcher
, and a def
named endWithExtension
that returns a new
instance of FileEndsWithExtensionMatcher
. Because the class extends Matcher[java.io.File]
,
the compiler will only allow it be used to match against instances of java.io.File
. A matcher must declare an
apply
method that takes the type decared in Matcher
's type parameter, in this case java.io.File
.
The apply method will return a MatchResult
whose matches
field will indicate whether the match succeeded.
The failureMessage
field will provide a programmer-friendly error message indicating, in the event of a match failure, what caused
the match to fail.
The FileEndsWithExtensionMatcher
matcher in this example determines success by determining if the passed java.io.File
ends with
the desired extension. It does this in the first argument passed to the MatchResult
factory method:
name.endsWith(expectedExtension)
In other words, if the file name has the expected extension, this matcher matches.
The next argument to MatchResult
's factory method produces the failure message string:
s"""File $name did not end with extension "$expectedExtension"""",
For example, consider this matcher expression:
import org.scalatest._ import Matchers._ import java.io.File import CustomMatchers._
new File("essay.text") should endWithExtension ("txt")
Because the passed java.io.File
has the name essay.text
, but the expected extension is "txt"
, the failure
message would be:
File essay.text did not have extension "txt"
For more information on the fields in a MatchResult
, including the subsequent field (or fields) that follow the failure message,
please see the documentation for MatchResult
.
Creating dynamic matchers
There are other ways to create new matchers besides defining one as shown above. For example, you might check that a file is hidden like this:
new File("secret.txt") should be ('hidden)
If you wanted to get rid of the tick mark, you could simply define hidden
like this:
val hidden = 'hidden
Now you can check that an file is hidden without the tick mark:
new File("secret.txt") should be (hidden)
You could get rid of the parens with by using shouldBe
:
new File("secret.txt") shouldBe hidden
Creating matchers using logical operators
You can also use ScalaTest matchers' logical operators to combine existing matchers into new ones, like this:
val beWithinTolerance = be >= 0 and be <= 10
Now you could check that a number is within the tolerance (in this case, between 0 and 10, inclusive), like this:
num should beWithinTolerance
When defining a full blown matcher, one shorthand is to use one of the factory methods in Matcher
's companion
object. For example, instead of writing this:
val beOdd = new Matcher[Int] { def apply(left: Int) = MatchResult( left % 2 == 1, left + " was not odd", left + " was odd" ) }
You could alternately write this:
val beOdd = Matcher { (left: Int) => MatchResult( left % 2 == 1, left + " was not odd", left + " was odd" ) }
Either way you define the beOdd
matcher, you could use it like this:
3 should beOdd 4 should not (beOdd)
Composing matchers
You can also compose matchers. For example, the endWithExtension
matcher from the example above
can be more easily created by composing a function with the existing endWith
matcher:
scala> import org.scalatest._ import org.scalatest._ scala> import Matchers._ import Matchers._ scala> import java.io.File import java.io.File scala> def endWithExtension(ext: String) = endWith(ext) compose { (f: File) => f.getPath } endWithExtension: (ext: String)org.scalatest.matchers.Matcher[java.io.File]
Now you have a Matcher[File]
whose apply
method first
invokes the converter function to convert the passed File
to a String
,
then passes the resulting String
to endWith
. Thus, you could use this version
endWithExtension
like the previous one:
scala> new File("output.txt") should endWithExtension("txt")
In addition, by composing twice, you can modify the type of both sides of a match statement with the same function, like this:
scala> val f = be > (_: Int) f: Int => org.scalatest.matchers.Matcher[Int] = <function1> scala> val g = (_: String).toInt g: String => Int = <function1> scala> val beAsIntsGreaterThan = (f compose g) andThen (_ compose g) beAsIntsGreaterThan: String => org.scalatest.matchers.Matcher[String] = <function1> scala> "8" should beAsIntsGreaterThan ("7")
At thsi point, however, the error message for the beAsIntsGreaterThan
gives no hint that the Int
s being compared were parsed from String
s:
scala> "7" should beAsIntsGreaterThan ("8") org.scalatest.exceptions.TestFailedException: 7 was not greater than 8
To modify error message, you can use trait MatcherProducers
, which
also provides a composeTwice
method that performs the compose
...
andThen
... compose
operation:
scala> import matchers._ import matchers._ scala> import MatcherProducers._ import MatcherProducers._ scala> val beAsIntsGreaterThan = f composeTwice g // means: (f compose g) andThen (_ compose g) beAsIntsGreaterThan: String => org.scalatest.matchers.Matcher[String] = <function1> scala> "8" should beAsIntsGreaterThan ("7")
Of course, the error messages is still the same:
scala> "7" should beAsIntsGreaterThan ("8") org.scalatest.exceptions.TestFailedException: 7 was not greater than 8
To modify the error messages, you can use mapResult
from MatcherProducers
. Here's an example:
scala> val beAsIntsGreaterThan = f composeTwice g mapResult { mr => mr.copy( failureMessageArgs = mr.failureMessageArgs.map((LazyArg(_) { "\"" + _.toString + "\".toInt"})), negatedFailureMessageArgs = mr.negatedFailureMessageArgs.map((LazyArg(_) { "\"" + _.toString + "\".toInt"})), midSentenceFailureMessageArgs = mr.midSentenceFailureMessageArgs.map((LazyArg(_) { "\"" + _.toString + "\".toInt"})), midSentenceNegatedFailureMessageArgs = mr.midSentenceNegatedFailureMessageArgs.map((LazyArg(_) { "\"" + _.toString + "\".toInt"})) ) } beAsIntsGreaterThan: String => org.scalatest.matchers.Matcher[String] = <function1>
The mapResult
method takes a function that accepts a MatchResult
and produces a new
MatchResult
, which can contain modified arguments and modified error messages. In this example,
the error messages are being modified by wrapping the old arguments in LazyArg
instances that lazily apply the given prettification functions to the toString
result of the old args.
Now the error message is clearer:
scala> "7" should beAsIntsGreaterThan ("8") org.scalatest.exceptions.TestFailedException: "7".toInt was not greater than "8".toInt
Matcher's variance
Matcher
is contravariant in its type parameter, T
, to make its use more flexible.
As an example, consider the hierarchy:
class Fruit class Orange extends Fruit class ValenciaOrange extends Orange
Given an orange:
val orange = Orange
The expression "orange should
" will, via an implicit conversion in Matchers
,
result in an object that has a should
method that takes a Matcher[Orange]
. If the static type of the matcher being passed to should
is
Matcher[Valencia]
it shouldn't (and won't) compile. The reason it shouldn't compile is that
the left value is an Orange
, but not necessarily a Valencia
, and a
Matcher[Valencia]
only knows how to match against a Valencia
. The reason
it won't compile is given that Matcher
is contravariant in its type parameter, T
, a
Matcher[Valencia]
is not a subtype of Matcher[Orange]
.
By contrast, if the static type of the matcher being passed to should
is Matcher[Fruit]
,
it should (and will) compile. The reason it should compile is that given the left value is an Orange
,
it is also a Fruit
, and a Matcher[Fruit]
knows how to match against Fruit
s.
The reason it will compile is that given that Matcher
is contravariant in its type parameter, T
, a
Matcher[Fruit]
is indeed a subtype of Matcher[Orange]
.
- Self Type
- Matcher[T]
- Source
- Matcher.scala
- Alphabetic
- By Inheritance
- Matcher
- Function1
- AnyRef
- Any
- Hide All
- Show All
- Public
- Protected
Type Members
- final class AndBeWord extends AnyRef
This class is part of the ScalaTest matchers DSL.
This class is part of the ScalaTest matchers DSL. Please see the documentation for
Matchers
for an overview of the matchers DSL. - final class AndContainWord extends AnyRef
This class is part of the ScalaTest matchers DSL.
This class is part of the ScalaTest matchers DSL. Please see the documentation for
Matchers
for an overview of the matchers DSL. - final class AndEndWithWord extends AnyRef
This class is part of the ScalaTest matchers DSL.
This class is part of the ScalaTest matchers DSL. Please see the documentation for
Matchers
for an overview of the matchers DSL. - final class AndFullyMatchWord extends AnyRef
This class is part of the ScalaTest matchers DSL.
This class is part of the ScalaTest matchers DSL. Please see the documentation for
Matchers
for an overview of the matchers DSL. - final class AndHaveWord extends AnyRef
This class is part of the ScalaTest matchers DSL.
This class is part of the ScalaTest matchers DSL. Please see the documentation for
Matchers
for an overview of the matchers DSL. - final class AndIncludeWord extends AnyRef
This class is part of the ScalaTest matchers DSL.
This class is part of the ScalaTest matchers DSL. Please see the documentation for
Matchers
for an overview of the matchers DSL. - final class AndNotWord extends AnyRef
This class is part of the ScalaTest matchers DSL.
This class is part of the ScalaTest matchers DSL. Please see the documentation for
Matchers
for an overview of the matchers DSL. - final class AndStartWithWord extends AnyRef
This class is part of the ScalaTest matchers DSL.
This class is part of the ScalaTest matchers DSL. Please see the documentation for
Matchers
for an overview of the matchers DSL. - final class OrBeWord extends AnyRef
This class is part of the ScalaTest matchers DSL.
This class is part of the ScalaTest matchers DSL. Please see the documentation for
Matchers
for an overview of the matchers DSL. - final class OrContainWord extends AnyRef
This class is part of the ScalaTest matchers DSL.
This class is part of the ScalaTest matchers DSL. Please see the documentation for
Matchers
for an overview of the matchers DSL. - final class OrEndWithWord extends AnyRef
This class is part of the ScalaTest matchers DSL.
This class is part of the ScalaTest matchers DSL. Please see the documentation for
Matchers
for an overview of the matchers DSL. - final class OrFullyMatchWord extends AnyRef
This class is part of the ScalaTest matchers DSL.
This class is part of the ScalaTest matchers DSL. Please see the documentation for
Matchers
for an overview of the matchers DSL. - final class OrHaveWord extends AnyRef
This class is part of the ScalaTest matchers DSL.
This class is part of the ScalaTest matchers DSL. Please see the documentation for
Matchers
for an overview of the matchers DSL. - final class OrIncludeWord extends AnyRef
This class is part of the ScalaTest matchers DSL.
This class is part of the ScalaTest matchers DSL. Please see the documentation for
Matchers
for an overview of the matchers DSL. - final class OrNotWord extends AnyRef
This class is part of the ScalaTest matchers DSL.
This class is part of the ScalaTest matchers DSL. Please see the documentation for
Matchers
for an overview of the matchers DSL. - final class OrStartWithWord extends AnyRef
This class is part of the ScalaTest matchers DSL.
This class is part of the ScalaTest matchers DSL. Please see the documentation for
Matchers
for an overview of the matchers DSL.
Abstract Value Members
- abstract def apply(left: T): MatchResult
Check to see if the specified object,
left
, matches, and report the result in the returnedMatchResult
.Check to see if the specified object,
left
, matches, and report the result in the returnedMatchResult
. The parameter is namedleft
, because it is usually the value to the left of ashould
ormust
invocation. For example, in:list should equal (List(1, 2, 3))
The
equal (List(1, 2, 3))
expression results in a matcher that holds a reference to the right value,List(1, 2, 3)
. Theshould
method invokesapply
on this matcher, passing inlist
, which is therefore the "left
" value. The matcher will compare thelist
(theleft
value) withList(1, 2, 3)
(the right value), and report the result in the returnedMatchResult
.- left
the value against which to match
- returns
the
MatchResult
that represents the result of the match
- Definition Classes
- Matcher → Function1
Concrete Value Members
- final def !=(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
- final def ##(): Int
- Definition Classes
- AnyRef → Any
- final def ==(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
- def and(notExist: ResultOfNotExist): MatcherFactory1[T, Existence]
This method enables the following syntax:
This method enables the following syntax:
aMatcher and not (exist) ^
- def and(existWord: ExistWord): MatcherFactory1[T, Existence]
This method enables the following syntax:
This method enables the following syntax:
aMatcher and exist ^
- def and(notWord: NotWord): AndNotWord
This method enables the following syntax:
This method enables the following syntax:
aMatcher and not contain value (3) ^
- def and(endWithWord: EndWithWord): AndEndWithWord
This method enables the following syntax:
This method enables the following syntax:
aMatcher and endWith regex (decimalRegex) ^
- def and(startWithWord: StartWithWord): AndStartWithWord
This method enables the following syntax:
This method enables the following syntax:
aMatcher and startWith regex ("1.7") ^
- def and(includeWord: IncludeWord): AndIncludeWord
This method enables the following syntax:
This method enables the following syntax:
aMatcher and include regex ("wor.d") ^
- def and(fullyMatchWord: FullyMatchWord): AndFullyMatchWord
This method enables the following syntax:
This method enables the following syntax:
aMatcher and fullyMatch regex (decimalRegex) ^
- def and(beWord: BeWord): AndBeWord
This method enables the following syntax:
This method enables the following syntax:
aMatcher and be a ('file) ^
- def and(containWord: ContainWord)(implicit prettifier: Prettifier, pos: Position): AndContainWord
This method enables the following syntax:
This method enables the following syntax:
aMatcher and contain key ("one") ^
- def and(haveWord: HaveWord): AndHaveWord
This method enables the following syntax:
This method enables the following syntax:
aMatcher and have size (3 - 1) ^
- def and[U, TC1[_]](rightMatcherFactory1: MatcherFactory1[U, TC1]): MatcherFactory1[T with U, TC1]
Returns a
MatcherFactory
whosematcher
method returns aMatcher
, which hasapply
method that returns aMatchResult
that represents the logical-and of the results of the wrapped and the passedMatcherFactory
applied to the same value.Returns a
MatcherFactory
whosematcher
method returns aMatcher
, which hasapply
method that returns aMatchResult
that represents the logical-and of the results of the wrapped and the passedMatcherFactory
applied to the same value.- rightMatcherFactory1
the
MatcherFactory
to logical-and with thisMatcherFactory
- returns
a
MatcherFactory
that performs the logical-and of this and the passedMatcherFactory
- def and[U <: T](rightMatcher: Matcher[U]): Matcher[U]
Returns a matcher whose
apply
method returns aMatchResult
that represents the logical-and of the results of the wrapped and the passed matcher applied to the same value.Returns a matcher whose
apply
method returns aMatchResult
that represents the logical-and of the results of the wrapped and the passed matcher applied to the same value.The reason
and
has an upper bound on its type parameter is so that theMatcher
resulting from an invocation ofand
will have the correct type parameter. If you calland
on aMatcher[Orange]
, passing in aMatcher[Valencia]
, the result will have typeMatcher[Valencia]
. This is correct because both aMatcher[Orange]
and aMatcher[Valencia]
know how to match aValencia
(but aMatcher[Valencia]
doesn't know how to match any oldOrange
). If you calland
on aMatcher[Orange]
, passing in aMatcher[Fruit]
, the result will have typeMatcher[Orange]
. This is also correct because both aMatcher[Orange]
and aMatcher[Fruit]
know how to match anOrange
(but aMatcher[Orange]
doesn't know how to match any oldFruit
).- returns
a matcher that performs the logical-and of this and the passed matcher
- def andThen[A](g: (MatchResult) => A): (T) => A
- Definition Classes
- Function1
- Annotations
- @unspecialized()
- final def asInstanceOf[T0]: T0
- Definition Classes
- Any
- def clone(): AnyRef
- Attributes
- protected[lang]
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.CloneNotSupportedException]) @native()
- def compose[U](g: (U) => T): Matcher[U]
Compose this matcher with the passed function, returning a new matcher.
Compose this matcher with the passed function, returning a new matcher.
This method overrides
compose
onFunction1
to return a more specific function type ofMatcher
. For example, given abeOdd
matcher defined like this:val beOdd = new Matcher[Int] { def apply(left: Int) = MatchResult( left % 2 == 1, left + " was not odd", left + " was odd" ) }
You could use
beOdd
like this:3 should beOdd 4 should not (beOdd)
If for some odd reason, you wanted a
Matcher[String]
that checked whether a string, when converted to anInt
, was odd, you could make one by composingbeOdd
with a function that converts a string to anInt
, like this:val beOddAsInt = beOdd compose { (s: String) => s.toInt }
Now you have a
Matcher[String]
whoseapply
method first invokes the converter function to convert the passed string to anInt
, then passes the resultingInt
tobeOdd
. Thus, you could usebeOddAsInt
like this:"3" should beOddAsInt "4" should not (beOddAsInt)
- Definition Classes
- Matcher → Function1
- final def eq(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
- def equals(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef → Any
- def finalize(): Unit
- Attributes
- protected[lang]
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.Throwable])
- final def getClass(): Class[_ <: AnyRef]
- Definition Classes
- AnyRef → Any
- Annotations
- @native()
- def hashCode(): Int
- Definition Classes
- AnyRef → Any
- Annotations
- @native()
- final def isInstanceOf[T0]: Boolean
- Definition Classes
- Any
- def mapArgs(prettify: (Any) => String): Matcher[T]
Creates a new
Matcher
that will produceMatchResult
s that contain error messages constructed using arguments that are transformed by the passedprettify
function.Creates a new
Matcher
that will produceMatchResult
s that contain error messages constructed using arguments that are transformed by the passedprettify
function. In other words, theMatchResult
produced by thisMatcher
will use arguments transformed byprettify
function to construct the final error messages.- prettify
a function with which to transform the arguments of error messages.
- returns
a new
Matcher
that will produceMatchResult
s that contain error messages constructed using arguments transformed by the passedprettify
function.
- def mapResult(prettify: (MatchResult) => MatchResult): Matcher[T]
Creates a new
Matcher
that will produceMatchResult
s by applying the originalMatchResult
produced by thisMatcher
to the passedprettify
function.Creates a new
Matcher
that will produceMatchResult
s by applying the originalMatchResult
produced by thisMatcher
to the passedprettify
function. In other words, theMatchResult
produced by thisMatcher
will be passed toprettify
to produce the finalMatchResult
- prettify
a function to apply to the original
MatchResult
produced by thisMatcher
- returns
a new
Matcher
that will produceMatchResult
s by applying the originalMatchResult
produced by thisMatcher
to the passedprettify
function
- final def ne(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
- final def notify(): Unit
- Definition Classes
- AnyRef
- Annotations
- @native()
- final def notifyAll(): Unit
- Definition Classes
- AnyRef
- Annotations
- @native()
- def or(notExist: ResultOfNotExist): MatcherFactory1[T, Existence]
This method enables the following syntax:
This method enables the following syntax:
aMatcher or not (exist) ^
- def or(existWord: ExistWord): MatcherFactory1[T, Existence]
This method enables the following syntax:
This method enables the following syntax:
aMatcher or exist ^
- def or(notWord: NotWord): OrNotWord
This method enables the following syntax:
This method enables the following syntax:
aMatcher or not contain value (3) ^
- def or(endWithWord: EndWithWord): OrEndWithWord
This method enables the following syntax:
This method enables the following syntax:
aMatcher or endWith regex ("7b") ^
- def or(startWithWord: StartWithWord): OrStartWithWord
This method enables the following syntax:
This method enables the following syntax:
aMatcher or startWith regex ("1.7") ^
- def or(includeWord: IncludeWord): OrIncludeWord
This method enables the following syntax:
This method enables the following syntax:
aMatcher or include regex ("1.7") ^
- def or(fullyMatchWord: FullyMatchWord): OrFullyMatchWord
This method enables the following syntax:
This method enables the following syntax:
aMatcher or fullyMatch regex (decimal) ^
- def or(beWord: BeWord): OrBeWord
This method enables the following syntax:
This method enables the following syntax:
aMatcher or be a ('directory) ^
- def or(containWord: ContainWord)(implicit prettifier: Prettifier, pos: Position): OrContainWord
This method enables the following syntax:
This method enables the following syntax:
aMatcher or contain value (1) ^
- def or(haveWord: HaveWord): OrHaveWord
This method enables the following syntax:
This method enables the following syntax:
aMatcher or have size (3 - 1) ^
- def or[U, TC1[_]](rightMatcherFactory1: MatcherFactory1[U, TC1]): MatcherFactory1[T with U, TC1]
Returns a
MatcherFactory
whosematcher
method returns aMatcher
, which hasapply
method that returns aMatchResult
that represents the logical-or of the results of the wrapped and the passedMatcherFactory
applied to the same value.Returns a
MatcherFactory
whosematcher
method returns aMatcher
, which hasapply
method that returns aMatchResult
that represents the logical-or of the results of the wrapped and the passedMatcherFactory
applied to the same value.- rightMatcherFactory1
the
MatcherFactory
to logical-or with thisMatcherFactory
- returns
a
MatcherFactory
that performs the logical-or of this and the passedMatcherFactory
- def or[U <: T](rightMatcher: Matcher[U]): Matcher[U]
Returns a matcher whose
apply
method returns aMatchResult
that represents the logical-or of the results of this and the passed matcher applied to the same value.Returns a matcher whose
apply
method returns aMatchResult
that represents the logical-or of the results of this and the passed matcher applied to the same value.The reason
or
has an upper bound on its type parameter is so that theMatcher
resulting from an invocation ofor
will have the correct type parameter. If you callor
on aMatcher[Orange]
, passing in aMatcher[Valencia]
, the result will have typeMatcher[Valencia]
. This is correct because both aMatcher[Orange]
and aMatcher[Valencia]
know how to match aValencia
(but aMatcher[Valencia]
doesn't know how to match any oldOrange
). If you callor
on aMatcher[Orange]
, passing in aMatcher[Fruit]
, the result will have typeMatcher[Orange]
. This is also correct because both aMatcher[Orange]
and aMatcher[Fruit]
know how to match anOrange
(but aMatcher[Orange]
doesn't know how to match any oldFruit
).- rightMatcher
the matcher to logical-or with this matcher
- returns
a matcher that performs the logical-or of this and the passed matcher
- final def synchronized[T0](arg0: => T0): T0
- Definition Classes
- AnyRef
- def toString(): String
- Definition Classes
- Function1 → AnyRef → Any
- final def wait(): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.InterruptedException])
- final def wait(arg0: Long, arg1: Int): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.InterruptedException])
- final def wait(arg0: Long): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.InterruptedException]) @native()