@@ -22,23 +22,20 @@ import cats.effect.unsafe.implicits.global
2222import org .scalatest .freespec .AsyncFreeSpec
2323import org .scalatest .matchers .should .Matchers
2424import org .typelevel .otel4s .sdk .data .LimitedData
25- import org .typelevel .otel4s .sdk .testkit .trace .TracesTestkit
25+ import org .typelevel .otel4s .sdk .testkit .trace ._
2626import org .typelevel .otel4s .sdk .trace .context .propagation .W3CTraceContextPropagator
27- import org .typelevel .otel4s .sdk .trace .data .{EventData , StatusData }
28- import org .typelevel .otel4s .trace .{ StatusCode , TracerProvider }
27+ import org .typelevel .otel4s .sdk .trace .data .{EventData , SpanData }
28+ import org .typelevel .otel4s .trace .TracerProvider
2929import org .typelevel .otel4s .{Attribute , Attributes }
3030import sttp .client4 ._
3131import sttp .client4 .impl .cats .CatsMonadAsyncError
3232import sttp .client4 .testing .{BackendStub , ResponseStub , StubBody }
3333import sttp .model .{StatusCode => HttpStatusCode }
3434
35- import scala .concurrent .ExecutionContext
3635import scala .concurrent .duration .Duration
3736import scala .util .control .NoStackTrace
3837
39- class Otel4sTracingBackendTest extends AsyncFreeSpec with Matchers {
40-
41- override def executionContext : ExecutionContext = ExecutionContext .global
38+ class Otel4sTracingBackendTest extends AsyncFreeSpec with Matchers with AsyncExecutionContext {
4239
4340 " Otel4sTracingBackend" - {
4441 " should add tracing headers to the request" in {
@@ -86,8 +83,6 @@ class Otel4sTracingBackendTest extends AsyncFreeSpec with Matchers {
8683 response <- backend.send(basicRequest.get(uri " http://user:pwd@localhost:8080/success?q=v " ))
8784 spans <- testkit.finishedSpans
8885 } yield {
89- val status = StatusData (StatusCode .Unset )
90-
9186 val attributes = Attributes (
9287 Attribute (" http.request.method" , " GET" ),
9388 Attribute (" http.response.status_code" , 200L ),
@@ -99,11 +94,19 @@ class Otel4sTracingBackendTest extends AsyncFreeSpec with Matchers {
9994
10095 response.code shouldBe HttpStatusCode .Ok
10196
102- spans.map(_.attributes.elements) shouldBe List (attributes)
103- spans.map(_.events.elements) shouldBe List (Vector .empty)
104- spans.map(_.status) shouldBe List (status)
105-
106- succeed
97+ assertSpansMatch(
98+ spans,
99+ TraceForestExpectation .ordered(
100+ TraceExpectation .leaf(
101+ SpanExpectation
102+ .client(" GET" )
103+ .noParentSpanContext
104+ .attributesExact(attributes)
105+ .status(StatusExpectation .unset)
106+ .eventCount(0 )
107+ )
108+ )
109+ )
107110 }
108111 }
109112 .unsafeToFuture()
@@ -130,8 +133,6 @@ class Otel4sTracingBackendTest extends AsyncFreeSpec with Matchers {
130133 response <- backend.send(basicRequest.get(uri " http://user@localhost:8080/bad-request?q=v " ))
131134 spans <- testkit.finishedSpans
132135 } yield {
133- val status = StatusData (StatusCode .Error )
134-
135136 val attributes = Attributes (
136137 Attribute (" http.request.method" , " GET" ),
137138 Attribute (" http.response.status_code" , 400L ),
@@ -144,11 +145,19 @@ class Otel4sTracingBackendTest extends AsyncFreeSpec with Matchers {
144145
145146 response.code shouldBe HttpStatusCode .BadRequest
146147
147- spans.map(_.attributes.elements) shouldBe List (attributes)
148- spans.map(_.events.elements) shouldBe List (Vector .empty)
149- spans.map(_.status) shouldBe List (status)
150-
151- succeed
148+ assertSpansMatch(
149+ spans,
150+ TraceForestExpectation .ordered(
151+ TraceExpectation .leaf(
152+ SpanExpectation
153+ .client(" GET" )
154+ .noParentSpanContext
155+ .attributesExact(attributes)
156+ .status(StatusExpectation .error)
157+ .eventCount(0 )
158+ )
159+ )
160+ )
152161 }
153162 }
154163 .unsafeToFuture()
@@ -179,8 +188,6 @@ class Otel4sTracingBackendTest extends AsyncFreeSpec with Matchers {
179188 response <- backend.send(basicRequest.get(uri " http://localhost/error " )).attempt
180189 spans <- testkit.finishedSpans
181190 } yield {
182- val status = StatusData (StatusCode .Error )
183-
184191 val attributes = Attributes (
185192 Attribute (" http.request.method" , " GET" ),
186193 Attribute (" server.address" , " localhost" ),
@@ -197,16 +204,34 @@ class Otel4sTracingBackendTest extends AsyncFreeSpec with Matchers {
197204
198205 response shouldBe Left (Err )
199206
200- spans.map(_.attributes.elements) shouldBe List (attributes)
201- spans.map(_.events.elements) shouldBe List (Vector (event))
202- spans.map(_.status) shouldBe List (status)
203-
204- succeed
207+ assertSpansMatch(
208+ spans,
209+ TraceForestExpectation .ordered(
210+ TraceExpectation .leaf(
211+ SpanExpectation
212+ .client(" GET" )
213+ .noParentSpanContext
214+ .attributesExact(attributes)
215+ .status(StatusExpectation .error)
216+ .exactlyEvents(
217+ EventExpectation .any.where(" matches the recorded exception event" )(_ == event)
218+ )
219+ )
220+ )
221+ )
205222 }
206223 }
207224 }
208225 .unsafeToFuture()
209226 }
210227 }
211228
229+ private def assertSpansMatch (spans : List [SpanData ], expectation : TraceForestExpectation ) =
230+ TraceExpectations .check(spans, expectation) match {
231+ case Right (_) =>
232+ succeed
233+ case Left (mismatches) =>
234+ fail(TraceExpectations .format(mismatches))
235+ }
236+
212237}
0 commit comments