Skip to content

Commit 9c98a7f

Browse files
committed
docs(rfc): clarify testing model and suite organisation
Signed-off-by: Evan Lezar <elezar@nvidia.com>
1 parent 085c681 commit 9c98a7f

1 file changed

Lines changed: 148 additions & 66 deletions

File tree

‎rfc/0016-testing-strategy/README.md‎

Lines changed: 148 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -12,31 +12,34 @@ links:
1212
## Summary
1313

1414
Define a common testing strategy for OpenShell that separates the behavioral
15-
contract being tested from the environment, installation, execution mechanism,
16-
and CI policy used to validate it. Contributors should be able to place a test,
17-
run it locally, and understand what its result establishes without consulting
18-
several competing descriptions of conformance.
15+
contract being tested from the environment, installation, client interface,
16+
and CI policy used to validate it. Reuse tests of public behavior across
17+
configured targets, while keeping implementation-specific checks and performance
18+
measurements distinct. A passing test establishes the same contract regardless
19+
of how its target was prepared.
1920

2021
Use Nix for reproducible build inputs and test artifacts, and tmachine for
21-
integration and Linux installation environments it can represent. Keep general
22-
conformance focused on public behavior exercised through the OpenShell CLI.
23-
Feature, driver, disruption, load/scale, and SDK coverage retain explicit
24-
boundaries. This is a proposal for incremental implementation, not a description
25-
of gates already enforced by CI.
22+
integration and Linux installation environments it can represent. Keep test
23+
contracts independent of those tools. Initially exercise general conformance
24+
through the OpenShell CLI; using an SDK does not create a different test category.
25+
This is a proposal for incremental implementation, not a description of gates
26+
already enforced by CI.
2627

2728
## Motivation
2829

29-
OpenShell tests have accumulated across crate-local tests, E2E binaries,
30-
driver wrappers, installed-artifact suites, and CI workflows. A single source
31-
binary can mix a portable behavioral contract, native runtime inspection, an
32-
external service integration, and performance measurements. This makes both
33-
ownership and coverage difficult to assess.
30+
How do we establish that OpenShell behaves as promised across supported
31+
configurations without duplicating behavioral tests for every driver and
32+
environment? Tests tied to particular environments make it difficult to
33+
distinguish product requirements from implementation details, reuse coverage,
34+
or determine what a passing suite establishes.
3435

35-
Documentation has the same problem. TESTING.md is being asked to describe local
36-
commands, a future execution model, conformance admission rules, migration work,
37-
and release gates. Suite READMEs and implementation PRs independently define
38-
parts of that strategy. Contributors cannot tell which document owns a decision
39-
or whether a statement describes current behavior or a target state.
36+
OpenShell tests have accumulated across crate-local tests, E2E binaries,
37+
driver wrappers, installed-artifact suites, and CI workflows. A single binary
38+
can mix public behavior, native runtime inspection, an external integration,
39+
and performance measurements. Without a shared model, contributors must either
40+
duplicate this coverage for new targets or carry assumptions that do not apply
41+
to them. Reviewers cannot reliably distinguish missing product support from
42+
missing test infrastructure.
4043

4144
The migration tracked by #3712 makes this concrete: the tmachine e2e-podman
4245
suite supplies interim coverage, but the intended outcome is to move the source
@@ -49,58 +52,54 @@ the definition of OpenShell conformance.
4952
- Implement the proposed framework, capability API, or CI matrices in this PR.
5053
- Finalize the destination of every existing E2E assertion; migration issues
5154
retain that analysis and their task lists.
52-
- Introduce named conformance profiles, hierarchical capability inference, or
53-
generic capability parameters before concrete tests require them.
54-
- Create a dedicated workload fixture image or dependency-declaration system
55-
for scenarios initially.
5655
- Establish a certification program, review board, or reporting service.
5756
- Replace the SDK compatibility proposal in #3238 or standardize language SDK
5857
APIs through the CLI runner.
5958

6059
## Proposal
6160

62-
### 1. Separate behavioral ownership from execution dimensions
61+
### 1. Define contracts and organise tests by purpose
6362

