3.3 KiB
3.3 KiB
Better Testing Strategy - Code Samples
Source advisory: docs/product/advisories/22-Dec-2026 - Better testing strategy.md
Note: These samples are carried over verbatim for reference and should remain offline-friendly and deterministic.
Minimal primitives to standardize immediately
public static class TestCategories
{
public const string Unit = "Unit";
public const string Property = "Property";
public const string Snapshot = "Snapshot";
public const string Integration = "Integration";
public const string Contract = "Contract";
public const string Security = "Security";
public const string Performance = "Performance";
public const string Live = "Live"; // opt-in only
}
Property test example (FsCheck-style)
using Xunit;
using FsCheck;
using FsCheck.Xunit;
public sealed class VersionComparisonProperties
{
[Property(Arbitrary = new[] { typeof(Generators) })]
[Trait("Category", "Unit")]
[Trait("Category", "Property")]
public void Compare_is_antisymmetric(SemVer a, SemVer b)
{
var ab = VersionComparer.Compare(a, b);
var ba = VersionComparer.Compare(b, a);
Assert.Equal(Math.Sign(ab), -Math.Sign(ba));
}
private static class Generators
{
public static Arbitrary<SemVer> SemVer() =>
Arb.From(Gen.Elements(
new SemVer(0,0,0),
new SemVer(1,0,0),
new SemVer(1,2,3),
new SemVer(10,20,30)
));
}
}
Canonical JSON determinism assertion
public static class DeterminismAssert
{
public static void CanonicalJsonStable<T>(T value, string expectedSha256)
{
byte[] canonical = CanonicalJson.SerializeToUtf8Bytes(value); // your library
string actual = Convert.ToHexString(SHA256.HashData(canonical)).ToLowerInvariant();
Assert.Equal(expectedSha256, actual);
}
}
Postgres fixture skeleton (Testcontainers)
public sealed class PostgresFixture : IAsyncLifetime
{
public string ConnectionString => _container.GetConnectionString();
private readonly PostgreSqlContainer _container =
new PostgreSqlBuilder().WithImage("postgres:16").Build();
public async Task InitializeAsync()
{
await _container.StartAsync();
await ApplyMigrationsAsync(ConnectionString);
}
public async Task DisposeAsync() => await _container.DisposeAsync();
private static async Task ApplyMigrationsAsync(string cs)
{
// call your migration runner for the module under test
}
}
OTel trace capture assertion
public sealed class OtelCapture : IDisposable
{
private readonly List<Activity> _activities = new();
private readonly ActivityListener _listener;
public OtelCapture()
{
_listener = new ActivityListener
{
ShouldListenTo = _ => true,
Sample = (ref ActivityCreationOptions<ActivityContext> _) => ActivitySamplingResult.AllData,
ActivityStopped = a => _activities.Add(a)
};
ActivitySource.AddActivityListener(_listener);
}
public void AssertHasSpan(string name) =>
Assert.Contains(_activities, a => a.DisplayName == name);
public void Dispose() => _listener.Dispose();
}