@@ -188,15 +188,22 @@ public function test_assert_trace_structure_with_strict_matching(): void
188188 // Assert the trace structure with non-strict matching (should pass)
189189 $ this ->assertTraceStructure ($ this ->storage , $ expectedStructure , false );
190190
191- // Define the expected structure with all attributes
191+ // Define the expected structure with all attributes and fields
192192 $ expectedStructureStrict = [
193193 [
194194 'name ' => 'test-span ' ,
195+ 'kind ' => 0 , // Default kind
195196 'attributes ' => [
196197 'attribute.one ' => 'value1 ' ,
197198 'attribute.two ' => 42 ,
198199 'attribute.three ' => true ,
199200 ],
201+ 'events ' => [], // Empty events array
202+ 'children ' => [], // Empty children array
203+ 'status ' => [
204+ 'code ' => 'Unset ' , // Default status code
205+ 'description ' => '' , // Default status description
206+ ],
200207 ],
201208 ];
202209
@@ -682,6 +689,166 @@ public function test_trace_structure_diff_output_with_missing_nested_span(): voi
682689 }
683690 }
684691
692+ /**
693+ * Test that strict mode fails when actual span has extra attributes.
694+ */
695+ public function test_assert_fails_with_extra_attributes_in_strict_mode (): void
696+ {
697+ $ tracer = $ this ->tracerProvider ->getTracer ('test-tracer ' );
698+
699+ // Create a span with multiple attributes
700+ $ span = $ tracer ->spanBuilder ('test-span ' )
701+ ->startSpan ();
702+
703+ $ span ->setAttribute ('attribute.one ' , 'value1 ' );
704+ $ span ->setAttribute ('attribute.two ' , 42 );
705+ $ span ->setAttribute ('attribute.three ' , true );
706+
707+ $ span ->end ();
708+
709+ // Define expected structure with only a subset of attributes
710+ $ expectedStructure = [
711+ [
712+ 'name ' => 'test-span ' ,
713+ 'attributes ' => [
714+ 'attribute.one ' => 'value1 ' ,
715+ 'attribute.two ' => 42 ,
716+ ],
717+ ],
718+ ];
719+
720+ // Expect assertion to fail in strict mode
721+ $ this ->expectException (\PHPUnit \Framework \AssertionFailedError::class);
722+ $ this ->expectExceptionMessageMatches ('/No matching span found for expected span "test-span"/ ' );
723+
724+ $ this ->assertTraceStructure ($ this ->storage , $ expectedStructure , true );
725+ }
726+
727+ /**
728+ * Test that strict mode fails when actual span has a kind but expected doesn't.
729+ */
730+ public function test_assert_fails_with_extra_kind_in_strict_mode (): void
731+ {
732+ $ tracer = $ this ->tracerProvider ->getTracer ('test-tracer ' );
733+
734+ // Create a span with a specific kind
735+ $ span = $ tracer ->spanBuilder ('test-span ' )
736+ ->setSpanKind (SpanKind::KIND_SERVER )
737+ ->startSpan ();
738+
739+ $ span ->end ();
740+
741+ // Define expected structure without kind
742+ $ expectedStructure = [
743+ [
744+ 'name ' => 'test-span ' ,
745+ ],
746+ ];
747+
748+ // Expect assertion to fail in strict mode
749+ $ this ->expectException (\PHPUnit \Framework \AssertionFailedError::class);
750+ $ this ->expectExceptionMessageMatches ('/No matching span found for expected span "test-span"/ ' );
751+
752+ $ this ->assertTraceStructure ($ this ->storage , $ expectedStructure , true );
753+ }
754+
755+ /**
756+ * Test that strict mode fails when actual span has events but expected doesn't.
757+ */
758+ public function test_assert_fails_with_extra_events_in_strict_mode (): void
759+ {
760+ $ tracer = $ this ->tracerProvider ->getTracer ('test-tracer ' );
761+
762+ // Create a span with events
763+ $ span = $ tracer ->spanBuilder ('test-span ' )
764+ ->startSpan ();
765+
766+ $ span ->addEvent ('event-1 ' );
767+ $ span ->addEvent ('event-2 ' );
768+
769+ $ span ->end ();
770+
771+ // Define expected structure without events
772+ $ expectedStructure = [
773+ [
774+ 'name ' => 'test-span ' ,
775+ ],
776+ ];
777+
778+ // Expect assertion to fail in strict mode
779+ $ this ->expectException (\PHPUnit \Framework \AssertionFailedError::class);
780+ $ this ->expectExceptionMessageMatches ('/No matching span found for expected span "test-span"/ ' );
781+
782+ $ this ->assertTraceStructure ($ this ->storage , $ expectedStructure , true );
783+ }
784+
785+ /**
786+ * Test that strict mode fails when actual span has a non-default status but expected doesn't.
787+ */
788+ public function test_assert_fails_with_extra_status_in_strict_mode (): void
789+ {
790+ $ tracer = $ this ->tracerProvider ->getTracer ('test-tracer ' );
791+
792+ // Create a span with a non-default status
793+ $ span = $ tracer ->spanBuilder ('test-span ' )
794+ ->startSpan ();
795+
796+ $ span ->setStatus (StatusCode::STATUS_ERROR , 'Something went wrong ' );
797+
798+ $ span ->end ();
799+
800+ // Define expected structure without status
801+ $ expectedStructure = [
802+ [
803+ 'name ' => 'test-span ' ,
804+ ],
805+ ];
806+
807+ // Expect assertion to fail in strict mode
808+ $ this ->expectException (\PHPUnit \Framework \AssertionFailedError::class);
809+ $ this ->expectExceptionMessageMatches ('/No matching span found for expected span "test-span"/ ' );
810+
811+ $ this ->assertTraceStructure ($ this ->storage , $ expectedStructure , true );
812+ }
813+
814+ /**
815+ * Test that strict mode fails when actual span has children but expected doesn't.
816+ */
817+ public function test_assert_fails_with_extra_children_in_strict_mode (): void
818+ {
819+ $ tracer = $ this ->tracerProvider ->getTracer ('test-tracer ' );
820+
821+ // Create a root span
822+ $ rootSpan = $ tracer ->spanBuilder ('root-span ' )
823+ ->startSpan ();
824+
825+ // Activate the root span
826+ $ rootScope = $ rootSpan ->activate ();
827+
828+ try {
829+ // Create a child span
830+ $ childSpan = $ tracer ->spanBuilder ('child-span ' )
831+ ->startSpan ();
832+ $ childSpan ->end ();
833+ } finally {
834+ $ rootSpan ->end ();
835+ $ rootScope ->detach ();
836+ }
837+
838+ // Define expected structure without children
839+ $ expectedStructure = [
840+ [
841+ 'name ' => 'root-span ' ,
842+ ],
843+ ];
844+
845+ // Expect assertion to fail in strict mode
846+ $ this ->expectException (\PHPUnit \Framework \AssertionFailedError::class);
847+ $ this ->expectExceptionMessageMatches ('/No matching span found for expected span "root-span"/ ' );
848+
849+ $ this ->assertTraceStructure ($ this ->storage , $ expectedStructure , true );
850+ }
851+
685852 /**
686853 * Test asserting a trace structure using PHPUnit matchers.
687854 */
0 commit comments