64-
Each assertion has an intended contract and an appropriate owner. A binary can
65-
be split when its assertions belong to different families.
63+
A behavioral contract specifies the expected observable result of an operation
64+
under stated conditions. A test case exercises that behavior; an assertion
65+
checks an observation against an expectation. A suite groups related test cases.
66+
For example, a contract may require that a deleted sandbox is absent from the
67+
sandbox list; the assertion checks that its identifier is absent. Assertions
68+
that verify test setup do not each define a separate product contract.
6669

67-
| Family | Contract and admission boundary |
70+
Group tests by the contracts they exercise, not by their current binary or
71+
runner. Split binaries when they mix unrelated contracts or prerequisites.
72+
73+
| Family | Purpose |
6874
| --- | --- |
6975
| Unit and component integration | Internal logic, configuration selection, translation, and implementation mechanics; use the lowest effective layer. |
70-
| General conformance | Public behavior demonstrated on at least two different drivers, with effective API capabilities for non-universal support. |
76+
| General conformance | Public behavioral contracts that hold across drivers and environments, independent of implementation details. |
7177
| Feature-specific | Public feature behavior requiring configured external integration, or currently implemented on only one driver; one representative driver suffices. |
7278
| Driver-specific | Driver configuration, runtime and host integration, and implementation contracts; exercise applicable environments for that driver. |
7379
| Disruption conformance | Portable continuity or recovery assertions using environment-specific disruption actuators; one working actuator suffices initially. |
7480
| Load/scale | Throughput, latency, concurrency, saturation, and scaling measurements, reported separately from behavioral correctness. |
75-
| SDK conformance | Behavior and compatibility of SDK implementations through their native interfaces, specified separately in #3238. |
81+
82+
The placement of portable, capability-dependent tests in general conformance
83+
or feature-specific suites remains open until a concrete migration example
84+
requires that decision. Capability dependence alone does not determine a family.
85+
86+
The client interface is separate from the test family. A public contract tested
87+
through an SDK can belong to general conformance just as it can through the CLI.
88+
SDK-specific behavior, such as language-specific conversion and cancellation,
89+
needs focused coverage; #3238 retains its SDK compatibility design scope.
7690

7791
Security portability is a workstream spanning these families. Define a separate
7892
security family only if multiple tests need common specialized infrastructure.
7993
For example, bypass prevention is an intended universal guarantee, but the
8094
existing seccomp-oriented probe needs separate analysis before its portable
8195
migration. Core-dump protection similarly needs a portable contract and probe.
8296

83-
The execution matrix has independent axes:
84-
85-
| Axis | Examples |
86-
| --- | --- |
87-
| Platform | Host and workload OS and architecture |
88-
| Driver | Docker, Podman, Kubernetes, VM, MXC |
89-
| Environment | Rootful/rootless Podman, local runtime, Kubernetes cluster |
90-
| Configuration | Gateway settings, in-process/external driver wiring |
91-
| Installation | Candidate binaries/images, RPM, DEB, Snap, Helm, Homebrew |
92-
| Suite | General conformance, a feature suite, a driver suite, disruption |
93-
94-
Rootful and rootless Podman are environments of one driver. They do not satisfy
95-
the two-driver admission rule. Driver tests should preserve their behavioral
96-
contract across those environments. Matrix entries should target meaningful
97-
risks without requiring the full cross-product of every axis.
98-
9997
### 2. Define general conformance through observable contracts
10098

10199
Conformance tests exercise a behavioral contract against an already configured
102-
OpenShell gateway. They remain CLI-based until direct API access is strictly
103-
required. Assertions should use observable outcomes and structured output;
100+
OpenShell gateway. The initial suite remains CLI-based until direct API access
101+
is strictly required; this is an execution choice, not a classification rule.
102+
Assertions should use observable outcomes and structured output;
104103
incidental presentation text is not a conformance contract. Native runtime
105104
inspection may provide best-effort failure diagnostics, but must not determine
106105
whether general conformance passed.
@@ -160,9 +159,9 @@ when support for that capability is optional.
160159

