Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions modules/core/shared/src/main/scala/weaver/Expectations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -96,15 +96,16 @@ case class Expectations(run: ValidatedNel[ExpectationFailed, Unit]) {
Expectations(otherL.orElse(otherR).orElse(otherL.product(otherR).void))
}

/** Raises an error in an effect if an expectation has failed. */
def failFast[F[_]: Sync]: F[Unit] =
this.run match {
case Invalid(e) => Sync[F].raiseError(e.head)
case Invalid(e) => Sync[F].raiseError(new ExpectationsFailed(e))
case Valid(_) => Sync[F].unit
}

/**
* Adds the specified location to the list of locations that will be reported
* if an expectation is failed.
* if an expectation has failed.
*/
def traced(loc: SourceLocation): Expectations =
Expectations(run.leftMap(_.map(e =>
Expand Down
11 changes: 5 additions & 6 deletions modules/core/shared/src/main/scala/weaver/Result.scala
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ private[weaver] object Result {
object Failures {
final case class Failure(
msg: String,
source: Throwable,
source: ExpectationFailed,
locations: NonEmptyList[SourceLocation])
}

Expand Down Expand Up @@ -104,13 +104,12 @@ private[weaver] object Result {

def from(error: Throwable): Result = {
error match {
case ex: ExpectationFailed =>
Failures(NonEmptyList.of(Failures.Failure(
ex.message,
ex,
ex.locations)))
case ex: IgnoredException =>
Ignored(ex.reason, ex.location)
case exs: ExpectationsFailed =>
Failures(exs.failures.map { ex =>
Failures.Failure(ex.message, ex, ex.locations)
})
case other =>
Exception(other)
}
Expand Down
3 changes: 2 additions & 1 deletion modules/core/shared/src/main/scala/weaver/TestOutcome.scala
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ object TestOutcome {

def cause: Option[Throwable] = result match {
case Result.Exception(cause) => Some(cause)
case Result.Failures(failures) => Some(failures.head.source)
case Result.Failures(failures) =>
Some(new ExpectationsFailed(failures.map(_.source)))
case Result.OnlyTagNotAllowedInCI(_) | Result.Ignored(
_,
_) | Result.Success => None
Expand Down
8 changes: 6 additions & 2 deletions modules/core/shared/src/main/scala/weaver/exceptions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ sealed abstract class WeaverTestException private[weaver] (

final class ExpectationFailed(
private[weaver] val message: String,
private[weaver] val locations: NonEmptyList[SourceLocation])
extends WeaverTestException(message) {
private[weaver] val locations: NonEmptyList[SourceLocation]) {
private[weaver] def withLocation(
location: SourceLocation): ExpectationFailed =
new ExpectationFailed(message, locations.append(location))
Expand All @@ -19,3 +18,8 @@ final class IgnoredException private[weaver] (
private[weaver] val reason: String,
private[weaver] val location: SourceLocation)
extends WeaverTestException(reason)

final class ExpectationsFailed(
private[weaver] val failures: NonEmptyList[ExpectationFailed])
extends WeaverTestException(
s"One or more expecations failed:\n${failures.map(_.message).toList.mkString(System.lineSeparator)}")
23 changes: 23 additions & 0 deletions modules/framework-cats/shared/src/test/scala/DogFoodTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,29 @@ object DogFoodTests extends IOSuite {
}
}

test("multiple failures are rendered for failFast") {
_.runSuite(Meta.Rendering).flatMap {
case (logs, _) =>
val actual = extractFailureMessageForTest(logs, "(failFast)")

assertInlineSnapshot(
actual,
"""- (failFast) 0ms
[0] Values not equal: (src/main/DogFoodTests.scala:5)
[0]
[0] => Diff (- obtained, + expected)
[0] -2
[0] +1

[1] Values not equal: (src/main/DogFoodTests.scala:5)
[1]
[1] => Diff (- obtained, + expected)
[1] -4
[1] +3"""
)
}
}

test("successes with clues are rendered correctly") {
_.runSuite(Meta.Clue).flatMap {
case (logs, _) =>
Expand Down
3 changes: 3 additions & 0 deletions modules/framework-cats/shared/src/test/scala/Meta.scala
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ object Meta {
expect(s"$x" == "2")
}

test("(failFast)") {
expect.eql(1, 2).and(expect.eql(3, 4)).failFast.as(success)
}
}

object Clue extends SimpleIOSuite {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,10 @@ trait Checkers {
x match {
case Some((_, Right(ex))) if ex.run.isValid => TestResult.Success
case Some((t, Right(ex))) => TestResult.Failure(t.show, ex)
case Some((t, Left(exception: ExpectationFailed))) =>
TestResult.Failure(t.show,
Expectations(Validated.invalidNel(exception)))
case Some((t, Left(exception: ExpectationsFailed))) =>
TestResult.Failure(
t.show,
Expectations(Validated.invalid(exception.failures)))
case Some((t, Left(other))) => TestResult.Exception(t.show, other)
case None => TestResult.Discard
}
Expand Down