Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scalatest Double equivalency in list of case classes

I have Double values that are going to be similar in value, but not exact. Normally I would do:

val a: Double = ???
val b: Double = ???

a shouldEqual b +- 0.25

And if I was just comparing a single case class I would do:

case class Data(label: String, value: Double)
val a: Data = ???
val b: Data = ???
a.value shouldEqual b.value +- 0.25

In my case, I have a list of case class instances, and would like to compare them with a tolerance for their value attributes:

val output = Seq(Data("a", 1.1), Data("b", 1.2))
val expected = Seq(Data("a", 0.9), Data("b", 1.1))
output should contain theSameElementsInOrderAs expected

Of course, that would file because the value attributes do not match exactly. What I need is something like this:

output should contain theSameElementsInOrderAs expected +- 0.25
like image 307
Tyler Avatar asked Nov 09 '22 01:11

Tyler


1 Answers

I ended up defining a custom Matcher for my Seq[Data] type:

trait CustomMatcher {

  class SeqDataContainsTheSameElementsInOrderAs(expected: Seq[Data]) {

    override def apply(left: Seq[Data]): MatchResult = {

      // ... do other checks like comparing the length and such

      val bad = left.zip(expected).filter(t => {
        val difference = Math.abs(t._1.value - t._2.value)
        difference > TOLERANCE // Declare this somewhere
      })

      // Return the MatchResult, you will probably want to give better error messages than this
      MatchResult(
        bad.isEmpty,
        s"""Some of the values were not equal""",
        s"""Everything was equal"""
      )
    }

    def customContainTheSameElementsInOrderAs(expected: Seq[Data]) = new SeqDataContainsTheSameElementsInOrderAs(expected)
  }
}

Then I use it like:

output should customContainTheSameElementsInOrderAs(expected)
like image 134
Tyler Avatar answered Nov 15 '22 11:11

Tyler