Repository navigation
Test in three layers with wall-clock budgets #12876
Description
Problem
Unit, integration, and end-to-end tests check the same behavior at several layers, yet regressions still reach v1:
- Typed gateway attributes are asserted by an SDK round trip, the provider schema test, provider backend tests, SDK compile tests, and an end-to-end protocol test. None applied Docker gateway storage through OpenTofu, so feat(provider): type gateway resources and service observation inputs #12831 broke Live / Docker on
v1. - Real OpenTofu runs through three conventions:
NEMOCLAW_TEST_BUNDLEinnemoclaw-sdk/src, andNEMOCLAW_TEST_TOFUwithNEMOCLAW_TEST_PROVIDERorNEMOCLAW_TEST_BUNDLEinnemoclaw-e2e. Workspace setup is copied in 22 places, and about six files define their own fake servers. - 112 of 147
nemoclaw-e2etests are ignored and run only when a name pattern in.config/nextest.tomlselects them;kubernetes_hclnever ran in CI until test(e2e): plan every remaining NemoClaw type from authored HCL #12868. - Tests decode other crates' internal JSON; reading the removed
specattribute broke Live / Kind after feat(provider): type managed Kubernetes resource settings #12855.
Cost is wall-clock time, not code. On linux_arm64 (CI / Native), deterministic tests take 62 s, and the lifecycle step takes 684 s for 109 tests that sum to 2,673 s. Three files account for 82% of that sum: deployment (1,247 s), remote_service (608 s), and fabric_deployment (335 s).
Layers
| Layer | Answers | Lives in | Budget on Linux CI runners |
|---|---|---|---|
| Unit | Is the rule right? | Each crate's src/, in-process fakes only |
Workspace step ≤ 90 s; each test ≤ 2 s |
| Contract | Does each provider type work through pinned OpenTofu? | One contract test binary per provider crate, with a fixture per type | Each provider ≤ 90 s; each fixture ≤ 15 s |
| System | Does SDK and CLI orchestration work? | nemoclaw-e2e |
Lifecycle step ≤ 8 min; each scenario ≤ 120 s |
Live Docker and Kind suites stay separate and report their time against 10 and 8 minutes.
A layer asserts only behavior its crate owns: SDK tests assert the generated configuration, provider tests assert their types, and no test decodes another crate's internal JSON.
Order
- Enforce wall-clock budgets per test layer #12877 records today's times and enforces the budgets, so every later change is measured.
- Share one test harness driven by the bundle #12878 gives every layer one harness.
- Contract tests for the nemoclaw provider #12879 and Contract tests for the openshell and fabric providers #12880 add contract tests per provider.
- Move tests to the layer that owns their behavior #12881 moves the remaining tests to the layer that owns them.
- Bring the system layer under its budget #12882 brings the system layer under budget.
- Run live suites on provider changes #12883 runs the live suites before merge.
Done when
All sub-issues are closed, CI enforces each budget, and the testing guide describes the layers and budgets.
Activity
cv commentedon Oct 9, 2026
Where each behavior is tested
The map below uses
linux_amd64timings from #12885's CI run, after that PR's reductions. Unit counts come from test names and are approximate.v1onlyvllm_runtime,kubernetes_hcldeployment, 10 Fabric harnesses, 4 remote lifecycles,multiple_providers, export testsopentofu_openshell,provider_protocolopentofu_openshelllost replies and untaint,service_storage,provider_protocoldeploymentscenarios, about 470 sopentofu_openshell,gateway_readinessprocessredaction rulesservice_readinesscli_redaction, bearer lifecycle (131 s)readinessandstatusservice_readiness,gateway_readiness,sandbox_readinessapply_health_failure,readiness_and_observation_failures, remote lifecyclesruntime_imageunit testsruntime_image,provider_protocolunverified_*_images, remote pull checksnemoclaw-openshellobservation reasonsincompatible_gateway…,gateway_change_between_plan_and_applyfabric_config,execution_settingskubernetes_hcl(plan only)nemoclaw-sdk(5 tests, about 61 s); Kind liveclitestscli_terminal_outputs…(37 s), startup failure messagesFindings
openshellhas 23 contract tests, thenemoclawprovider about 20 scattered across 10 modules, Fabric none, and Kubernetes a plan-only check. Failure and recovery fornemoclawandfabrictypes is therefore checked only in 30-second system scenarios. Contract tests for the nemoclaw provider #12879 and Contract tests for the openshell and fabric providers #12880 cover this.test: keep one system lifecycle per drift kind (#12906)
test: split tests into layers with wall-clock budgets (#12885)
ci: fail a test step that exceeds its wall-clock budget (#12938)
ci: run the live suites on pull requests that can affect them (#12937)
1 remaining item
feat(docker): reach SSH container engines from Windows (#12945)
test(provider): move single-type nemoclaw tests into the provider's c…
test: reach fake engines from OpenTofu-launched providers on every pl…
test: run the bundle-driven system tests on Windows (#12960)
test: run the SSH simulator's tests on Windows (#12963)
test: split the slow remote-service lifecycle scenarios (#12965)
test: share fixture binaries and finish the nemoclaw contract tests (#…
cv commentedon Oct 10, 2026
Status on
v1:nemoclawcontract testsopenshellandfabriccontract testsBesides the sub-issues, two Done-when items remain:
.config/test-budgets.yamlhas no contract-layer budget. Contract tests run inside the lifecycle partitions.docs/contributing/testing.mdlists the step budgets but doesn't describe the three layers.ci: lower the lifecycle budget to its measured times (#12969)
test: apply, refresh, and tear down the Kubernetes resources in the n…
ci: budget each provider's contract tests (#12990)
ci: stop a contract test near its time limit (#12994)
docs: describe the test layers and their budgets (#12997)
cv commentedon Oct 12, 2026
Done on
v1..config/test-budgets.yamlsets a wall-clock budget for the test step, each lifecycle partition, each provider's contract binary, and each live suite, plus a per-test limit for each.cargo cienforces them on the Linux runners, and nextest stops a test near its limit.docs/contributing/testing.mdandintegration-tests.mddescribe the unit, contract, system, and live layers, how to run each, and their budgets (docs: describe the test layers and their budgets #12997, docs: describe where the SDK's OpenTofu recovery tests moved #13004).Since this issue was opened, on linux_amd64:
On Windows, the lifecycle step went from 52 to about 128 tests.
#13005 tracks the remaining rewrite of
model_live, a manual GPU test.v1is not the default branch, so closing keywords did not apply.