Testing README — start here
Documentation index · Packaging README · Developer guide
Use this sequence to set up the test environment, run the relevant checks, verify
installation, and remove test resources. Run workstation tests as a normal user
from a full reviewed source checkout, not an installed payload or the smaller
installer source archive. Keep existing user environments and workloads intact.
1. Choose the scope and record the baseline
Record the exact source commit/tree, changed files, host OS and intended checks.
Before changing or packaging source, compare both production documentation
locations and the live POS source as described in the
operator-edit guard.
Those documents are preservation guards, not hourly task sources.
| Change |
Start with |
Before calling it validated |
| Documentation |
Step 5 and viewer tests |
Rebuild check, local links/allowlists, staged inclusion and live guide URLs |
| Python/backend |
Relevant tests/test_*.py |
Full regressions for a release, dev endpoint/feature checks |
| Dashboard JavaScript |
Relevant tests/*.cjs |
All JS checks for a release, browser visual/keyboard checks |
| Installer/RPM |
Steps 6–7 |
Signed package/dependency/setup checks on matching hosts |
| Podman/CRIU/KVM/networking |
Mocked regressions first |
Scoped live checks on an allocated compatible Linux host |
For live tests, record containers and their IDs/start times, images/tags,
snapshots, mounts, active builds, peer state and relevant host settings before
testing. Give every test-created resource an explicit owner/run identifier and
register its exact name/path for cleanup immediately. Preserve pre-existing
resources. Arrange finally/exit/signal cleanup before creating live resources;
if interrupted unexpectedly, reconcile the recorded inventory before rerunning.
2. Create an isolated workstation environment
Use Python 3.12 for workstation regressions and Node.js 20+ for UI/docs checks.
RHEL runtime validation is separate: EL9 uses Python 3.11; EL10 uses its packaged
python3. A Python build providing hashlib.scrypt is required for identity tests.
From the full checkout, run the following in a Bash session and keep the same
session for steps 3–6. The trap removes only the environment and scratch created
here when that session exits, including failures and interrupt/termination.
Activate set -e so a failed command stops that session; open a dedicated shell
for these instructions if you need your parent shell to remain open.
set -eu
umask 077
test_work=$(mktemp -d /tmp/mykos-test.XXXXXX)
test_work=$(cd "$test_work" && pwd -P)
trap 'rm -rf -- "$test_work"' EXIT
trap 'exit 130' INT
trap 'exit 143' TERM
export PYTHONDONTWRITEBYTECODE=1
export PYTHONPATH="$PWD/services/helpers:$PWD/services/web${PYTHONPATH:+:$PYTHONPATH}"
export TMPDIR="$test_work"
export PIP_CACHE_DIR="$test_work/pip-cache"
export npm_config_cache="$test_work/npm-cache"
python3.12 -m venv "$test_work/venv"
. "$test_work/venv/bin/activate"
python -m pip install -r services/requirements.txt pytest httpx
python -c 'import hashlib; assert hasattr(hashlib, "scrypt")'
python --version
node --version
python -m pip freeze > "$test_work/dependencies.txt"
Expected: dependencies install, the scrypt assertion succeeds, and the versions
are recorded. Runtime direct dependencies are pinned; pytest/httpx and all
transitive test dependencies are not a fully locked test environment. Preserve a
compact dependency record with a failure report before exiting. Do not replace
pinned runtime versions just to hide a failing assertion.
3. Run Python regressions
Start with files relevant to the change. For example:
python -m pytest -q -p no:cacheprovider tests/test_supporting_docs.py
python -m pytest -q -p no:cacheprovider tests/test_installer.py
For a planned release, run the complete discovered Python suite:
python -m pytest -q -p no:cacheprovider --basetemp="$test_work/pytest" tests
Expected: no unexplained failures. Record the actual pass/skip counts and reasons;
do not copy a historical count into a new result. Tests use temporary fixtures
and mocked system boundaries; passing them does not prove live host behavior.
The suite contains Linux-specific behavior, so reproduce a platform-only failure
on the compatible dev host before changing code. Never remove a failing test to
make the release appear green.
4. Run JavaScript checks
From the same checkout and session:
for test_file in tests/*.cjs; do
node "$test_file" || exit 1
done
Expected: every script exits successfully. These are plain Node scripts; use
node FILE.cjs, not an assumed npm or node --test project runner. For changed
controls, also inspect real browser behavior on dev: focus/keyboard order,
permissions, popup/close behavior and refresh/error recovery. Test fixtures do
not establish visual correctness or a working remote terminal/guest console.
Close temporary tabs, sessions and PTYs, and restore browser preferences after
verification.
5. Build and verify documentation
Use an expendable copy so npm ci never deletes a pre-existing tooling install.
The example copies the docs tool's exact files into this run's scratch, installs
there, and temporarily links its dependencies into this reviewed checkout. It
refuses to replace an existing tools/docs/node_modules; use that existing
installation after checking its lockfile instead, or use a separate scratch
checkout. The cleanup trap removes only the link and scratch created here.
(
set -eu
test ! -e tools/docs/node_modules
test ! -L tools/docs/node_modules
docs_work=$(mktemp -d /tmp/mykos-docs.XXXXXX)
trap 'rm -f tools/docs/node_modules; rm -rf -- "$docs_work"' EXIT
trap 'exit 130' INT
trap 'exit 143' TERM
cp tools/docs/package.json tools/docs/package-lock.json "$docs_work/"
npm --prefix "$docs_work" ci --ignore-scripts
ln -s "$docs_work/node_modules" tools/docs/node_modules
node tools/docs/build.mjs
python tools/docs/check.py
node tools/docs/build.mjs --check
python -m pytest -q -p no:cacheprovider tests/test_supporting_docs.py
)
Expected: all pages/links, exact viewer allowlists, diagrams, protected originals
and permanent light theme pass; --check finds no generated-file drift. Keep
changed generated HTML/diagrams as intentional source output. It is normal to
commit that output; it is not disposable test scratch. Review the diff. See the
documentation build guide for source ownership and
public allowlists. Do not edit rendered HTML as the primary source.
6. Check staged installation
Stay in the isolated environment from step 2. Stage into its empty scratch root;
never substitute / for this --root:
python bin/mykos-install install --root "$test_work/stage" \
--python /usr/bin/python3.11
python bin/mykos-install verify --root "$test_work/stage"
test -s "$test_work/stage/usr/local/share/mykos/LICENSE.txt"
test -s "$test_work/stage/usr/local/share/mykos/THIRD_PARTY_NOTICES.txt"
test -s "$test_work/stage/usr/local/share/mykos/docs/rendered/PACKAGING_README.html"
test -s "$test_work/stage/usr/local/share/mykos/docs/rendered/TESTING_README.html"
Expected: installer verification reports no unreviewed drift and required guides
and license files exist. Alternate-root staging does not activate host services,
install host dependencies, or prove login/guest lifecycle behavior. Use the
Packaging README to build, inspect and verify the archive
and signed RPMs separately. Check the extracted archive too; passing tests in a
full checkout does not prove that packaging included every required file.
7. Validate live behavior on dev, then production
Use an explicitly allocated compatible Linux environment and the intended signed
candidate. Follow RPM upgrade and verification with a
recorded scoped rollback. Recheck docs/POS preservation guards immediately before
each deployment. Confirm dev's installer verification, app readiness,
authenticated behavior and the changed feature before production promotion.
Keep HTTPS verification enabled and use the host's actual trusted certificate
name. A DNS rename does not update its certificate; do not treat a curl -k
result as a successful trust check. Check the main Docs page and new guide links
through the actual proxy path, not only loopback. Compare served bytes against
accepted rendered output.
Only exercise live lifecycle operations required by the change, with disposable
IDs/storage recorded before use. Scripts named *_probe.py may create real
resources and are not equivalent to mocked pytest files: inspect them first.
Do not build all OS images as a routine app-release test. Preserve active user
builds, containers, snapshots, peers, network configuration and background
repository copies. MYKOS_BASE does not relocate every privileged helper's
hard-coded system paths and is not a lifecycle sandbox.
After dev passes, deploy the same candidate to production, check affected
behavior, and compare preserved resource identities/start times and settings
with the baseline. Defer a disruptive web reload if an active base editor would
be disconnected. If production fails, restore the scoped application change,
record the failure and return to dev; stop publication.
Record test limits precisely. Mocked tests and UBI package/app/login checks do
not verify physical NIC routing, bare-metal KVM, CRIU memory restore or a fresh
installation of every guest. EL10 fresh dependency/native-CRIU availability and
live EL10 runtime verification remain separate release qualifications.
8. Clean up and record results
Before reporting any test complete, on success, failure or interruption:
- Remove only this run's test containers and temporary accounts/sessions/PTYs.
Remove only its test snapshots, disks, volumes and mounts after checking
references and unmounting temporary mounts.
- Check image/container/snapshot references before removing test tags/images.
Use non-forced removal. Never run a global prune or remove shared/in-use
images to make the inventory look clean.
- Remove this run's staging roots, build trees, scratch, caches and temporary
dependency installations. Preserve pre-existing caches/environments. Exit the
dedicated shell from step 2 to trigger its cleanup; verify its recorded
$test_work path is gone from a parent shell. A forced process kill may
require explicit recovery cleanup from the resource record.
- Compare final inventory with the pre-test baseline. Explain legitimate user
changes; do not delete them to force equality. Retain necessary scoped
installer rollback records and accepted release artifacts/evidence only.
- Record source identity, commands, environment, actual results, skips/limits,
dev/prod endpoint results and cleanup verification. Keep private notes and
credentials out of public source, release artifacts and unrelated summaries.
A test is complete when its expected assertions and cleanup checks pass. A
release is complete only after signed publication and verification at all
required destinations; see the release closeout steps.