diff --git a/modules/api/src/main/scala/gs/test/v0/api/Check.scala b/modules/api/src/main/scala/gs/test/v0/api/Check.scala index d586a3e..94f22eb 100644 --- a/modules/api/src/main/scala/gs/test/v0/api/Check.scala +++ b/modules/api/src/main/scala/gs/test/v0/api/Check.scala @@ -106,6 +106,16 @@ object Check: ): F[TestResult] = Sync[F].delay(isEqualTo(expected)) + def isEqualToT[F[_]: Sync]( + expected: A + )( + using + CanEqual[A, A], + ClassTag[A], + SourcePosition + ): EitherT[F, TestFailure, Any] = + EitherT(Sync[F].delay(isEqualTo(expected))) + extension (obtained: Check[Boolean]) /** ## Usage diff --git a/modules/runtime/src/test/scala/gs/test/v0/runtime/engine/TestEngineTests.scala b/modules/runtime/src/test/scala/gs/test/v0/runtime/engine/TestEngineTests.scala index 5b22a64..5427faf 100644 --- a/modules/runtime/src/test/scala/gs/test/v0/runtime/engine/TestEngineTests.scala +++ b/modules/runtime/src/test/scala/gs/test/v0/runtime/engine/TestEngineTests.scala @@ -4,8 +4,7 @@ import cats.effect.IO import cats.effect.Resource import gs.test.v0.api.* import gs.test.v0.reporting.InMemoryReporter -import gs.test.v0.runtime.engine.TestEngineTests.EngineObservation -import gs.test.v0.runtime.engine.TestEngineTests.G1 +import gs.test.v0.runtime.engine.TestEngineTests.* import gs.timing.v0.MonotonicProvider.ManualTickProvider import gs.timing.v0.Timing import gs.uuid.v0.UUID @@ -79,6 +78,50 @@ class TestEngineTests extends IOSuite: } } + iotest("should run an engine with a single failing test") { + newEngine().use { obs => + val g2 = new G2 + val group = g2.compile() + for + suiteExecution <- obs.engine.runSuite( + suite = Generators.testSuite(), + tests = fs2.Stream.apply(group) + ) + rootSpan <- obs.entryPoint.getSpan(EngineConstants.Tracing.RootSpan) + groupSpan <- obs.entryPoint.getSpan(EngineConstants.Tracing.FullGroup) + beforeGroupSpan <- obs.entryPoint.getSpan( + EngineConstants.Tracing.BeforeGroup + ) + afterGroupSpan <- obs.entryPoint.getSpan( + EngineConstants.Tracing.AfterGroup + ) + inGroupSpan <- obs.entryPoint.getSpan(EngineConstants.Tracing.InGroup) + fullTestSpan <- obs.entryPoint.getSpan(EngineConstants.Tracing.FullTest) + beforeTestSpan <- obs.entryPoint.getSpan( + EngineConstants.Tracing.BeforeTest + ) + afterTestSpan <- obs.entryPoint.getSpan( + EngineConstants.Tracing.AfterTest + ) + testSpan <- obs.entryPoint.getSpan(EngineConstants.Tracing.TestSpan) + results <- obs.reporter.terminateAndGetResults() + yield + assertEquals(rootSpan.isDefined, true) + assertEquals(groupSpan.isDefined, true) + assertEquals(beforeGroupSpan.isDefined, true) + assertEquals(afterGroupSpan.isDefined, true) + assertEquals(inGroupSpan.isDefined, true) + assertEquals(fullTestSpan.isDefined, true) + assertEquals(beforeTestSpan.isDefined, true) + assertEquals(afterTestSpan.isDefined, true) + assertEquals(testSpan.isDefined, true) + assertEquals(results.size, 1) + assertEquals(suiteExecution.seen, 1L) + assertEquals(suiteExecution.passed, 0L) + assertEquals(suiteExecution.failed, 1L) + } + } + private def emptyStream[A]: fs2.Stream[IO, A] = fs2.Stream.empty @@ -130,4 +173,15 @@ object TestEngineTests: check(true).isTrueT() } + end G1 + + class G2 extends TestGroup[IO]: + override def name: String = "single-failing-test" + + test(pid"engine:g2", "this will fail") { + check(1).isEqualToT(2) + } + + end G2 + end TestEngineTests