Skip to content

Commit

Permalink
fix: fix the failure messages for container matchers
Browse files Browse the repository at this point in the history
when using modifiers like atMost, atLeast, exactly
fixes #1201
  • Loading branch information
etorreborre committed Nov 4, 2023
1 parent 4c2dec8 commit 68afff6
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,7 @@ class FilesContentMatchersSpec extends Spec with FilesContentMatchers with Befor
|MD5 mismatch:
|file | MD5
|${(targetDir / actual / sub | f2).path} | 4392ebd49e53e2cfe36abb22e39601db
|${(targetDir / expected2 / sub | f2).path} | 1b7b2f1969fee054225ad6bbf7f6bdd7
|""".stripMargin.replace(" ", "")
|${(targetDir / expected2 / sub | f2).path} | 1b7b2f1969fee054225ad6bbf7f6bdd7""".stripMargin.replace(" ", "")

val targetDir: DirectoryPath = "target" / "test" / FileName.unsafe("fcm-" + hashCode)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ import text.Plural.*

case class ContainWithResult[T](
check: ValueCheck[T],
timesMin: Option[Times] = Some(1.times),
timesMin: Option[Times] = Some(Times(1)),
timesMax: Option[Times] = None,
checkAll: Boolean = true,
negate: Boolean = false
Expand All @@ -472,11 +472,18 @@ case class ContainWithResult[T](
failures.collect { case Failure(_, _, _, d) if d != NoDetails => d }.headOption.getOrElse(NoDetails)

(timesMin, timesMax) match
case (None, None) => Result.result(successes.size == seq.size, koMessage, details)
case (Some(Times(min)), None) => Result.result(successes.size >= min, koMessage, details)
case (None, Some(Times(max))) => Result.result(successes.size <= max, koMessage, details)
case (None, None) => Result.result(successes.size == seq.size, koMessage, details)
case (Some(Times(min)), None) =>
val message = koMessage + s"""\nNumber of successful matches: ${successes.size}. Expected: at least $min"""
Result.result(successes.size >= min, message, details)
case (None, Some(Times(max))) =>
val message = koMessage + s"""\nNumber of successful matches: ${successes.size}. Expected: at most $max"""
Result.result(successes.size <= max, message, details)
case (Some(Times(min)), Some(Times(max))) =>
Result.result(successes.size >= min && successes.size <= max, koMessage, details)
val expected =
if min == max then s"exactly $min" else if min == 1 then s"at most $max" else s"between $min and $max"
val message = koMessage + s"""\nNumber of successful matches: ${successes.size}. Expected: $expected"""
Result.result(successes.size >= min && successes.size <= max, message, details)
}

if negate then Result.result(!r.isSuccess, "Expectation failed:\n" + r.message)
Expand All @@ -500,25 +507,29 @@ case class ContainWithResult[T](
def foreach = copy(timesMin = None, timesMax = None)

private def messages[S <: Traversable[T]](expectable: String, successes: Seq[Result], failures: Seq[Result]) =
def equalValueCheckMessages(expected: Any) =
val containsMessage = s"$expectable contains $expected"
val doesNotContainMessage = s"$expectable does not contain $expected"
(containsMessage, if successes.isEmpty then doesNotContainMessage else containsMessage)

check match
case BeEqualTypedValueCheck(expected) =>
(s"$expectable contains $expected", s"$expectable does not contain $expected")
case BeEqualValueCheck(expected) => (s"$expectable contains $expected", s"$expectable does not contain $expected")
case _ => genericMessages(expectable, successes, failures)
case BeEqualTypedValueCheck(expected) => equalValueCheckMessages(expected)
case BeEqualValueCheck(expected) => equalValueCheckMessages(expected)
case _ => genericMessages(expectable, successes, failures)

private def genericMessages(
expectable: String,
successes: scala.collection.Seq[Result],
failures: scala.collection.Seq[Result]
) =
def elementsAre(results: scala.collection.Seq[Result], success: Boolean) =
if results.isEmpty then s"There are no matches"
if results.isEmpty then (if success then "There are no matches" else "There are no failures")
else if results.size <= 1 then s"There is ${results.size} ${if success then "success" else "failure"}"
else s"There are ${results.size} ${if success then "successes" else "failures"}"

def messages(results: scala.collection.Seq[Result]) =
if results.isEmpty then ""
else results.map(_.message).mkString("\n", "\n", "\n")
else results.map(_.message).mkString("\n", "\n", "")

(
elementsAre(successes, success = true) + messages(successes),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ Messages

def collection2 =
def beEven: Matcher[Int] = (i: Int) => (i % 2 == 0, i.toString + " is odd")
foreach(Seq(1, 2, 3))((i: Int) => i must beEven) returns "There are 2 failures\n1 is odd\n3 is odd\n"
foreach(Seq(1, 2, 3))((i: Int) => i must beEven) returns "There are 2 failures\n1 is odd\n3 is odd"

def messages1 =
def beEven: Matcher[Int] = (i: Int) => (i % 2 == 0, i.toString + " is odd")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ class TraversableMatchersSpec(val env: Env) extends Specification with ResultMat
${(Seq(1, 2, 3) must not(contain(be_>=(2)))) returns "Expectation failed:\nThere is 1 failure\n1 is strictly less than 2"}
${(Seq(1, 2, 3) must contain(be_>=(3))
.atLeast(2.times)) returns "There are 2 failures\n1 is strictly less than 3\n2 is strictly less than 3\n"}
${(Seq(1, 2, 3) must contain(be_>=(3)).atLeast(2.times)) returns "There are 2 failures\n1 is strictly less than 3\n2 is strictly less than 3\nNumber of successful matches: 1. Expected: at least 2"}
${(Seq(1, 2, 3) must contain(be_>=(1)).atMost(2.times)) returns "There are no failures\nNumber of successful matches: 3. Expected: at most 2"}
${(Seq(1, 2, 3) must contain(be_>=(3)).exactly(2.times)) returns "There are 2 failures\n1 is strictly less than 3\n2 is strictly less than 3\nNumber of successful matches: 1. Expected: exactly 2"}
${(Seq(1, 2, 3, 4) must contain(be_>=(2)).atMost(2.times)) returns "There is 1 failure\n1 is strictly less than 2\nNumber of successful matches: 3. Expected: at most 2"}
${(Seq(1, 1, 2, 3) must contain(===(1)).exactly(1.times)) returns "There are 2 failures\n2 != 1\n3 != 1\nNumber of successful matches: 2. Expected: exactly 1"}

We can compare a collection to another by using matchers

Expand Down

0 comments on commit 68afff6

Please sign in to comment.