trainlog/docs/tests.md

224 lines
5.2 KiB
Markdown

# Tests and Validation
## 1. Principle
A feature is not complete without relevant validation.
The exchange validator is executable specification during the format gates.
## 2. Canonical exchange validation
Run:
```bash
python tools/validate_json.py
```
The command validates:
- `examples/session-v1.json`;
- all `tests/fixtures/valid/*.json` as valid;
- all `tests/fixtures/invalid/*.json` as invalid.
A negative fixture passes only when Trainlog rejects it.
## 3. Validation layers
A v1 document must pass:
1. JSON Schema validation;
2. Trainlog semantic validation.
Schema handles shape, enumerations, and primitive ranges.
Semantic validation handles cross-object and normalized rules.
## 4. Gate 1 semantic coverage
The canonical validator checks:
- unique `exercise_id`;
- normalized exercise-name uniqueness;
- explicit timestamp offsets;
- end time later than start time;
- exact catalog/reference set equality;
- one workout entry per exercise;
- catalog tracking mode matching target;
- catalog tracking mode matching actual sets;
- load-mode/weight consistency;
- non-blank notes.
## 5. Positive fixture coverage
Gate 1 includes:
- mixed loaded repetition + timed session;
- active session without `ended_at`;
- planned exercise with zero actual sets;
- bodyweight exercise with zero-repetition failed attempt;
- assistance load;
- completely interrupted session with zero exercises.
## 6. Negative fixture coverage
Gate 1 includes rejection of:
- duplicate exercise IDs;
- duplicate normalized exercise names;
- duplicate workout exercise entries;
- end timestamp before start;
- missing timestamp offset;
- target/actual tracking mismatch;
- target containing both repetitions and duration;
- unknown exercise reference;
- unknown JSON field;
- catalog tracking-mode mismatch;
- `load_mode=none` carrying weight;
- loaded target missing weight;
- loaded actual set missing weight;
- unreferenced catalog entries;
- blank session notes;
- blank exercise notes;
- negative actual repetitions.
## 7. Gate 2 compiled validation
The normal Meson suite currently covers:
```text
database
catalog
session_detail
duration
body_metrics
bodyviz
exercise_performance
session_type_schema
session_edit
body_observation_edit
```
The session-edit test verifies transactional child replacement without changing
the parent session identity. The body-observation edit test verifies stable
observation identity while metric values and notes are updated.
Schema validation includes the v1 -> v2 `session_type` migration.
## 8. C validation
Current pre-push validation includes:
- normal strict-warning build;
- the complete Meson test suite;
- `git diff --check`;
- frozen JSON v1 validators.
ASan/UBSan is run for meaningful implementation checkpoints before declaring a
gate complete.
## 9. Pre-push checklist
Before every meaningful push:
1. run `python tools/validate_json.py`;
2. run `python tools/validate_import_contract.py`;
3. run `meson compile -C build`;
4. run `meson test -C build --print-errorlogs`;
5. run sanitizers when relevant;
6. run `git diff --check`;
7. inspect `git status --short`;
8. review documentation changes.
## 10. Catalog reconciliation contract
Before the C17 importer exists, Gate 1 defines local catalog merge behavior through an executable Python specification.
Run:
```bash
python tools/validate_import_contract.py
```
Canonical cases cover:
- exact existing exercise reuse;
- same identity with renamed display text;
- same identity with incompatible tracking mode;
- different identities with equivalent normalized names;
- new unique exercise creation.
The full Gate 1 validation command is:
```bash
python tools/validate_json.py
python tools/validate_import_contract.py
git diff --check
```
<!-- TRAINLOG_MTP_VALIDATION -->
## 11. USB/MTP transport validation
The compiled suite now contains:
```text
usb
mtp
```
The `usb` test covers API validation, physical-device enumeration invariants,
and rejection of duplicated USB interface children.
The `mtp` test covers bounded API argument validation for storage, folder,
upload, listing, and download entry points.
Hardware probes additionally validate the real device path:
```text
trainlog-usb-probe
trainlog-mtp-probe
trainlog-mtp-exchange-probe
trainlog-mtp-roundtrip-probe
```
Physical checkpoint result:
```text
MTP devices: 1
ROUNDTRIP=PASS Trainlog/trainlog-probe.txt
```
The hardware probe is intentionally separate from the normal automated test
suite because CI is not expected to have a connected unlocked Android MTP
device.
<!-- TRAINLOG_MTP_VALIDATION _END -->
<!-- TRAINLOG_CONTINUOUS_TEST_CHECKPOINT -->
## Profile-aware / continuous validation
Expected normal test suite after this checkpoint:
```text
15 tests
```
Coverage added around:
```text
exercise profile schema
profiled catalog creation
schema migration
continuous session persistence
continuous session detail loading
```
Manual TUI validation includes:
```text
Marche configured CONTINUOUS + DURATION + SPEED_KMH
entry asks duration minutes + speed
no sets/rest/load prompts
continuous_activity row persisted
performed_sets count remains zero
history reopens as continuous
duration and speed render correctly
```
<!-- TRAINLOG_CONTINUOUS_TEST_CHECKPOINT _END -->