Skip to content

Commit 2224328

Browse files
committed
tests
1 parent 255d22e commit 2224328

22 files changed

+432
-263
lines changed

AGENTS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ Current local `AGENTS.md` files:
174174
- [src/PrompterOne.Core/AGENTS.md](./src/PrompterOne.Core/AGENTS.md)
175175
- [src/PrompterOne.Shared/AGENTS.md](./src/PrompterOne.Shared/AGENTS.md)
176176
- [tests/PrompterOne.Core.Tests/AGENTS.md](./tests/PrompterOne.Core.Tests/AGENTS.md)
177+
- [tests/PrompterOne.Testing/AGENTS.md](./tests/PrompterOne.Testing/AGENTS.md)
177178
- [tests/PrompterOne.Web.Tests/AGENTS.md](./tests/PrompterOne.Web.Tests/AGENTS.md)
178179
- [tests/PrompterOne.Web.UITests/AGENTS.md](./tests/PrompterOne.Web.UITests/AGENTS.md)
179180

@@ -284,6 +285,8 @@ Local `AGENTS.md` files may tighten these values, but they must not loosen them
284285
- Do not use mocks, fakes, stubs, or service doubles in verification.
285286
- Exercise internal and external dependencies through real containers, test instances, or sandbox environments that match the real contract.
286287
- Flaky tests are failures. Fix the cause.
288+
- Do not hide multiple verification scenarios inside one test with a `foreach`; split them into separate TUnit data-driven test cases so failures stay isolated and the runner can schedule the cases independently.
289+
- Supporting TUnit suites should use environment-aware parallel limits: cap CI worker counts lower than local runs, and keep timer-, storage-, or culture-mutation-heavy classes isolated when they prove flaky under suite-wide parallelism.
287290
- Changed production code MUST reach at least 80% line coverage, and at least 70% branch coverage where branch coverage is available.
288291
- Critical flows and public contracts MUST reach at least 90% line coverage with explicit success and failure assertions.
289292
- Repository or module coverage must not decrease without an explicit written exception. Coverage after the change must stay at least at the previous baseline or improve.

PrompterOne.slnx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
<Project Path="src/PrompterOne.TpsSdk/PrompterOne.TpsSdk.csproj" />
77
</Folder>
88
<Folder Name="/tests/">
9+
<Project Path="tests/PrompterOne.Testing/PrompterOne.Testing.csproj" />
910
<Project Path="tests/PrompterOne.Web.Tests/PrompterOne.Web.Tests.csproj" />
1011
<Project Path="tests/PrompterOne.Web.UITests/PrompterOne.Web.UITests.csproj" />
1112
<Project Path="tests/PrompterOne.Core.Tests/PrompterOne.Core.Tests.csproj" />

docs/Architecture.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ flowchart LR
5050
Shared["src/PrompterOne.Shared<br/>Razor pages, layout, CSS, JS interop"]
5151
Core["src/PrompterOne.Core<br/>TPS, RSVP, workspace, media, streaming"]
5252
Docs["docs/<br/>Architecture + TPS reference + feature docs"]
53-
Tests["tests/*<br/>TUnit + bUnit + Playwright"]
53+
Tests["tests/*<br/>TUnit + bUnit + Playwright + shared test support"]
5454
5555
App --> Shared
5656
Shared --> Core
@@ -65,7 +65,8 @@ flowchart LR
6565

6666
- `src/PrompterOne.Shared` keeps routed UI in feature slices: `AppShell`, `Diagnostics`, `Editor`, `Library`, `Learn`, `Teleprompter`, `GoLive`, `Settings`, and `Media`.
6767
- `src/PrompterOne.Core` keeps host-neutral behavior in matching domain slices: `Tps`, `Editor`, `Workspace`, `Library`, `Rsvp`, `Media`, `Streaming`, and `Localization`.
68-
- `tests/PrompterOne.Core.Tests`, `tests/PrompterOne.Web.Tests`, and `tests/PrompterOne.Web.UITests` mirror those feature slices and reserve `Support` or `Infrastructure` for shared harness code.
68+
- `tests/PrompterOne.Core.Tests`, `tests/PrompterOne.Web.Tests`, and `tests/PrompterOne.Web.UITests` mirror those feature slices.
69+
- `tests/PrompterOne.Testing` owns reusable test assertions and runner configuration shared across multiple test projects.
6970

7071
## Design And Structure Principles
7172

@@ -530,10 +531,13 @@ sequenceDiagram
530531

