ワンクリックで
testing-strategy
Test organization, FsCheck property-based testing, Best.Conventional convention tests. Use when writing or modifying tests.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Test organization, FsCheck property-based testing, Best.Conventional convention tests. Use when writing or modifying tests.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
| name | testing-strategy |
| description | Test organization, FsCheck property-based testing, Best.Conventional convention tests. Use when writing or modifying tests. |
| user-invocable | false |
Tests/
├── Domain/ # Entity and value object tests
├── Application/ # Command/query handler tests
├── Infrastructure/ # Outbox, processor tests (Moq + InMemory DbContext)
├── Integration/ # Full API integration tests (Testcontainers)
├── Conventions/ # Architectural rule enforcement
├── Fuzzing/ # Property-based tests (FsCheck)
└── TestBuilders/ # Test data builders
FsCheck 3.3.3 with FsCheck.Xunit 3.3.3 integration. Instead of hand-picked test values, FsCheck generates hundreds of random inputs to verify domain invariants hold universally.
Key properties tested:
+n then -n restores original), over-deduction throwsTotalIncGst == UnitIncGst * Qty), GST rate bounds, ID/quantity validationUsage: Tests use [Property] attribute (FsCheck.Xunit) instead of [Fact]. FsCheck automatically shrinks failing inputs to minimal counterexamples.
Architectural Rule Enforcement with Best.Conventional (Conventions/ directory: ApiConventionTests, CachingConventionTests, CqrsConventionTests, DapperConventionTests, DomainConventionTests, NamingConventionTests, PersistenceConventionTests).
Approach: Use built-in conventions where possible. For structural checks not covered by built-ins, create custom conventions extending ConventionSpecification (from Conventional.Conventions namespace).
Naming — Convention.NameMustEndWith:
endpointTypes.MustConformTo(Convention.NameMustEndWith("Endpoints"));
commandTypes.MustConformTo(Convention.NameMustEndWith("Command"));
Encapsulation — Convention.PropertiesMustHavePrivateSetters / PropertiesMustHavePublicGetters:
entityTypes.MustConformTo(Convention.PropertiesMustHavePrivateSetters);
dtoTypes.MustConformTo(Convention.PropertiesMustHavePublicGetters);
CQRS Data Access — Convention.MustNotTakeADependencyOn:
commandHandlers.MustConformTo(Convention.MustNotTakeADependencyOn(typeof(IDbConnection), "..."));
queryHandlers.MustConformTo(Convention.MustNotTakeADependencyOn(typeof(ApplicationDbContext), "..."));
CQRS Handler Wiring — Convention.RequiresACorrespondingImplementationOf:
commandsWithResponse.MustConformTo(Convention.RequiresACorrespondingImplementationOf(
typeof(IRequestHandler<,>), allTypes));
Domain Integrity — Convention.MustHaveANonPublicDefaultConstructor + custom specs:
entityTypes.MustConformTo(Convention.MustHaveANonPublicDefaultConstructor);
valueObjectTypes.MustConformTo(new MustOverrideEqualsAndGetHashCodeConvention());
Safety — Convention.VoidMethodsMustNotBeAsync, Convention.MustNotResolveCurrentTimeViaDateTime
Dapper SQL Quality — Custom IL inspection convention (DapperConventionTests):
ldstr opcodes (0x72) to extract SQL string literalsRegex(@"SELECT\s+\*") to prevent SELECT *COUNT(*) and other non-column-expanding uses of *For checks covered by Best.Conventional built-ins, use Convention.* directly. For structural/wiring checks, extend ConventionSpecification:
private class MyCustomConvention : ConventionSpecification
{
protected override string FailureMessage => "description of what's expected";
public override ConventionResult IsSatisfiedBy(Type type)
{
return /* check passes */
? ConventionResult.Satisfied(type.FullName!)
: ConventionResult.NotSatisfied(type.FullName!, "specific failure reason");
}
}
The main test project uses WebApplicationFactory<IApiMarker> with Testcontainers for PostgreSQL and Respawn for per-test cleanup. This is the workhorse for API endpoint testing:
A separate test project for end-to-end distributed system testing. Spins up the full AppHost (PostgreSQL, Service Bus emulator, API, Functions, DbMigrator) using DistributedApplicationTestingBuilder:
DistributedApplicationTestingBuilder manages all container lifecycle — no manual Docker setupapp.CreateHttpClient("api") to get a properly configured client[Trait("Category", "Aspire")] to exclude from fast CI runsvar appHost = await DistributedApplicationTestingBuilder
.CreateAsync<Projects.StarterApp_AppHost>();
await using var app = await appHost.BuildAsync();
await app.StartAsync();
var httpClient = app.CreateHttpClient("api");
Shell script (scripts/smoke-test.sh) for verifying a live deployment. Complements integration tests — integration tests verify correctness in-process, smoke tests verify the deployed artifact works end-to-end.
# BASE_URL is required — pass it positionally or via the SMOKE_BASE_URL env var.
# With neither set, the script prints usage and exits 2 (no baked-in default).
./scripts/smoke-test.sh https://localhost:7286 # Aspire (API URL from the dashboard)
SMOKE_BASE_URL=https://localhost:7286 ./scripts/smoke-test.sh
What it covers (25 assertions):
Design decisions:
curl — zero dependencies, runs anywhereTestcontainers for Realistic Testing:
public class ApiTestFixture : IAsyncLifetime
{
private readonly PostgreSqlContainer _postgresContainer;
private WebApplicationFactory<Program> _factory;
public async Task InitializeAsync()
{
await _postgresContainer.StartAsync();
_factory = new WebApplicationFactory<Program>()
.WithWebHostBuilder(builder =>
{
builder.ConfigureServices(services =>
{
services.Configure<ConnectionStrings>(options =>
{
options.DefaultConnection = _postgresContainer.GetConnectionString();
});
});
});
}
}
Consistency reports: the advisory cohort reports (structural distances + per-feature divergence) are written to docs/_local/consistency-*.txt on every test run — read them there when reviewing structural drift; do not gate builds on distances.
Minimal API endpoint patterns with IEndpointDefinition, filters, error handling. Use when creating or modifying API endpoints.
Perform a thorough architecture review of a .NET project examining structure, maintainability, clarity, robustness, and goal achievement. Use when the user asks to review, audit, or examine a codebase.
CQRS implementation — commands use EF Core DbContext, queries use Dapper IDbConnection. Use when implementing or modifying command/query handlers.
Perform a thorough architecture review of a .NET project examining structure, maintainability, clarity, robustness, and goal achievement. Use when the user asks to review, audit, or examine a codebase.
EF Core configuration, value object embedding, DbUp migrations, Aspire setup. Use when modifying database schema, migrations, or data access code.
Domain entity and value object patterns — private setters, factory methods, Reconstitute. Use when creating or modifying domain models.