Test Suite Consolidation Deep Dive
Audience: maintainers planning the test-consolidation effort — deciding which suites become PR-blocking, nightly, release-gating, or remain report-only.
Snapshot date: 2026-05-22 UTC.
This report extends TEST_PROJECT_CI_INVENTORY.mdwith a consolidation-grade static inventory of runnable suites and fixture/corpus ownership. It is intended to support consolidation planning — it reports structure and CI mapping, not behavioral correctness.
Generated appendices:
test-suite-layer-inventory.csvtest-fixture-corpus-inventory.csv- Existing scenario appendix:
test-e2e-scenario-inventory.csv
Follow-up consolidation plan: TEST_FRAMEWORK_CONSOLIDATION_PLAN.md.
Method
The inventory was generated from repository-local files only. It excludes bin, obj, node_modules, dist, generated artifacts, Playwright reports, coverage output, and test result directories.
For .NET projects, estimated_test_methods_or_spec_files is a static count of [Fact] plus [Theory] methods, not expanded data rows. Data-driven breadth is captured separately through InlineData, MemberData, and ClassData counts in the CSV. For frontend, Playwright, and Go rows, the same field counts spec/test files.
Headline Findings
| Finding | Count | Consolidation impact |
|---|---|---|
| Runnable suite rows inventoried | 597 | Includes .NET, frontend, Playwright, Go, tooling, and docs sample/template runners. |
| Test/spec files indexed | 7,557 | Static source files after generated/build output pruning. |
| Estimated methods/spec files | 41,954 | Useful for relative suite size, not exact test-case expansion. |
| Fixture/corpus roots | 198 | Fixture ownership needs its own manifest, not ad hoc project-local conventions. |
| High-value suites not currently blocking | 368 | Integration, E2E, security, golden, determinism, offline, connector, performance, and contract layers are mostly manual/report-only today. |
| Runnable rows with no active CI mapping | 23 | Includes 20 product/test-surface rows plus 3 docs sample/template rows. |
.NET suites missing Category traits | 147 | Filter-based consolidation is unsafe until trait taxonomy is normalized. |
| Suites with skipped tests | 10 | These contain 34 static Skip = attributes and need an explicit skip audit. |
CI State
| CI state | Rows | Meaning |
|---|---|---|
manual-report-only | 567 | Generic .NET sweep / fanout mapping exists, but current workflow state is manual and report-only. |
no-active-ci | 23 | No direct active workflow mapping was found. |
automatic-pr-or-push | 3 | Current workflow mapping includes automatic PR/push execution without a report-only marker. |
report-only | 3 | Automatic or mixed workflow exists, but the mapped row is explicitly report-only. |
The three automatic rows are the OpenAPI conformance pack, the Air-gap Federation integration pack, and root docs/API parity tooling. Frontend is intentionally conservative in this table because its current single row mixes Vitest PR drift, default Playwright, and Air-gap E2E mappings; the manifest work should split those into separate runner rows.
Suite Layers
Layer counts are non-exclusive because a single suite can be both integration and security, or golden and determinism.
| Suite layer | Rows |
|---|---|
unit/component | 188 |
integration | 181 |
connector/feed/plugin | 130 |
determinism/replay/time | 52 |
security/identity/crypto | 48 |
golden/corpus | 44 |
analyzer/static-analysis | 42 |
e2e | 31 |
contract/conformance | 30 |
performance/benchmark | 23 |
offline/airgap | 16 |
chaos | 6 |
browser-e2e | 2 |
go-unit | 2 |
frontend-unit | 1 |
operator-live | 1 |
Scenario Families
| Scenario family | Rows |
|---|---|
advisory-feed-connectors | 105 |
scanner/reachability/vex | 100 |
__Libraries | 57 |
evidence/attestation/signing | 53 |
policy/risk/verdict | 38 |
release-workflow | 38 |
binary/symbols/ground-truth | 33 |
__Tests | 31 |
notification/connectors | 28 |
identity/authority | 26 |
web/ui | 23 |
airgap/offline | 16 |
The highest fragmentation is in advisory-feed connector fixtures and Scanner reachability/VEX coverage. These should be manifest-owned first because they combine fixture corpuses, external-format contracts, and high-value regression coverage.
Consolidation Buckets
| Bucket | Rows | Meaning |
|---|---|---|
high-value-not-blocking | 368 | Suite layer looks release-relevant but current CI state is manual/report-only or unmapped. |
fixture-owned | 216 | Suite has local fixtures, embedded/content resources, or fixture roots nearby. |
trait-missing | 147 | .NET suite has no static Category trait detected. |
standardize-in-manifest | 135 | No immediate exception, but should still be registered in the manifest. |
ci-gap | 23 | No direct active CI mapping. |
skip-audit | 10 | Suite has static skipped tests. |
CI Gap Rows
| Module | Suite | Layer | Estimate | Path |
|---|---|---|---|---|
src/__Tests/playwright | operator-trust-playwright | browser-e2e;e2e;operator-live | 16 | src/__Tests/playwright/package.json |
__Tests | StellaOps.Testing.Determinism.Properties | determinism/replay/time | 15 | src/__Tests/__Libraries/StellaOps.Testing.Determinism.Properties/StellaOps.Testing.Determinism.Properties.csproj |
__Tests | StellaOps.E2E.AnomalyV2Pipeline | e2e | 1 | src/__Tests/e2e/AnomalyV2Pipeline/StellaOps.E2E.AnomalyV2Pipeline.csproj |
__Tests | StellaOps.E2E.GoldenSetDiff | e2e;golden/corpus | 7 | src/__Tests/e2e/GoldenSetDiff/StellaOps.E2E.GoldenSetDiff.csproj |
__Tests | StellaOps.Integration.E2E.Integrations | determinism/replay/time;e2e;integration;offline/airgap | 111 | src/__Tests/e2e/Integrations/StellaOps.Integration.E2E.Integrations.csproj |
__Tests | StellaOps.E2E.ReplayableVerdict | determinism/replay/time;e2e | 12 | src/__Tests/e2e/ReplayableVerdict/StellaOps.E2E.ReplayableVerdict.csproj |
__Tests | StellaOps.E2E.RuntimeLinkage | e2e;integration | 5 | src/__Tests/e2e/RuntimeLinkage/StellaOps.E2E.RuntimeLinkage.csproj |
__Tests | StellaOps.Integration.GoldenSetDiff | golden/corpus;integration | 20 | src/__Tests/Integration/GoldenSetDiff/StellaOps.Integration.GoldenSetDiff.csproj |
__Tests | StellaOps.Integration.AirGap | e2e;integration;offline/airgap | 19 | src/__Tests/Integration/StellaOps.Integration.AirGap/StellaOps.Integration.AirGap.csproj |
__Tests | StellaOps.Integration.ClockSkew | determinism/replay/time;integration | 12 | src/__Tests/Integration/StellaOps.Integration.ClockSkew/StellaOps.Integration.ClockSkew.csproj |
__Tests | StellaOps.Integration.Determinism | determinism/replay/time;integration | 182 | src/__Tests/Integration/StellaOps.Integration.Determinism/StellaOps.Integration.Determinism.csproj |
__Tests | StellaOps.Integration.E2E | e2e;integration | 28 | src/__Tests/Integration/StellaOps.Integration.E2E/StellaOps.Integration.E2E.csproj |
__Tests | StellaOps.Integration.HLC | chaos;determinism/replay/time;integration | 18 | src/__Tests/Integration/StellaOps.Integration.HLC/StellaOps.Integration.HLC.csproj |
__Tests | StellaOps.Integration.Immutability | determinism/replay/time;integration | 19 | src/__Tests/Integration/StellaOps.Integration.Immutability/StellaOps.Integration.Immutability.csproj |
__Tests | StellaOps.Integration.Performance | integration;performance/benchmark | 41 | src/__Tests/Integration/StellaOps.Integration.Performance/StellaOps.Integration.Performance.csproj |
__Tests | StellaOps.Integration.Platform | integration | 8 | src/__Tests/Integration/StellaOps.Integration.Platform/StellaOps.Integration.Platform.csproj |
__Tests | StellaOps.Integration.ProofChain | integration | 6 | src/__Tests/Integration/StellaOps.Integration.ProofChain/StellaOps.Integration.ProofChain.csproj |
__Tests | StellaOps.Integration.Reachability | integration | 9 | src/__Tests/Integration/StellaOps.Integration.Reachability/StellaOps.Integration.Reachability.csproj |
__Tests | StellaOps.Integration.Unknowns | integration | 12 | src/__Tests/Integration/StellaOps.Integration.Unknowns/StellaOps.Integration.Unknowns.csproj |
BinaryIndex | StellaOps.BinaryIndex.Benchmarks | performance/benchmark | 0 | src/BinaryIndex/__Tests/StellaOps.BinaryIndex.Benchmarks/StellaOps.BinaryIndex.Benchmarks.csproj |
Doctor | StellaOps.Doctor.Plugin.Storage.Tests | connector/feed/plugin;integration | 7 | src/Doctor/__Tests/StellaOps.Doctor.Plugin.Storage.Tests/StellaOps.Doctor.Plugin.Storage.Tests.csproj |
docs-sample/template | StellaOps.Plugin.MyConnector.Tests | connector/feed/plugin | 0 | docs/dev/sdks/plugin-templates/stellaops-plugin-connector/__Tests/StellaOps.Plugin.MyConnector.Tests/StellaOps.Plugin.MyConnector.Tests.csproj |
docs-sample/template | StellaOps.Plugin.MyJob.Tests | connector/feed/plugin | 0 | docs/dev/sdks/plugin-templates/stellaops-plugin-scheduler/__Tests/StellaOps.Plugin.MyJob.Tests/StellaOps.Plugin.MyJob.Tests.csproj |
docs-sample/template | Examples.Integration.Tests | integration | 0 | docs/modules/router/samples/tests/Examples.Integration.Tests/Examples.Integration.Tests.csproj |
Largest Suites
| Module | Suite | Layer | Estimate | CI state |
|---|---|---|---|---|
Cli | StellaOps.Cli.Tests | determinism/replay/time;golden/corpus;integration | 1,687 | manual-report-only |
Policy | StellaOps.Policy.Engine.Tests | determinism/replay/time;integration;performance/benchmark | 1,204 | manual-report-only |
Web | stellaops-web | browser-e2e;e2e;frontend-unit | 968 | report-only |
Scanner | StellaOps.Scanner.WebService.Tests | contract/conformance;integration;security/identity/crypto | 935 | manual-report-only |
ExportCenter | StellaOps.ExportCenter.Tests | integration | 895 | manual-report-only |
AdvisoryAI | StellaOps.AdvisoryAI.Tests | determinism/replay/time;integration;performance/benchmark;security/identity/crypto | 868 | manual-report-only |
Signals | StellaOps.Signals.Tests | determinism/replay/time;integration | 758 | manual-report-only |
Attestor | StellaOps.Attestor.ProofChain.Tests | determinism/replay/time;golden/corpus;integration | 735 | manual-report-only |
Notifier | StellaOps.Notifier.Tests | integration | 671 | manual-report-only |
Policy | StellaOps.Policy.Tests | integration | 648 | manual-report-only |
Scanner | StellaOps.Scanner.Reachability.Tests | contract/conformance;determinism/replay/time;golden/corpus;integration;performance/benchmark | 601 | manual-report-only |
Concelier | StellaOps.Concelier.Core.Tests | determinism/replay/time;integration;performance/benchmark | 514 | manual-report-only |
These suites should not be moved casually. They are the best candidates for a manifest-driven split into fast deterministic slices, fixture-backed golden slices, and slower infra/live slices.
Fixture and Corpus Ownership
Top fixture roots by file count:
| Owner | Fixture root | Type | Files |
|---|---|---|---|
src/__Tests/e2e | src/__Tests/e2e/scanner-analyzer-corpus/fixtures | fixture | 880 |
__Tests | src/__Tests/reachability/fixtures | fixture | 523 |
tests | src/tests/reachability/fixtures | fixture | 385 |
Scanner | src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Tests/Fixtures | fixture | 359 |
Scanner | src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Fixtures | fixture | 102 |
Scanner | src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Tests/Fixtures | fixture | 81 |
Scanner | src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Bun.Tests/Fixtures | fixture | 62 |
Scanner | src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Node.Tests/Fixtures | fixture | 60 |
Cryptography | src/Cryptography/__Tests/StellaOps.Cryptography.Tests/Eidas/Fixtures | fixture | 58 |
__Tests | src/__Tests/fixtures | fixture | 57 |
Fixture root counts by owner are concentrated in Concelier (57), Scanner (38), cross-cutting __Tests (17), Policy (9), docs/qa (9), Attestor (8), and Authority (7). Consolidation should add ownership, refresh command, offline status, and determinism policy for each root.
Skip Audit
The deep inventory found 10 suites with static Skip = attributes, totaling 34 skipped declarations. The affected modules include __Tests, AdvisoryAI, Cli, Concelier, Platform, ReleaseOrchestrator, Router, and Scanner. These should be reviewed before using suite green status as release evidence.
Consolidation Recommendations
- Create a versioned test manifest and make CI consume it. Each row should name the runner, layer, owner, fixture roots, infra, trigger, and gating state.
- Resolve
ci-gaprows first. Product/test-surface priorities are production Playwright,src/__Tests/e2e/**,src/__Tests/Integration/**, module-owned Doctor plugin tests, andBinaryIndexbenchmarks. - Split mixed rows before changing gates. The Web row currently combines Vitest specs, default Playwright, live/search Playwright, and Air-gap federation UI specs. Those should become separate manifest entries.
- Normalize
Category/Lanetraits before relying on filter-based consolidation. There are 147 .NET rows with no static Category trait. - Promote high-value report-only suites in stages: first make them explicit non-blocking lanes with stable artifacts, then decide which slices become PR blocking, nightly blocking, release blocking, or permanently report-only.
- Give fixture corpuses first-class ownership. The Scanner SCM corpus, reachability fixtures, Concelier connector fixtures, and docs/QA fixtures should have refresh commands, offline rules, and expected deterministic outputs.
- Keep expensive, live, hardware, OS-confinement, and Docker-heavy tests out of generic PR fanout unless they have fast slices. They still need manifest rows so consolidation does not hide them.
Decisions Needed Later
- Whether production/operator Playwright under
src/__Tests/playwrightshould become PR-blocking, scheduled, release-blocking, or remain manual. - Whether docs sample/template test projects should be runnable CI examples or excluded from the consolidation manifest.
- Which high-value report-only layer should be promoted first: cross-cutting integration/e2e, Scanner reachability/VEX, Concelier connector fixtures, or security/identity/crypto.
