Skip to content

Commit 6f4da96

Browse files
committed
Modify failFast to raise multiple expectation failures.
1 parent 07b9f18 commit 6f4da96

File tree

7 files changed

+46
-14
lines changed

7 files changed

+46
-14
lines changed

modules/core/shared/src/main/scala/weaver/Expectations.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,15 +96,16 @@ case class Expectations(run: ValidatedNel[ExpectationFailed, Unit]) {
9696
Expectations(otherL.orElse(otherR).orElse(otherL.product(otherR).void))
9797
}
9898

99+
/** Raises an error in an effect if an expectation has failed. */
99100
def failFast[F[_]: Sync]: F[Unit] =
100101
this.run match {
101-
case Invalid(e) => Sync[F].raiseError(e.head)
102+
case Invalid(e) => Sync[F].raiseError(new ExpectationsFailed(e))
102103
case Valid(_) => Sync[F].unit
103104
}
104105

105106
/**
106107
* Adds the specified location to the list of locations that will be reported
107-
* if an expectation is failed.
108+
* if an expectation has failed.
108109
*/
109110
def traced(loc: SourceLocation): Expectations =
110111
Expectations(run.leftMap(_.map(e =>

modules/core/shared/src/main/scala/weaver/Result.scala

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ private[weaver] object Result {
6666
object Failures {
6767
final case class Failure(
6868
msg: String,
69-
source: Throwable,
69+
source: ExpectationFailed,
7070
locations: NonEmptyList[SourceLocation])
7171
}
7272

@@ -104,13 +104,12 @@ private[weaver] object Result {
104104

105105
def from(error: Throwable): Result = {
106106
error match {
107-
case ex: ExpectationFailed =>
108-
Failures(NonEmptyList.of(Failures.Failure(
109-
ex.message,
110-
ex,
111-
ex.locations)))
112107
case ex: IgnoredException =>
113108
Ignored(ex.reason, ex.location)
109+
case exs: ExpectationsFailed =>
110+
Failures(exs.failures.map { ex =>
111+
Failures.Failure(ex.message, ex, ex.locations)
112+
})
114113
case other =>
115114
Exception(other)
116115
}

modules/core/shared/src/main/scala/weaver/TestOutcome.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ object TestOutcome {
4444

4545
def cause: Option[Throwable] = result match {
4646
case Result.Exception(cause) => Some(cause)
47-
case Result.Failures(failures) => Some(failures.head.source)
47+
case Result.Failures(failures) =>
48+
Some(new ExpectationsFailed(failures.map(_.source)))
4849
case Result.OnlyTagNotAllowedInCI(_) | Result.Ignored(
4950
_,
5051
_) | Result.Success => None

modules/core/shared/src/main/scala/weaver/exceptions.scala

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ sealed abstract class WeaverTestException private[weaver] (
88

99
final class ExpectationFailed(
1010
private[weaver] val message: String,
11-
private[weaver] val locations: NonEmptyList[SourceLocation])
12-
extends WeaverTestException(message) {
11+
private[weaver] val locations: NonEmptyList[SourceLocation]) {
1312
private[weaver] def withLocation(
1413
location: SourceLocation): ExpectationFailed =
1514
new ExpectationFailed(message, locations.append(location))
@@ -19,3 +18,8 @@ final class IgnoredException private[weaver] (
1918
private[weaver] val reason: String,
2019
private[weaver] val location: SourceLocation)
2120
extends WeaverTestException(reason)
21+
22+
final class ExpectationsFailed(
23+
private[weaver] val failures: NonEmptyList[ExpectationFailed])
24+
extends WeaverTestException(
25+
s"One or more expecations failed:\n${failures.map(_.message).toList.mkString(System.lineSeparator)}")

modules/framework-cats/shared/src/test/scala/DogFoodTests.scala

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,29 @@ object DogFoodTests extends IOSuite {
401401
}
402402
}
403403

404+
test("multiple failures are rendered for failFast") {
405+
_.runSuite(Meta.Rendering).flatMap {
406+
case (logs, _) =>
407+
val actual = extractFailureMessageForTest(logs, "(failFast)")
408+
409+
assertInlineSnapshot(
410+
actual,
411+
"""- (failFast) 0ms
412+
[0] Values not equal: (src/main/DogFoodTests.scala:5)
413+
[0]
414+
[0] => Diff (- obtained, + expected)
415+
[0] -2
416+
[0] +1
417+
418+
[1] Values not equal: (src/main/DogFoodTests.scala:5)
419+
[1]
420+
[1] => Diff (- obtained, + expected)
421+
[1] -4
422+
[1] +3"""
423+
)
424+
}
425+
}
426+
404427
test("successes with clues are rendered correctly") {
405428
_.runSuite(Meta.Clue).flatMap {
406429
case (logs, _) =>

modules/framework-cats/shared/src/test/scala/Meta.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,9 @@ object Meta {
119119
expect(s"$x" == "2")
120120
}
121121

122+
test("(failFast)") {
123+
expect.eql(1, 2).and(expect.eql(3, 4)).failFast.as(success)
124+
}
122125
}
123126

124127
object Clue extends SimpleIOSuite {

modules/scalacheck/shared/src/main/scala/weaver/scalacheck/Checkers.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,10 @@ trait Checkers {
150150
x match {
151151
case Some((_, Right(ex))) if ex.run.isValid => TestResult.Success
152152
case Some((t, Right(ex))) => TestResult.Failure(t.show, ex)
153-
case Some((t, Left(exception: ExpectationFailed))) =>
154-
TestResult.Failure(t.show,
155-
Expectations(Validated.invalidNel(exception)))
153+
case Some((t, Left(exception: ExpectationsFailed))) =>
154+
TestResult.Failure(
155+
t.show,
156+
Expectations(Validated.invalid(exception.failures)))
156157
case Some((t, Left(other))) => TestResult.Exception(t.show, other)
157158
case None => TestResult.Discard
158159
}

0 commit comments

Comments
 (0)