Skip to content

Commit

Permalink
Add stack trace to output for beSuccessfulTry on failure (etorreborre…
Browse files Browse the repository at this point in the history
…#1163)

* Add stack trace to output for beSuccessfulTry on failure

* Add some types to TryMatchers
  • Loading branch information
tmccombs authored Jun 12, 2023
1 parent 8b488a0 commit 5a84743
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 6 deletions.
27 changes: 23 additions & 4 deletions matcher/shared/src/main/scala/org/specs2/matcher/TryMatchers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package matcher

import scala.reflect.ClassTag
import util.*
import execute.{Result, AsResult}
import execute.ResultImplicits.*
import org.specs2.matcher.describe.Diffable
import text.NotNullStrings.*
Expand Down Expand Up @@ -45,11 +46,17 @@ trait TryMatchers:

object TryeMatchers extends TryMatchers

case class TrySuccessMatcher[T]() extends OptionLikeMatcher[Try[T], T]("a Success", (_: Try[T]).toOption):
def withValue(t: ValueCheck[T]) = TrySuccessCheckedMatcher(t)
case class TrySuccessMatcher[T]() extends Matcher[Try[T]]:
def apply[S <: Try[T]](value: Expectable[S]): Result = checkSuccess(value, ValueCheck.alwaysOk)

case class TrySuccessCheckedMatcher[T](check: ValueCheck[T])
extends OptionLikeCheckedMatcher[Try[T], T]("a Success", (_: Try[T]).toOption, check)
def withValue(t: ValueCheck[T]): Matcher[Try[T]] = TrySuccessCheckedMatcher(t)

def which[R: AsResult](f: T => R): Matcher[Try[T]] = new TrySuccessCheckedMatcher(f)

def like[R: AsResult](f: PartialFunction[T, R]): Matcher[Try[T]] = new TrySuccessCheckedMatcher(f)

case class TrySuccessCheckedMatcher[T](check: ValueCheck[T]) extends Matcher[Try[T]]:
def apply[S <: Try[T]](value: Expectable[S]): Result = checkSuccess(value, check)

case class TryFailureMatcher[T]()
extends OptionLikeMatcher[Try[T], Throwable]("a Failure", (_: Try[T]).failed.toOption):
Expand All @@ -65,3 +72,15 @@ case class TryFailureMatcher[T]()
})
case class TryFailureCheckedMatcher[T](check: ValueCheck[Throwable])
extends OptionLikeCheckedMatcher[Try[T], Throwable]("a Failure", (_: Try[T]).failed.toOption, check)

private def checkSuccess[T](value: Expectable[Try[T]], check: ValueCheck[T]): Result = value.value match
case Success(v) =>
val r = check.check(v)
val koMessage = s"${value.description} is a Success but ${r.message}"
r match
case execute.Failure(_, _, _, details) => Result.result(false, koMessage, details)
case _ => Result.result(r.isSuccess, koMessage)
case Failure(e) =>
execute.Failure(
s"${value.description} is not a Success\n\nFailed with ${e.getMessage}:\n\n${e.getStackTrace.mkString("\n")}"
)
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ class TryMatchersSpec extends Spec with TryMatchers with ResultMatchers {
${(Succeeded(1) must beASuccessfulTry.which(_ > 0))}
${(Succeeded(1) must beASuccessfulTry
.which(_ < 0)) returns "Success(1) is a Success but the function returns 'false' on '1'"}
${(Failed[I](e) must beASuccessfulTry.which(_ > 0)) returns "Failure(boom) is not a Success"}
${(Failed[I](e) must beASuccessfulTry.which(_ > 0)) returns "Failure(boom) is not a Success\n\nFailed with boom:\n\n"}

${Succeeded(1) must beASuccessfulTry[Int].like { case a if a > 0 => ok }}
${(Succeeded(1) must not(beASuccessfulTry[Int].like { case a => a must be_>=(0) })) returns "Expectation failed: 'Success(1) is a Success but 1 is strictly less than 0'"}
${Succeeded(1) must not(beASuccessfulTry.withValue(2))}
${Failed[I](e) must not(beASuccessfulTry)}
${Failed[I](e) must not(beASuccessfulTry.withValue(2))}
${(Failed[I](e) must beSuccessfulTry) returns "Failure(boom) is not a Success"}
${(Failed[I](e) must beSuccessfulTry) returns "Failure(boom) is not a Success\n\nFailed with boom:\n\n"}
${(Succeeded(1) must beSuccessfulTry.withValue(2)) returns "Success(1) is a Success but 1 != 2"}

beAFailure checks if an element is Failure(_)
Expand Down

0 comments on commit 5a84743

Please sign in to comment.