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

14 katselukertaa
Siirry ensimmäiseen lukemattomaan viestiin

pou...@pouria.me

lukematon,
4.1.2017 klo 19.32.144.1.2017
vastaanottaja 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

lukematon,
6.1.2017 klo 6.39.096.1.2017
vastaanottaja 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.
Vastaa kaikille
Vastaa kirjoittajalle
Välitä
0 uutta viestiä