diff --git a/test-tests/shared/src/test/scala/zio/test/DefaultTestReporterSpec.scala b/test-tests/shared/src/test/scala/zio/test/DefaultTestReporterSpec.scala index 33436f25382a..5b756b6a1fec 100644 --- a/test-tests/shared/src/test/scala/zio/test/DefaultTestReporterSpec.scala +++ b/test-tests/shared/src/test/scala/zio/test/DefaultTestReporterSpec.scala @@ -40,6 +40,11 @@ object DefaultTestReporterSpec extends ZIOBaseSpec { test("correctly reports labeled failures") { assertM(runLog(test7))(equalTo(test7Expected.mkString + "\n" + reportStats(0, 0, 1))) }, + test("correctly reports labeled failures for assertTrue") { + for { + log <- runLog(test9) + } yield assertTrue(log.contains("""?? "third""""), log.contains("""?? "fourth"""")) + }, test("correctly reports negated failures") { assertM(runLog(test8))(equalTo(test8Expected.mkString + "\n" + reportStats(0, 0, 1))) } diff --git a/test-tests/shared/src/test/scala/zio/test/ReportingTestUtils.scala b/test-tests/shared/src/test/scala/zio/test/ReportingTestUtils.scala index 99a4a72c6bab..add6650ccd57 100644 --- a/test-tests/shared/src/test/scala/zio/test/ReportingTestUtils.scala +++ b/test-tests/shared/src/test/scala/zio/test/ReportingTestUtils.scala @@ -156,6 +156,13 @@ object ReportingTestUtils { withOffset(2)(assertSourceLocation() + "\n") ) + def test9(implicit trace: ZTraceElement): ZSpec[Any, Nothing] = test("labeled failures") { + assertTrue(1 == 1).map(_.label("first")) && + assertTrue(1 == 1).map(_.label("second")) && + assertTrue(1 == 0).map(_.label("third")) && + assertTrue(1 == 0).map(_.label("fourth")) + } + def suite1(implicit trace: ZTraceElement): Spec[Any, TestFailure[Nothing], TestSuccess] = suite("Suite1")(test1, test2) def suite1Expected(implicit trace: ZTraceElement): Vector[String] = Vector( diff --git a/test/shared/src/main/scala/zio/test/AssertionResult.scala b/test/shared/src/main/scala/zio/test/AssertionResult.scala index e8d938f1945f..1baef150e87d 100644 --- a/test/shared/src/main/scala/zio/test/AssertionResult.scala +++ b/test/shared/src/main/scala/zio/test/AssertionResult.scala @@ -12,7 +12,7 @@ sealed trait AssertionResult { self => case result: FailureDetailsResult => result.copy(failureDetails = result.failureDetails.label(label)) case result: AssertionResult.TraceResult => - result + result.copy(label = Some(label)) } def setGenFailureDetails(details: GenFailureDetails): AssertionResult = @@ -27,6 +27,9 @@ sealed trait AssertionResult { self => object AssertionResult { case class FailureDetailsResult(failureDetails: FailureDetails, genFailureDetails: Option[GenFailureDetails] = None) extends AssertionResult - case class TraceResult(trace: Trace[Boolean], genFailureDetails: Option[GenFailureDetails] = None) - extends AssertionResult + case class TraceResult( + trace: Trace[Boolean], + genFailureDetails: Option[GenFailureDetails] = None, + label: Option[String] = None + ) extends AssertionResult } diff --git a/test/shared/src/main/scala/zio/test/DefaultTestReporter.scala b/test/shared/src/main/scala/zio/test/DefaultTestReporter.scala index 5a1e385a77ea..11b125937b9a 100644 --- a/test/shared/src/main/scala/zio/test/DefaultTestReporter.scala +++ b/test/shared/src/main/scala/zio/test/DefaultTestReporter.scala @@ -85,10 +85,10 @@ object DefaultTestReporter { result .fold[Option[TestResult]] { case result: AssertionResult.FailureDetailsResult => Some(BoolAlgebra.success(result)) - case AssertionResult.TraceResult(trace, genFailureDetails) => + case AssertionResult.TraceResult(trace, genFailureDetails, label) => Trace .prune(trace, false) - .map(a => BoolAlgebra.success(AssertionResult.TraceResult(a, genFailureDetails))) + .map(a => BoolAlgebra.success(AssertionResult.TraceResult(a, genFailureDetails, label))) }( { case (Some(a), Some(b)) => Some(a && b) @@ -185,12 +185,12 @@ object DefaultTestReporter { def renderAssertionResult(assertionResult: AssertionResult, offset: Int): Message = assertionResult match { - case AssertionResult.TraceResult(trace, genFailureDetails) => + case AssertionResult.TraceResult(trace, genFailureDetails, label) => val failures = FailureCase.fromTrace(trace) failures .map(fc => renderGenFailureDetails(genFailureDetails, offset) ++ - Message(renderFailureCase(fc, offset)) + Message(renderFailureCase(fc, offset, label)) ) .foldLeft(Message.empty)(_ ++ _) @@ -199,7 +199,7 @@ object DefaultTestReporter { renderFailureDetails(failureDetails, offset) } - def renderFailureCase(failureCase: FailureCase, offset: Int): Chunk[Line] = + def renderFailureCase(failureCase: FailureCase, offset: Int, testLabel: Option[String]): Chunk[Line] = failureCase match { case FailureCase(errorMessage, codeString, location, path, _, nested, _) => val errorMessageLines = @@ -210,8 +210,8 @@ object DefaultTestReporter { val result = errorMessageLines ++ - Chunk(Line.fromString(codeString)) ++ - nested.flatMap(renderFailureCase(_, offset)).map(_.withOffset(1)) ++ + Chunk(Line.fromString(testLabel.fold(codeString)(l => s"""$codeString ?? "$l""""))) ++ + nested.flatMap(renderFailureCase(_, offset, None)).map(_.withOffset(1)) ++ Chunk.fromIterable(path.flatMap { case (label, value) => Chunk.fromIterable(PrettyPrint(value).split("\n").map(primary(_).toLine)) match { case head +: lines => (dim(s"${label.trim} = ") +: head) +: lines