Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on May 26th, 2012  |  syntax: None  |  size: 3.32 KB  |  hits: 10  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. Creating a Specs2 matcher in a modular way
  2. type TF = A => Double
  3. (f: TF) must computeSameResultsAs(g: TF,tolerance: Double, tests: Set[A])
  4.        
  5. (f: TF) must computeSameResultsAs(g: TF)
  6.                .withTolerance(tolerance)
  7.                .onValues(tests: Set[A])
  8.        
  9. def computeSameResultsAs[A](ref: A => Double, tolerance: Double, args: Set[A]): Matcher[A => Double] =
  10.   args.map(beCloseOnArg(ref, tolerance, _)).reduce(_ and _)
  11.  
  12. def beCloseOnArg[A](ref: A => Double, tolerance: Double, arg: A): Matcher[A => Double] =
  13.   closeTo(ref(arg), tolerance) ^^ ((_: A => Double).apply(arg))
  14.        
  15. def beCloseOnArg[A](ref: A => Double, tolerance: Double, arg: A): Matcher[A => Double] =
  16.   closeTo(ref(arg), tolerance) ^^ ((_: A => Double).apply(arg) aka "result on argument " + arg)
  17.        
  18. def computeSameResultsAs[A](g: A => Double,
  19.                             tolerance: Double = 0.0,
  20.                             values: Seq[A] = Seq()) = TFMatcher(g, tolerance, values)
  21.  
  22. case class TFMatcher[A](g: A => Double,
  23.                         tolerance: Double = 0.0,
  24.                         values: Seq[A] = Seq()) extends Matcher[A => Double] {
  25.  
  26.   def apply[S <: A => Double](f: Expectable[S]) = {
  27.     // see definition below
  28.   }
  29.  
  30.   def withTolerance(t: Double) = TFMatcher(g, t, values)
  31.   def onValues(tests: A*) = TFMatcher(g, tolerance, tests)
  32. }
  33.        
  34. val f = (i: Int) => i.toDouble
  35. val g = (i: Int) => i.toDouble + 0.1
  36.  
  37. "f must be close to another similar function with a tolerance" in {
  38.   f must computeSameResultsAs[Int](g).withTolerance(0.5).onValues(1, 2, 3)          
  39. }
  40.        
  41. def apply[S <: A => Double](f: Expectable[S]) = {
  42.   val res = ((v: A) => beCloseTo(g(v) +/- tolerance).apply(theValue(f.value(v)))).forall(values)
  43.  
  44.   val message = "f is "+(if (res.isSuccess) "" else "not ")+
  45.                 "close to g with a tolerance of "+tolerance+" "+
  46.                 "on values "+values.mkString(",")+": "+res.message
  47.    result(res.isSuccess, message, message, f)
  48.  }
  49.        
  50. ((v: A) => beCloseTo(g(v) +/- tolerance).apply(theValue(f.value(v)))).forall(values)
  51.        
  52. val f = (i: Int) => i.toDouble
  53. val g = (i: Int) => i.toDouble + 1.0
  54.  
  55. "f must be close to another similar function with a tolerance" in {
  56.   f must computeSameResultsAs[Int](g, tolerance = 0.5, values = Seq(1, 2, 3))          
  57. }
  58.  
  59. def computeSameResultsAs[A](ref: A => Double, tolerance: Double, values: Seq[A]): Matcher[A => Double] = (f: A => Double) => {
  60.   verifyFunction((a: A) => (beCloseTo(ref(a) +/- tolerance)).apply(theValue(f(a)))).forall(values)
  61. }
  62.        
  63. In the sequence '1, 2, 3', the 1st element is failing: 1.0 is not close to 2.0 +/- 0.5
  64.        
  65. implicit def functionResultToMatcher[T](f: T => MatchResult[_]): Matcher[T] = (t: T) => {
  66.   val result = f(t)
  67.   (result.isSuccess, result.message)
  68. }
  69.        
  70. 1.0 is not close to 2.0 +/- 0.5; 2.0 is not close to 3.0 +/- 0.5; 3.0 is not close to 4.0 +/- 0.5
  71.        
  72. def computeSameResultsAs[A](ref: A => Double, tolerance: Double, values: Seq[A]): Matcher[A => Double] = (f: A => Double) => {
  73.   ((a: A) => beCloseTo(ref(a) +/- tolerance) ^^ f).forall(values)
  74. }
  75.        
  76. def computeSameResultsAs[A](ref: A => Double, tolerance: Double, values: Seq[A]): Matcher[A => Double] = (f: A => Double) => {
  77.   ((a: A) => beCloseTo(ref(a) +/- tolerance) ^^ ((a1: A) => f(a) aka "the value")).forall(values)
  78. }
  79.        
  80. In the sequence '1, 2, 3', the 1st element is failing: the value '1.0' is not close to 2.0 +/- 0.5