161160
Non-universal behavior supported by at least two drivers is a signal to extend
162161
the public capability API. Prefer adding the capability and its concrete test
163-
in the same PR. If an API extension is infeasible, use feature-specific or
164-
driver-specific coverage. Both drivers used for general-conformance admission
165-
must advertise the capability and pass its assertions.
162+
in the same PR. The eventual suite classification of optional portable contracts
163+
is deferred, but their result semantics are not: absent optional support is
164+
unsupported, and advertised behavior that violates its contract fails.
166165

167166
| Outcome | Meaning |
168167
| --- | --- |
@@ -180,6 +179,48 @@ driver. A focused or incomplete invocation must not imply complete coverage.
180179

181180
### 4. Keep execution reusable and select CI gates explicitly
182181

182+
A test run exercises selected test cases against a configured target and records
183+
their results. Target preparation supplies the environment, installs artifacts,
184+
and configures the gateway. Behavioral tests consume that target through a
185+
client interface. CI policy selects runs and decides which results gate a merge
186+
or release; it does not redefine the tested contracts.
187+
188+
```mermaid
189+
flowchart LR
190+
subgraph preparation[Target preparation]
191+
machine[Machine / base image] --> setup[Environment setup]
192+
setup --> install[Install and configure OpenShell]
193+
end
194+
artifacts[Build artifacts] --> install
195+
install --> target[Configured OpenShell target]
196+
external[External provisioning] --> target
197+
suite[Test suite] --> client[CLI or SDK]
198+
client -->|exercises| target
199+
```
200+
201+
In the current tmachine configuration, a `Machine` identifies a base image.
202+
An `Environment` references a machine and supplies setup playbooks. A separate
203+
`Installer` supplies installation playbooks and artifact inputs, and a
204+
`Testsuite` supplies test playbooks and inputs. Selecting an environment,
205+
installer, and suite composes a run without making test ownership depend on
206+
target preparation.
207+
208+
Runs vary along several dimensions; not every combination is meaningful:
209+
210+
| Dimension | Examples |
211+
| --- | --- |
212+
| Platform | Host and workload OS and architecture |
213+
| Driver | Docker, Podman, Kubernetes, VM, MXC |
214+
| Environment | Local runtime, Kubernetes cluster, rootful/rootless Podman |
215+
| Configuration | Gateway settings, in-process/external driver wiring |
216+
| Installation | Candidate binaries/images, RPM, DEB, Snap, Helm, Homebrew |
217+
| Client interface | CLI, language SDK |
218+
| Suite | General conformance, feature-specific, driver-specific, disruption |
219+
220+
For example, rootful and rootless Podman change the environment, not the driver
221+
or expected contract. They do not supply two-driver admission evidence. Select
222+
combinations for meaningful coverage rather than requiring a full cross-product.
223+
183224
Nix pins source-check dependencies and builds candidate artifacts and test
184225
archives. Tmachine provisions supported environments, applies installation and
185226
configuration, and runs a selected suite. Tests should consume an already
@@ -228,7 +269,43 @@ the effective configuration. Other provisioners supply equivalent target
228269
identification. This is a placeholder, not a complete report schema; richer
229270
capability, scenario, and artifact reporting can follow a concrete need.
230271

