with one click
test
// Write and run tests for the workflow engine. Use when creating tests, adding test coverage, scaffolding test files, or running the test suite.
// Write and run tests for the workflow engine. Use when creating tests, adding test coverage, scaffolding test files, or running the test suite.
Norsk tekstforfatter og redaktør for Digdir: klarspråk, AI-markører, anglisismer, fagtermer, mikrotekst.
Rebase a stacked PR onto main after its parent was squash-merged, using `git rebase --onto` to skip already-merged commits. Use when rebasing a stacked or dependent PR, handling a squash-merged parent PR, or recovering from empty commits or spurious conflicts after `git rebase main`.
Skill for reviewing text content - error messages, labels, help texts and tone of voice. Use this skill only when directly invoked.
Manage the workflow engine's Docker Compose stack. Use when starting, stopping, rebuilding containers, or resetting the database.
Format C# files with CSharpier and verify the build passes. Use when formatting code, fixing build errors from formatting, or before committing changes.
Run k6 load tests against the workflow engine. Use when performance testing, stress testing, or benchmarking.
| name | test |
| description | Write and run tests for the workflow engine. Use when creating tests, adding test coverage, scaffolding test files, or running the test suite. |
When writing or running tests, follow these guidelines.
dotnet testdotnet test tests/WorkflowEngine.<Project>.Testsdotnet test --filter "FullyQualifiedName~ClassName.MethodName"dotnet csharpier format <file> on new/modified test files before finishing.| Project | Type | Fixture | Dependencies |
|---|---|---|---|
Api.Tests | Unit | WorkflowEngineTestFixture.Create() per test | Moq |
Models.Tests | Unit | None | — |
Resilience.Tests | Unit | None | — |
Data.Tests | Unit | None | — |
Repository.Tests | Repository (real DB) | PostgresFixture via collection | Testcontainers.PostgreSql |
Integration.Tests | End-to-end | EngineAppFixture via collection | Testcontainers, WireMock, WebApplicationFactory, Verify |
// Arrange, // Act, // Assert comment markers.[Theory] with [InlineData] or [MemberData] (returning TheoryData<>) when inputs vary but logic is the same.[Fact] only for single meaningful scenarios with no parameterisation.MethodName_Scenario_ExpectedResult.TestContext.Current.CancellationToken to async calls that accept a CancellationToken. This includes Task.Delay, HttpClient methods, EF queries, polling loops, etc. xUnit v3 analyzer rule xUnit1051 enforces this.public sealed class MyServiceTests
{
[Fact]
public async Task MethodName_Scenario_ExpectedResult()
{
// Arrange
using var fixture = WorkflowEngineTestFixture.Create();
// setup mocks via fixture.HttpHandler, fixture.ServiceProvider, etc.
// Act
var result = await sut.Method(CancellationToken.None);
// Assert
Assert.Equal(expected, result);
}
}
[Collection(PostgresCollection.Name)]
public sealed class MyRepositoryTests(PostgresFixture fixture) : IAsyncLifetime
{
public async ValueTask InitializeAsync() => await fixture.ResetAsync();
public ValueTask DisposeAsync() => ValueTask.CompletedTask;
[Fact]
public async Task MethodName_Scenario_ExpectedResult()
{
// Arrange
await using var context = fixture.CreateDbContext();
var repo = fixture.CreateRepository(context);
// Act
// ...
// Assert
// ...
}
}
Integration tests use partial classes split by concern. To add tests to an existing concern, add to the appropriate partial file (e.g., EngineTests.Insert.cs). To add a new concern, create a new partial file.
// EngineTests.MyConcern.cs
public partial class EngineTests
{
[Fact]
public async Task MyConcern_Scenario_ExpectedResult()
{
// Arrange
var request = _testHelpers.CreateEnqueueRequest(
_testHelpers.CreateWorkflow("wf", WorkflowType.Generic, [...steps...]),
lockToken: InstanceLockToken
);
// Act
var response = await _client.Enqueue(_instanceGuid, request);
// Assert
Assert.Equal(HttpStatusCode.Accepted, response.StatusCode);
}
}
The base EngineTests.cs class handles fixture injection, IAsyncLifetime, and shared helpers:
_client — EngineApiClient for the test host_testHelpers — builders for steps, workflows, enqueue requests_instanceGuid — fresh GUID per testInstanceLockToken — constant from fixtureUsed in integration tests for response shape validation:
[Fact]
public async Task Response_Shape_IsCorrect()
{
// Arrange + Act
var response = await _client.GetWorkflow(_instanceGuid, workflowId);
var json = await response.Content.ReadAsStringAsync();
// Assert
await Verify(json).UseMethodName("Response_Shape_IsCorrect");
}
tests/WorkflowEngine.Integration.Tests/.snapshots/ModuleInitializer: databaseId, createdAt, updatedAt, backoffUntil, traceId, inline GUIDsVerifierSettings.AutoVerify)postgres:18 containers (Repository.Tests, Integration.Tests)WebApplicationFactory (Integration.Tests)[Collection(...)].IAsyncLifetime on test classes for per-test setup/teardown (typically calls fixture.ResetAsync()).