My hacky matcher creation method, is there anything wrong with it?

14 views
Skip to first unread message

pou...@pouria.me

unread,
Jan 4, 2017, 7:32:14 PM1/4/17
to specs2-users
Hi,

Given the following:

def hackyMatcher[T](res: T => MatchResult[Any]): Matcher[T] = new Matcher[T] {
 
override def apply[S <: T](t: Expectable[S]): MatchResult[S] =
    res
(t.value).asInstanceOf[MatchResult[S]]   // Is the cast here problematic?
}

I can write matchers like:

def beCool = hackyMatcher[Int] {i =>
  val str
= i.hashCode.toString

  str
.length    must_== 12
  str
.charAt(3) must_== 'z'
}

I find the matcher above to be really to-the-point.

Without the hacky matcher, you'd have to do something like the following (is there a better way?):

def beCoolWithoutHacks: Matcher[Int] =
  be_
==(12)  ^^ {(_: Int).hashCode.toString.length} and
  be_
==('z') ^^ {(_: Int).hashCode.toString.charAt(3)}

Or:

def beCoolWithoutHacks2: Matcher[Int] = (
  be_
==(12)  ^^ {(_: String).length} and
  be_
==('z') ^^ {(_: String).charAt(3)}
) ^^ {(_: Int).hashCode.toString}

Both of the above are way less readable than the hacky matcher, as the logic is reversed, and you need type annotations everywhere.

My question is, should we add hackyMatcher to specs2, or is it just too hacky? Is there an existing, better way to accomplish this in specs2?

Thanks,
Pouria

etorreborre

unread,
Jan 6, 2017, 6:39:09 AM1/6/17
to specs2-users
In the org.specs2.matcher.MatcherImplicits object there is an implicit conversion doing what you want, so you can write:

import org.specs2.matcher.MatcherImplicits._

def beCool: Matcher[Int] = { actual =>
  val str = i.hashCode.toString

  str.length    must_== 12
  str.charAt(3) must_== 'z'
}

Eric.
Reply all
Reply to author
Forward
0 new messages