231-
### 5. Give each document one responsibility
272+
## Implementation plan
273+
274+
### Build on the existing suite layout
275+
276+
Retain the existing suite locations and extend them as contracts are migrated:
277+
278+
```text
279+
tests/
280+
├── config.nix # Existing tmachine definitions
281+
├── artifacts.nix # Existing artifact construction
282+
├── ansible/ # Existing provisioning and execution
283+
├── CONFORMANCE.md # Proposed agreed conformance policy
284+
└── suites/
285+
├── conformance/
286+
│ ├── cli/ # Existing CLI test entry points
287+
│ └── README.md # Proposed suite contributor guidance
288+
├── drivers/
289+
│ └── podman/ # Existing driver-specific tests
290+
└── features/
291+
└── provider-refresh/
292+
└── keycloak/ # Existing external-integration tests
293+
```
294+
295+
Move the shared `crates/openshell-conformance` library under
296+
`tests/suites/conformance` alongside its existing CLI entry points; choose its
297+
precise internal layout in that relocation. Extend `drivers/` and `features/`
298+
with focused suites rather than new catch-all binaries. Unit and component
299+
integration tests remain alongside their components, and SDK-native tests may
300+
remain in their SDK trees. Folder placement does not define the behavioral
301+
contract. Disruption and load/scale locations remain open pending their concrete
302+
infrastructure needs.
303+
304+
### Publish the agreed model
305+
306+
Documentation records the testing model and its implementation; reorganising
307+
documentation is not a substitute for implementing reusable suites and target
308+
preparation. Publish agreed policy as implementation lands:
232309

233310
| Document | Responsibility |
234311
| --- | --- |
@@ -247,7 +324,7 @@ proposal while sharing terminology and provisioning boundaries. Accepted policy
247324
is published in the living guides as implementation lands; current references
248325
must not describe proposed gates as already enforced.
249326

250-
## Implementation plan
327+
### Adopt incrementally
251328

252329
1. Discuss this RFC through existing PR #3460 and track follow-ups in #3954.
253330
Resolve policy questions independently from per-test migration details.
@@ -296,12 +373,19 @@ must not describe proposed gates as already enforced.
296373

297374
## Alternatives
298375

299-
### Continue expanding TESTING.md and suite READMEs independently
376+
### Maintain independent driver-specific E2E suites
377+
378+
Each driver could retain a complete E2E suite tailored to its runtime. This
379+
minimises initial migration, but duplicates public behavioral checks and allows
380+
expectations to diverge. Reuse portable contracts across targets and reserve
381+
driver-specific coverage for implementation and integration requirements.
300382

301-
This is the smallest immediate documentation change, but leaves strategy,
302-
commands, and future gates interleaved. A single RFC and focused living
303-
references give reviewers a place to resolve disagreements before publishing
304-
authoritative guidance.
383+
### Couple behavioral tests to target provisioning
384+
385+
Each suite could provision and configure its own gateway. This simplifies local
386+
setup for that suite, but makes it harder to validate installed artifacts or an
387+
externally prepared gateway with the same tests. Separate target preparation
388+
from behavioral testing while allowing a harness to orchestrate both.
305389

306390
### Introduce separate API and CLI conformance frameworks immediately
307391

@@ -310,18 +394,13 @@ runner and overlapping scenarios before a CLI limitation requires them. Keep
310394
general conformance CLI-based initially; SDK interface testing remains a
311395
separate justified consumer under #3238.
312396

313-
### Require every scenario on every configuration
397+
### Require every tested behavior on every configuration
314398

315399
This gives a uniform baseline but excludes useful portable behavior that some
316400
drivers do not implement. Mandatory scenarios plus precise optional capabilities
317-
allow useful coverage while requiring advertised behavior to pass.
318-
319-
### Establish profiles and a full certification process first
320-
321-
Profiles, a versioned certification program, and formal promotion gates could
322-
clarify compatibility guarantees, but would add policy and infrastructure before
323-
the existing tests have been classified. Keep these decisions open and evolve
324-
them from concrete contracts and consumers.
401+
allow useful coverage while requiring advertised behavior to pass. Whether
402+
optional portable contracts belong in general conformance or feature-specific
403+
suites is deferred; this alternative concerns support requirements, not naming.
325404

326405
## Prior art
327406

@@ -341,6 +420,9 @@ them from concrete contracts and consumers.
341420

342421
## Open questions
343422

423+
- Should portable, capability-dependent tests belong in general conformance or
424+
feature-specific suites? Resolve this using the first concrete migration
425+
example that requires the distinction, without adding a category in advance.
344426
- What constitutes a complete conformance claim, and how are suite versions
345427
matched to gateway/CLI releases? Which version-skew guarantees are required?
346428
- What maturity and reliability evidence is required beyond two-driver success?

0 commit comments

Comments
 (0)