using System.Diagnostics; using System.Linq; using FluentAssertions; using StellaOps.TestKit.Observability; using Xunit; namespace StellaOps.TestKit.Tests; public sealed partial class ObservabilityContractTests { [Fact] public void HasRequiredSpans_AllPresent_NoException() { using var source = new ActivitySource("TestSource"); using var capture = new OtelCapture("TestSource"); using (source.StartActivity("Span1")) { } using (source.StartActivity("Span2")) { } var act = () => OTelContractAssert.HasRequiredSpans(capture, "Span1", "Span2"); act.Should().NotThrow(); } [Fact] public void HasRequiredSpans_Missing_ThrowsContractViolation() { using var source = new ActivitySource("TestSource2"); using var capture = new OtelCapture("TestSource2"); using (source.StartActivity("Span1")) { } var act = () => OTelContractAssert.HasRequiredSpans(capture, "Span1", "MissingSpan"); act.Should().Throw() .WithMessage("*MissingSpan*"); } [Fact] public void SpanHasAttributes_AllPresent_NoException() { using var source = new ActivitySource("TestSource3"); using var capture = new OtelCapture("TestSource3"); using (var activity = source.StartActivity("TestSpan")) { activity?.SetTag("user_id", "123"); activity?.SetTag("tenant_id", "acme"); } var span = capture.CapturedActivities.First(); var act = () => OTelContractAssert.SpanHasAttributes(span, "user_id", "tenant_id"); act.Should().NotThrow(); } [Fact] public void SpanHasAttributes_Missing_ThrowsContractViolation() { using var source = new ActivitySource("TestSource4"); using var capture = new OtelCapture("TestSource4"); using (var activity = source.StartActivity("TestSpan")) { activity?.SetTag("user_id", "123"); } var span = capture.CapturedActivities.First(); var act = () => OTelContractAssert.SpanHasAttributes(span, "user_id", "missing_attr"); act.Should().Throw() .WithMessage("*missing_attr*"); } [Fact] public void AttributeCardinality_WithinThreshold_NoException() { using var source = new ActivitySource("TestSource5"); using var capture = new OtelCapture("TestSource5"); for (int i = 0; i < 5; i++) { using (var activity = source.StartActivity($"Span{i}")) { activity?.SetTag("status", i % 3 == 0 ? "ok" : "error"); } } var act = () => OTelContractAssert.AttributeCardinality(capture, "status", maxCardinality: 10); act.Should().NotThrow(); } }