Fix build and code structure improvements. New but essential UI functionality. CI improvements. Documentation improvements. AI module improvements.
This commit is contained in:
@@ -0,0 +1,153 @@
|
||||
using System.Reflection;
|
||||
using Xunit;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace StellaOps.Infrastructure.Postgres.Testing;
|
||||
|
||||
/// <summary>
|
||||
/// Marks a test method as a migration test that requires database isolation.
|
||||
/// When applied, the test will automatically truncate all tables before execution.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Use this attribute on test methods that modify database state and need isolation
|
||||
/// from other tests. The attribute ensures a clean database state by truncating
|
||||
/// all tables in the test schema before the test runs.
|
||||
///
|
||||
/// Example:
|
||||
/// <code>
|
||||
/// [MigrationTest]
|
||||
/// public async Task Should_Insert_Record_Successfully()
|
||||
/// {
|
||||
/// // Database tables are empty when this test starts
|
||||
/// await _fixture.ExecuteSqlAsync("INSERT INTO ...");
|
||||
/// }
|
||||
/// </code>
|
||||
/// </remarks>
|
||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
|
||||
public sealed class MigrationTestAttribute : BeforeAfterTestAttribute
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether to truncate tables before the test runs.
|
||||
/// Default is true.
|
||||
/// </summary>
|
||||
public bool TruncateBefore { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether to truncate tables after the test runs.
|
||||
/// Default is false (let the next test with TruncateBefore handle cleanup).
|
||||
/// </summary>
|
||||
public bool TruncateAfter { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets specific table names to truncate. If null or empty, all tables are truncated.
|
||||
/// </summary>
|
||||
public string[]? Tables { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Called before the test method runs.
|
||||
/// </summary>
|
||||
public override void Before(MethodInfo methodUnderTest)
|
||||
{
|
||||
if (!TruncateBefore)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to find the fixture from the test class
|
||||
var testClass = methodUnderTest.DeclaringType;
|
||||
if (testClass is null) return;
|
||||
|
||||
// Look for a field or property of type PostgresIntegrationFixture
|
||||
var fixtureField = testClass
|
||||
.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)
|
||||
.FirstOrDefault(f => typeof(PostgresIntegrationFixture).IsAssignableFrom(f.FieldType));
|
||||
|
||||
var fixtureProperty = testClass
|
||||
.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)
|
||||
.FirstOrDefault(p => typeof(PostgresIntegrationFixture).IsAssignableFrom(p.PropertyType));
|
||||
|
||||
// Note: We can't access the instance here in xUnit's BeforeAfterTestAttribute
|
||||
// This is a limitation - the actual truncation needs to be done via a different mechanism
|
||||
// See MigrationTestFixture for a better approach
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called after the test method runs.
|
||||
/// </summary>
|
||||
public override void After(MethodInfo methodUnderTest)
|
||||
{
|
||||
// Cleanup is optional and typically not needed
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A test fixture wrapper that provides automatic table truncation between tests.
|
||||
/// </summary>
|
||||
/// <typeparam name="TFixture">The underlying PostgreSQL integration fixture type.</typeparam>
|
||||
public abstract class MigrationTestBase<TFixture> : IAsyncLifetime
|
||||
where TFixture : PostgresIntegrationFixture
|
||||
{
|
||||
private readonly TFixture _fixture;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the underlying test fixture.
|
||||
/// </summary>
|
||||
protected TFixture Fixture => _fixture;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the connection string for direct database access.
|
||||
/// </summary>
|
||||
protected string ConnectionString => _fixture.ConnectionString;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the schema name for this test.
|
||||
/// </summary>
|
||||
protected string SchemaName => _fixture.SchemaName;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new migration test base with the specified fixture.
|
||||
/// </summary>
|
||||
protected MigrationTestBase(TFixture fixture)
|
||||
{
|
||||
_fixture = fixture ?? throw new ArgumentNullException(nameof(fixture));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called before each test. Override to customize initialization.
|
||||
/// By default, truncates all tables for test isolation.
|
||||
/// </summary>
|
||||
public virtual async Task InitializeAsync()
|
||||
{
|
||||
await _fixture.TruncateAllTablesAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called after each test. Override to customize cleanup.
|
||||
/// </summary>
|
||||
public virtual Task DisposeAsync()
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes raw SQL for test setup.
|
||||
/// </summary>
|
||||
protected Task ExecuteSqlAsync(string sql, CancellationToken cancellationToken = default)
|
||||
=> _fixture.ExecuteSqlAsync(sql, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Collection definition for migration tests that require database isolation.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Apply [Collection(MigrationTestCollection.Name)] to test classes that share a database fixture.
|
||||
/// Tests within the collection run sequentially to avoid database conflicts.
|
||||
/// </remarks>
|
||||
public static class MigrationTestCollection
|
||||
{
|
||||
/// <summary>
|
||||
/// The collection name for migration tests.
|
||||
/// </summary>
|
||||
public const string Name = "MigrationTests";
|
||||
}
|
||||
@@ -14,8 +14,8 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Testcontainers.PostgreSql" Version="4.1.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.3" />
|
||||
<PackageReference Include="Testcontainers.PostgreSql" />
|
||||
<PackageReference Include="xunit" PrivateAssets="all" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user