531532
```mermaid
532533
flowchart LR
534+
TestSupport["tests/PrompterOne.Testing"]
533535
CoreTests["tests/PrompterOne.Core.Tests"]
534536
AppTests["tests/PrompterOne.Web.Tests"]
535537
UiTests["tests/PrompterOne.Web.UITests"]
536538
539+
CoreTests --> TestSupport
540+
AppTests --> TestSupport
537541
CoreTests --> Core["src/PrompterOne.Core"]
538542
AppTests --> Shared["src/PrompterOne.Shared"]
539543
UiTests --> App["src/PrompterOne.Web"]
@@ -544,6 +548,7 @@ flowchart LR
544548
- `PrompterOne.Core.Tests`: domain correctness and regression tests grouped by core slice plus `Support/`
545549
- `PrompterOne.Web.Tests`: bUnit coverage grouped by routed feature slice plus `Support/`
546550
- `PrompterOne.Web.UITests`: Playwright browser flows grouped by browser feature slice plus `Infrastructure/`, `Scenarios/`, `Media/`, and `Support/`
551+
- `PrompterOne.Testing`: shared test-only infrastructure such as assertion adapters and environment-aware runner limits
547552

548553
## Constraints
549554

tests/PrompterOne.Core.Tests/PrompterOne.Core.Tests.csproj

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,12 @@
88
</PropertyGroup>
99

1010
<ItemGroup>
11-
<PackageReference Include="Shouldly" />
1211
<PackageReference Include="TUnit" />
1312
</ItemGroup>
1413

15-
<ItemGroup>
16-
<Compile Include="..\Shared\ShouldlyAssert.cs" Link="Support\ShouldlyAssert.cs" />
17-
</ItemGroup>
18-
1914
<ItemGroup>
2015
<ProjectReference Include="..\..\src\PrompterOne.Core\PrompterOne.Core.csproj" />
16+
<ProjectReference Include="..\PrompterOne.Testing\PrompterOne.Testing.csproj" />
2117
</ItemGroup>
2218

2319
</Project>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using PrompterOne.Testing;
2+
3+
[assembly: ParallelLimiter<PrompterOne.Core.Tests.MaxParallelTestsForPipeline>]
4+
5+
namespace PrompterOne.Core.Tests;
6+
7+
/// <summary>
8+
/// Limits parallel test execution to reduce resource contention in CI.
9+
/// </summary>
10+
public sealed class MaxParallelTestsForPipeline : EnvironmentAwareParallelLimitBase
11+
{
12+
protected override int LocalLimit { get; } = 6;
13+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# AGENTS.md
2+
3+
## Project Purpose
4+
5+
`PrompterOne.Testing` is the shared test-support library for reusable assertion helpers, runner configuration, and cross-project test infrastructure.
6+
7+
## Entry Points
8+
9+
- `ShouldlyAssert.cs`
10+
- `EnvironmentAwareParallelLimitBase.cs`
11+
12+
## Boundaries
13+
14+
- Keep only reusable test infrastructure here; do not move feature-specific test cases or app behavior assertions into this project.
15+
- Shared helpers must stay test-only and must not leak into production projects.
16+
- Prefer stable low-level helpers that reduce duplication across multiple test projects.
17+
18+
## Project-Local Commands
19+
20+
- `dotnet build ./tests/PrompterOne.Testing/PrompterOne.Testing.csproj`
21+
22+
## Applicable Skills
23+
24+
- no special skill is required; use root repo rules and nearest consuming test-project rules
25+
26+
## Local Risks Or Protected Areas
27+
28+
- Shared helpers affect multiple suites at once; keep API changes minimal and rerun every consuming suite after edits.
29+
- Do not turn this project into a dumping ground for feature-specific assertions or fixtures.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using TUnit.Core.Interfaces;
2+
3+
namespace PrompterOne.Testing;
4+
5+
/// <summary>
6+
/// Provides environment-aware parallel test limits using standard CI markers.
7+
/// </summary>
8+
public abstract class EnvironmentAwareParallelLimitBase : IParallelLimit
9+
{
10+
private const string AzurePipelinesEnv = "TF_BUILD";
11+
private const string CiEnv = "CI";
12+
private const string GitHubActionsEnv = "GITHUB_ACTIONS";
13+
private const string NumericTrueValue = "1";
14+
15+
protected virtual int CiLimit { get; } = 4;
16+
protected virtual int LocalLimit { get; } = 6;
17+
18+
public int Limit => ResolveLimit();
19+
20+
protected int ResolveLimit() =>
21+
IsCiEnvironment()
22+
? CiLimit
23+
: LocalLimit;
24+
25+
private static bool IsCiEnvironment() =>
26+
IsEnabled(Environment.GetEnvironmentVariable(CiEnv))
27+
|| IsEnabled(Environment.GetEnvironmentVariable(AzurePipelinesEnv))
28+
|| IsEnabled(Environment.GetEnvironmentVariable(GitHubActionsEnv));
29+
30+
private static bool IsEnabled(string? value)
31+
{
32+
if (string.IsNullOrWhiteSpace(value))
33+
{
34+
return false;
35+
}
36+
37+
return string.Equals(value, bool.TrueString, StringComparison.OrdinalIgnoreCase)
38+
|| string.Equals(value, NumericTrueValue, StringComparison.OrdinalIgnoreCase);
39+
}
40+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<IsPackable>false</IsPackable>
5+
<TUnitImplicitUsings>false</TUnitImplicitUsings>
6+
<TUnitAssertionsImplicitUsings>false</TUnitAssertionsImplicitUsings>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<PackageReference Include="Shouldly" />
11+
<PackageReference Include="TUnit" />
12+
</ItemGroup>
13+
14+
</Project>

tests/Shared/ShouldlyAssert.cs renamed to tests/PrompterOne.Testing/ShouldlyAssert.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
namespace PrompterOne.Testing;
55

6-
internal static class ShouldlyAssert
6+
public static class ShouldlyAssert
77
{
88
public static void Equal<T>(T expected, T actual)
99
=> actual.ShouldBe(expected);

tests/PrompterOne.Web.Tests/Editor/EditorLocalHistoryInteractionTests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
namespace PrompterOne.Web.Tests;
1212

13+
[NotInParallel]
1314
public sealed class EditorLocalHistoryInteractionTests : BunitContext
1415
{
1516
private readonly AppHarness _harness;

0 commit comments

Comments
 (0)