Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6755420

Browse files
committed
zio-test: Ignored annotated suites should not trigger shared layer creation
1 parent 4cf2798 commit 6755420

File tree

5 files changed

+180
-36
lines changed

5 files changed

+180
-36
lines changed

test-sbt/shared/src/test/scala/zio/test/sbt/FrameworkSpecInstances.scala

Lines changed: 95 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package zio.test.sbt
22

33
import zio.test._
4-
import zio.{ZIO, ZLayer, durationInt}
4+
import zio.{Scope, ZIO, ZLayer, durationInt}
55

66
import java.util.concurrent.atomic.AtomicInteger
77

@@ -135,6 +135,100 @@ object FrameworkSpecInstances {
135135
)
136136
}
137137

138+
object TagsSpecWithFailingEnv extends ZIOSpecDefault {
139+
// failing test with `provide`
140+
private val suiteWithFailingProvideEnv =
141+
(
142+
suite("suite with tag and failing `provide` env")(
143+
test("should not be executed - 0")(assertTrue(false))
144+
).provide(ZLayer(ZIO.fail(new RuntimeException("should not be called - 0"))))
145+
) @@ TestAspect.tag("NotExecuted")
146+
147+
// succeeding test with `provide`
148+
private val suiteWithValidProvideEnv =
149+
(
150+
suite("suite with tag and valid `provide` env")(
151+
test("should be executed - 1")(ZIO.serviceWith[Int](i => assertTrue(i == 1)))
152+
).provide(ZLayer.succeed(1))
153+
) @@ TestAspect.tag("Executed")
154+
155+
// failing test with `provideShared`
156+
private val suiteWithFailingProvideSharedEnv =
157+
(
158+
suite("suite with tag and failing `provideShared` env")(
159+
test("should not be executed - 2")(assertTrue(false))
160+
).provideShared(ZLayer(ZIO.fail(new RuntimeException("should not be called - 2"))))
161+
) @@ TestAspect.tag("NotExecuted")
162+
163+
// succeeding test with `provideShared`
164+
private val suiteWithValidProvideSharedEnv =
165+
(
166+
suite("suite with tag and valid `provideShared` env")(
167+
test("should be executed - 3")(ZIO.serviceWith[Int](i => assertTrue(i == 1)))
168+
).provideShared(ZLayer.succeed(1))
169+
) @@ TestAspect.tag("Executed")
170+
171+
// failing test with `provideLayerShared`
172+
private val suiteWithFailingProvideLayerSharedEnv =
173+
(
174+
suite("suite with tag and failing `provideShared` env")(
175+
test("should not be executed - 4")(assertTrue(false))
176+
).provideLayerShared(ZLayer(ZIO.fail(new RuntimeException("should not be called - 4"))))
177+
) @@ TestAspect.tag("NotExecuted")
178+
179+
// succeeding test with `provideLayerShared`
180+
private val suiteWithValidProvideLayerSharedEnv =
181+
(
182+
suite("suite with tag and valid `provideShared` env")(
183+
test("should be executed - 5")(ZIO.serviceWith[Int](i => assertTrue(i == 1)))
184+
).provideLayerShared(ZLayer.succeed(1))
185+
) @@ TestAspect.tag("Executed")
186+
187+
// failing test with `provideSomeLayerShared`
188+
private val suiteWithFailingProvideSomeLayerSharedEnv =
189+
(
190+
suite("suite with tag and failing `provideShared` env")(
191+
test("should not be executed - 6")(assertTrue(false))
192+
).provideSomeLayerShared[Int](
193+
ZLayer.fail(new RuntimeException("should not be called - 6")): ZLayer[Int, Throwable, Any]
194+
)
195+
).provide(ZLayer.succeed(1)) @@ TestAspect.tag("NotExecuted")
196+
197+
// succeeding test with `provideSomeLayerShared`
198+
private val suiteWithValidProvideSomeLayerSharedEnv =
199+
(
200+
suite("suite with tag and valid `provideShared` env")(
201+
test("should be executed - 7")(ZIO.serviceWith[Int](i => assertTrue(i == 1)))
202+
).provideSomeLayerShared[Int](ZLayer.service[Int])
203+
).provide(ZLayer.succeed(1)) @@ TestAspect.tag("Executed")
204+
205+
private val suiteWithTestWithFailingProvideEnv =
206+
suite("suite with tags and with tests having invalid env")(
207+
(
208+
test("should not be executed - 8") {
209+
assertTrue(false)
210+
}.provide(ZLayer(ZIO.fail(new RuntimeException("should not be called - 8"))))
211+
) @@ TestAspect.tag("NotExecuted"),
212+
test("should be executed - 9") {
213+
assertTrue(true)
214+
} @@ TestAspect.tag("Executed")
215+
)
216+
217+
override def spec: Spec[TestEnvironment with Scope, Any] =
218+
suite("tag suite with failing env")(
219+
suiteWithFailingProvideEnv,
220+
suiteWithValidProvideEnv,
221+
suiteWithFailingProvideSharedEnv,
222+
suiteWithValidProvideSharedEnv,
223+
suiteWithFailingProvideLayerSharedEnv,
224+
suiteWithValidProvideLayerSharedEnv,
225+
suiteWithValidProvideSomeLayerSharedEnv,
226+
suiteWithValidProvideSomeLayerSharedEnv,
227+
suiteWithFailingProvideSomeLayerSharedEnv,
228+
suiteWithTestWithFailingProvideEnv
229+
)
230+
}
231+
138232
object NestedSpec extends ZIOSpecDefault {
139233
def spec: Spec[Any, TestFailure[Any]] = suite("outer")(
140234
suite("inner")(

test-sbt/shared/src/test/scala/zio/test/sbt/ZTestFrameworkSpec.scala

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
package zio.test.sbt
22

33
import sbt.testing.{Status, TestSelector}
4-
import zio.{Scope, ZIO}
5-
import zio.test.{Spec, TestAspect, TestEnvironment, TestResult, ZIOSpecDefault, assertTrue}
64
import zio.test.sbt.Colors.{green, red, yellow}
75
import zio.test.sbt.ExecuteSpecs.{getEvents, getOutput, getOutputs}
6+
import zio.test.{Spec, TestAspect, TestEnvironment, TestResult, ZIOSpecDefault, assertTrue, assert}
7+
import zio.{Scope, ZIO}
88

99
object ZTestFrameworkSpec extends ZIOSpecDefault {
1010
override def spec: Spec[TestEnvironment with Scope, Any] = suite("test framework")(
@@ -136,6 +136,37 @@ object ZTestFrameworkSpec extends ZIOSpecDefault {
136136
)
137137
} yield assertTrue(output.equals(expected))
138138
},
139+
test("do not create layers for test with ignored tag") {
140+
for {
141+
output <- getOutput(FrameworkSpecInstances.TagsSpecWithFailingEnv, args = Array("-ignore-tags", "NotExecuted"))
142+
} yield {
143+
// Verify all tests with "Executed" tag ran successfully
144+
assertTrue(
145+
output.exists(_.contains("""should be executed - 1 - tagged: "Executed"""")),
146+
output.exists(_.contains("""should be executed - 3 - tagged: "Executed"""")),
147+
output.exists(_.contains("""should be executed - 5 - tagged: "Executed"""")),
148+
output.exists(_.contains("""should be executed - 7 - tagged: "Executed"""")),
149+
output.exists(_.contains("""should be executed - 9 - tagged: "Executed""""))
150+
) &&
151+
// Verify that tests with "NotExecuted" tag did NOT run
152+
assertTrue(
153+
!output.exists(_.contains("""should not be executed - 0""")),
154+
!output.exists(_.contains("""should not be executed - 2""")),
155+
!output.exists(_.contains("""should not be executed - 4""")),
156+
!output.exists(_.contains("""should not be executed - 6""")),
157+
!output.exists(_.contains("""should not be executed - 8"""))
158+
) &&
159+
// Verify that layers for filtered tests were NOT constructed
160+
// This is the critical assertion: if layers were built, we'd see these error messages
161+
assertTrue(
162+
!output.exists(_.contains("should not be called - 0")),
163+
!output.exists(_.contains("should not be called - 2")),
164+
!output.exists(_.contains("should not be called - 4")),
165+
!output.exists(_.contains("should not be called - 6")),
166+
!output.exists(_.contains("should not be called - 8"))
167+
)
168+
}
169+
},
139170
test("honor `TestSelector`s") {
140171
for {
141172
events <- getEvents(FrameworkSpecInstances.SimpleFailingSharedSpec)

test-tests/shared/src/test/scala/zio/test/SpecSpec.scala

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -83,28 +83,25 @@ object SpecSpec extends ZIOBaseSpec {
8383
trait Service {
8484
def open: UIO[Boolean]
8585
}
86-
object Service {
87-
val open: ZIO[Service, Nothing, Boolean] =
88-
ZIO.serviceWithZIO(_.open)
89-
}
9086
val layer =
9187
ZLayer {
9288
for {
9389
ref <- Ref.make(true)
9490
_ <- ZIO.addFinalizer(ref.set(false))
9591
} yield new Service {
96-
def open: UIO[Boolean] =
97-
ref.get
92+
def open: UIO[Boolean] = ref.get
9893
}
9994
}
100-
val spec = suite("suite")(
101-
test("test1") {
102-
assertZIO(Service.open)(isTrue)
103-
},
104-
test("test2") {
105-
assertZIO(Service.open)(isTrue)
106-
}
107-
).provideLayerShared(layer).provideLayer(Scope.default) @@ sequential
95+
val spec =
96+
suite("suite")(
97+
test("test1") {
98+
assertZIO(ZIO.serviceWithZIO[Service](_.open))(isTrue)
99+
},
100+
test("test2") {
101+
assertZIO(ZIO.serviceWithZIO[Service](_.open))(isTrue)
102+
}
103+
).provideLayerShared(layer).provideLayer(Scope.default) @@ sequential
104+
108105
assertZIO(succeeded(spec))(isTrue)
109106
},
110107
test("propagates the scope to multiple tests") {

test/shared/src/main/scala/zio/test/Spec.scala

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -347,11 +347,21 @@ final case class Spec[-R, +E](caseValue: SpecCase[R, E, Spec[R, E]]) extends Spe
347347
.flatMap(r => scoped.map(_.provideEnvironment(r)).provideSomeEnvironment[Scope](r.union[Scope]))
348348
)
349349
case MultipleCase(specs) =>
350-
Spec.scoped[R0](
351-
layer.memoize.flatMap(layer =>
352-
layer.mapError(TestFailure.fail).build.map(_ => Spec.multiple(specs.map(_.provideLayer(layer))))
353-
)
354-
)
350+
Spec.scoped[R0] {
351+
ZIO.scopeWith { scope =>
352+
import Spec.RichLayer
353+
354+
val scopedLayer: ZLayer[R0, E1, R] =
355+
ZLayer.makeSome[R0, R](
356+
ZLayer.succeed(scope),
357+
layer.extendScope
358+
)
359+
360+
scopedLayer.memoizeWithinScope(scope).map { memoizedLayer =>
361+
Spec.multiple(specs.map(_.provideLayer(memoizedLayer)))
362+
}
363+
}
364+
}
355365
case TestCase(test, annotations) => Spec.test(test.provideLayer(layer.mapError(TestFailure.fail)), annotations)
356366
}
357367

@@ -538,12 +548,19 @@ object Spec {
538548
}
539549
)
540550
case MultipleCase(specs) =>
541-
Spec.scoped[R0](
542-
layer.memoize
543-
.flatMap(layer =>
544-
layer.mapError(TestFailure.fail).build.map(_ => Spec.multiple(specs.map(_.provideSomeLayer[R0](layer))))
545-
)
546-
)
551+
Spec.scoped[R0] {
552+
ZIO.scopeWith { scope =>
553+
val scopedLayer: ZLayer[R0, E1, R1] =
554+
ZLayer.makeSome[R0, R1](
555+
ZLayer.succeed(scope),
556+
layer.extendScope
557+
)
558+
559+
scopedLayer.memoizeWithinScope(scope).map { memoizedLayer =>
560+
Spec.multiple(specs.map(_.provideSomeLayer[R0](memoizedLayer)))
561+
}
562+
}
563+
}
547564
case TestCase(test, annotations) =>
548565
Spec.test(test.provideSomeLayer(layer.mapError(TestFailure.fail)), annotations)
549566
}
@@ -567,4 +584,13 @@ object Spec {
567584
)(implicit tag: Tag[Map[Key, Service]], trace: Trace): Spec[R1, E] =
568585
self.provideSomeEnvironment(_.updateAt(key)(f))
569586
}
587+
588+
private implicit final class RichLayer[RIn, E0, ROut](private val layer: ZLayer[RIn, E0, ROut]) extends AnyVal {
589+
590+
/**
591+
* Version of `ZLayer::memoize` that uses the provided scope.
592+
*/
593+
def memoizeWithinScope(scope: Scope)(implicit trace: Trace): ZIO[Any, Nothing, ZLayer[RIn, E0, ROut]] =
594+
layer.build(scope).memoize.map(ZLayer.fromZIOEnvironment(_))
595+
}
570596
}

test/shared/src/main/scala/zio/test/ZIOSpecAbstract.scala

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,14 +97,11 @@ abstract class ZIOSpecAbstract extends ZIOApp with ZIOSpecAbstractVersionSpecifi
9797
): URIO[
9898
Environment with TestEnvironment with Scope,
9999
Summary
100-
] = {
101-
val filteredSpec: Spec[Environment with TestEnvironment with Scope, Any] = FilteredSpec(spec, testArgs)
102-
100+
] =
103101
for {
104-
runtime <-
105-
ZIO.runtime[
106-
TestEnvironment with Scope
107-
]
102+
runtime <- ZIO.runtime[TestEnvironment with Scope]
103+
104+
filteredSpec = FilteredSpec(spec, testArgs)
108105

109106
scopeEnv: ZEnvironment[Scope] = runtime.environment
110107
perTestLayer = (ZLayer.succeedEnvironment(scopeEnv) <*> liveEnvironment) >>>
@@ -128,7 +125,6 @@ abstract class ZIOSpecAbstract extends ZIOApp with ZIOSpecAbstractVersionSpecifi
128125
aspects.foldLeft(filteredSpec)(_ @@ _) @@ TestAspect.fibers: @nowarn("cat=deprecation")
129126
)
130127
} yield summary
131-
}
132128

133129
@deprecated("use the overload that does not take Console parameter")
134130
private[zio] def runSpecWithSharedRuntimeLayer(

0 commit comments

Comments
 (0)