151 lines
7.9 KiB
Markdown
151 lines
7.9 KiB
Markdown
# Testing Guide
|
|
|
|
Elsa uses unit, integration, component, and performance tests. The best test choice depends on what boundary you are changing.
|
|
|
|
The detailed internal testing strategy is [doc/qa/test-guidelines.md](../qa/test-guidelines.md). This page is a wiki-sized map.
|
|
|
|
## Test Folders
|
|
|
|
| Folder | Purpose |
|
|
| --- | --- |
|
|
| [test/unit](../../test/unit) | Isolated services, activities, converters, stores, validators, descriptors, and small logic. |
|
|
| [test/integration](../../test/integration) | In-process composition of workflow engine services, expressions, activities, runtime behavior, and module integration. |
|
|
| [test/component](../../test/component) | Host-level workflows, persistence-backed scenarios, HTTP workflows, clustered behavior, and lifecycle behavior. |
|
|
| [test/performance](../../test/performance) | Benchmark and throughput scenarios. |
|
|
|
|
Shared helpers:
|
|
|
|
- [Elsa.Testing.Shared](../../src/common/Elsa.Testing.Shared)
|
|
- [Elsa.Testing.Shared.Integration](../../src/common/Elsa.Testing.Shared.Integration)
|
|
- [Elsa.Testing.Shared.Component](../../src/common/Elsa.Testing.Shared.Component)
|
|
|
|
## Choosing A Test Type
|
|
|
|
| Change | Preferred test |
|
|
| --- | --- |
|
|
| Activity logic without persistence or scheduler | Unit test with `ActivityTestFixture`. |
|
|
| Expression evaluator/parser behavior | Unit test or language-specific integration test. |
|
|
| Workflow execution semantics | Integration test with workflow runner/test fixture. |
|
|
| Bookmarks, triggers, runtime dispatch, recovery | Integration test; component test if host lifecycle or persistence matters. |
|
|
| API endpoint shape or authorization | Unit/integration endpoint test if existing pattern exists; component test for host-level behavior. |
|
|
| EF Core store or migration | Provider-specific integration/component test. |
|
|
| HTTP workflows | Component test under HTTP workflow scenarios. |
|
|
| Structured log SQLite persistence | SQLite integration test project. |
|
|
| Console log capture, buffering, or endpoints | `Elsa.Diagnostics.ConsoleLogs.UnitTests` or `Elsa.Diagnostics.ConsoleLogs.IntegrationTests`. |
|
|
| OpenTelemetry diagnostics collection or endpoints | `Elsa.Diagnostics.OpenTelemetry.UnitTests` or `Elsa.Diagnostics.OpenTelemetry.IntegrationTests`. |
|
|
| Dashboard API endpoints or aggregation logic | `Elsa.Dashboard.Api.UnitTests`. |
|
|
| AI/Weaver abstractions or host behavior | `Elsa.AI.Abstractions.UnitTests`, `Elsa.AI.Host.UnitTests`, or `Elsa.AI.IntegrationTests`. |
|
|
| Persistence vNext store or physicalization logic | `Elsa.Persistence.VNext.UnitTests`. |
|
|
|
|
## Useful Commands
|
|
|
|
Restore first when starting from a clean checkout or after dependency changes:
|
|
|
|
```bash
|
|
./build.sh Restore --ignore-failed-sources
|
|
```
|
|
|
|
Build the solution with direct `dotnet` commands:
|
|
|
|
```bash
|
|
dotnet restore Elsa.sln --ignore-failed-sources
|
|
dotnet build Elsa.sln --no-restore
|
|
```
|
|
|
|
Run all tests with direct `dotnet` commands:
|
|
|
|
```bash
|
|
dotnet restore Elsa.sln --ignore-failed-sources
|
|
dotnet test Elsa.sln --no-restore
|
|
```
|
|
|
|
Run the NUKE test target after the resilient restore:
|
|
|
|
```bash
|
|
./build.sh Test
|
|
```
|
|
|
|
Run targeted projects:
|
|
|
|
```bash
|
|
dotnet restore test/unit/Elsa.Workflows.Core.UnitTests/Elsa.Workflows.Core.UnitTests.csproj --ignore-failed-sources
|
|
dotnet test test/unit/Elsa.Workflows.Core.UnitTests/Elsa.Workflows.Core.UnitTests.csproj --no-restore
|
|
|
|
dotnet restore test/integration/Elsa.Workflows.IntegrationTests/Elsa.Workflows.IntegrationTests.csproj --ignore-failed-sources
|
|
dotnet test test/integration/Elsa.Workflows.IntegrationTests/Elsa.Workflows.IntegrationTests.csproj --no-restore
|
|
|
|
dotnet restore test/component/Elsa.Workflows.ComponentTests/Elsa.Workflows.ComponentTests.csproj --ignore-failed-sources
|
|
dotnet test test/component/Elsa.Workflows.ComponentTests/Elsa.Workflows.ComponentTests.csproj --no-restore
|
|
|
|
dotnet restore test/integration/Elsa.Diagnostics.StructuredLogs.Persistence.Sqlite.IntegrationTests/Elsa.Diagnostics.StructuredLogs.Persistence.Sqlite.IntegrationTests.csproj --ignore-failed-sources
|
|
dotnet test test/integration/Elsa.Diagnostics.StructuredLogs.Persistence.Sqlite.IntegrationTests/Elsa.Diagnostics.StructuredLogs.Persistence.Sqlite.IntegrationTests.csproj --no-restore
|
|
```
|
|
|
|
Run ElsaScript DSL tests:
|
|
|
|
```bash
|
|
./run-dsl-tests.sh
|
|
```
|
|
|
|
## Activity Tests
|
|
|
|
Use `ActivityTestFixture` from [Elsa.Testing.Shared](../../src/common/Elsa.Testing.Shared). Activity tests should assert activity outputs, variables, scheduled child activities, outcomes, and fault behavior without needing a host.
|
|
|
|
Examples live in:
|
|
|
|
- [test/unit/Elsa.Activities.UnitTests](../../test/unit/Elsa.Activities.UnitTests)
|
|
- [test/unit/Elsa.Workflows.Core.UnitTests](../../test/unit/Elsa.Workflows.Core.UnitTests)
|
|
|
|
## Workflow Integration Tests
|
|
|
|
Use integration helpers when activity behavior depends on workflow runner behavior, variables, activity outputs, expressions, or bookmarks.
|
|
|
|
Examples:
|
|
|
|
- [test/integration/Elsa.Workflows.IntegrationTests](../../test/integration/Elsa.Workflows.IntegrationTests)
|
|
- [test/integration/Elsa.Activities.IntegrationTests](../../test/integration/Elsa.Activities.IntegrationTests)
|
|
- [test/integration/Elsa.JavaScript.IntegrationTests](../../test/integration/Elsa.JavaScript.IntegrationTests)
|
|
|
|
## Component Tests
|
|
|
|
Component tests use host fixtures. The base class is [AppComponentTest](../../test/component/Elsa.Workflows.ComponentTests/Helpers/Abstractions/AppComponentTest.cs). It creates a scope, pushes the default tenant context, tracks in-flight workflows, and waits for them to idle on dispose.
|
|
|
|
Fixture landmarks:
|
|
|
|
- [App](../../test/component/Elsa.Workflows.ComponentTests/Helpers/Fixtures/App.cs)
|
|
- [Cluster](../../test/component/Elsa.Workflows.ComponentTests/Helpers/Fixtures/Cluster.cs)
|
|
- [WorkflowServer](../../test/component/Elsa.Workflows.ComponentTests/Helpers/Fixtures/WorkflowServer.cs)
|
|
- [Infrastructure](../../test/component/Elsa.Workflows.ComponentTests/Helpers/Fixtures/Infrastructure.cs)
|
|
|
|
Use component tests when host lifecycle, HTTP server behavior, actual persistence, distributed runtime behavior, or multiple services working together are essential to the assertion.
|
|
|
|
## Structured Log Tests
|
|
|
|
Structured log tests are split by layer:
|
|
|
|
- [test/unit/Elsa.Diagnostics.StructuredLogs.UnitTests](../../test/unit/Elsa.Diagnostics.StructuredLogs.UnitTests)
|
|
- [test/integration/Elsa.Diagnostics.StructuredLogs.IntegrationTests](../../test/integration/Elsa.Diagnostics.StructuredLogs.IntegrationTests)
|
|
- [test/unit/Elsa.Diagnostics.StructuredLogs.Persistence.Relational.UnitTests](../../test/unit/Elsa.Diagnostics.StructuredLogs.Persistence.Relational.UnitTests)
|
|
- [test/integration/Elsa.Diagnostics.StructuredLogs.Persistence.Sqlite.IntegrationTests](../../test/integration/Elsa.Diagnostics.StructuredLogs.Persistence.Sqlite.IntegrationTests)
|
|
|
|
This mirrors the architecture: core capture and API behavior should not require SQLite; SQLite tests should prove durability, migrations, retention, timestamp storage, queue overflow, and filtering.
|
|
|
|
## Console Log Tests
|
|
|
|
Console log tests are split by layer:
|
|
|
|
- [test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests](../../test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests): capture, filtering, redaction, buffering, source registry, and naming.
|
|
- [test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests](../../test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests): module registration, endpoint authorization, SignalR hub, and recent query behavior.
|
|
|
|
Run targeted console log tests when touching `Elsa.Diagnostics.ConsoleLogs`.
|
|
|
|
## Good Test Hygiene
|
|
|
|
- Prefer targeted project tests while iterating.
|
|
- Add a regression test for a bug before or alongside the fix.
|
|
- Keep arrange/setup in constructors or small helpers when it repeats.
|
|
- Use `IAsyncDisposable` or xUnit async lifetime patterns for async teardown.
|
|
- Avoid sleeps when a deterministic signal or store assertion is available.
|
|
- For multi-targeting issues, consider whether all target frameworks need coverage.
|
|
- When changing shared runtime or persistence behavior, finish with a broader build/test run if feasible.
|