test(kc): test fixtures and automated round-trip tests for .kc file handling #46

Open
opened 2026-02-18 21:19:33 +00:00 by forbes · 0 comments
Owner

Summary

Create .kc test fixtures and automated tests that verify the full document lifecycle: open, parse silo/ entries, create tree objects, edit metadata, save, reopen, and confirm round-trip integrity. Currently there are zero tests and zero .kc fixtures in the repository.

Background

The .kc file handling system spans multiple components:

  • kc_format.py — ZIP round-trip preservation
  • silo_tree.py — tree object creation from silo/ entries
  • silo_objects.py — transient document objects
  • silo_document.py — document observer lifecycle hooks
  • kindred_document.pysilo/ parsing and serialization
  • silo_viewers.py — viewer widgets (dirty tracking, save-back)

None of these have tests. The Prop_Transient flag behavior, observer registration ordering, and ZIP manipulation all have edge cases that need automated coverage.

Scope

Test fixtures

Create minimal .kc ZIP files in a fixtures directory for test use:

Fixture Contents
minimal.kc FreeCAD standard zone (minimal Document.xml, empty GuiDocument.xml) + silo/manifest.json only
full.kc All silo/ entry types: manifest, metadata, history, approvals, dependencies, one job YAML, one macro .py
no-silo.fcstd Standard .fcstd with no silo/ directory (regression: must not create Silo tree)
stale-stubs.kc .kc with Silo object stubs in Document.xml from a previous save (tests cleanup)
empty-groups.kc .kc with empty silo/jobs/ and silo/macros/ directories (tests conditional node creation — no empty groups)

Fixture location: tests/fixtures/ or src/Mod/Create/tests/fixtures/

Unit tests

kc_format.py tests

  • Round-trip: save a .kc, verify silo/ entries are preserved
  • Manifest auto-creation: save a file without silo/manifest.json, verify it is created
  • modified_at update: save twice, verify timestamp changes
  • pre_reinject callback: register callback, verify it receives and can modify cache dict
  • Non-.kc files: save a .fcstd, verify no silo/ entries are injected

silo_tree.py tests

  • Conditional node creation: parse full.kc, verify all expected tree nodes are created
  • Minimal node creation: parse minimal.kc, verify only Silo > Manifest exists
  • Empty groups suppressed: parse empty-groups.kc, verify no Jobs/Macros groups created
  • Stale stub cleanup: parse stale-stubs.kc, verify old stubs are removed before new tree is created
  • .fcstd no-op: parse no-silo.fcstd, verify no Silo tree objects created

silo_objects.py tests

  • Transient properties: create SiloViewerObject, verify all properties have Prop_Transient flag
  • Serialization: verify __getstate__ returns None
  • Content types: verify JSON content is correctly serialized/deserialized via RawContent

silo_document.py tests

  • Observer registration: verify slotCreatedDocument fires and triggers tree creation for .kc
  • Observer no-op for .fcstd: verify slotCreatedDocument does not trigger tree creation
  • Document close cleanup: verify Silo tree objects are removed on slotDeletedDocument

kindred_document.py tests

  • Parse all entry types: open full.kc, verify each silo/ entry is correctly parsed
  • Save-back round-trip: modify metadata via RawContent, save, reopen, verify changes persisted
  • Promotion: promote a .fcstd to .kc, verify silo/manifest.json is created with UUID

Integration tests (require FreeCAD runtime)

  • Full lifecycle: open full.kc → verify tree → double-click Manifest → verify viewer opens → edit metadata → save → reopen → verify edits persisted
  • Demotion: open .kc, Save As .fcstd, verify no silo/ directory in result
  • Vanilla FreeCAD compatibility: open .kc fixture in FreeCAD without Create module, verify no errors

Technical notes

  • FreeCAD test harness: FreeCAD provides unittest-based testing via freecad.app module. Tests can be run headless with freecadcmd -t TestModule.
  • GUI tests: Viewer widget tests require freecad.gui (needs display or xvfb). Keep these separate from headless tests.
  • ZIP manipulation: Use Python's zipfile module to create fixtures programmatically in test setup, or check in pre-built .kc files.
  • Prop_Transient verification: The C++ source confirms flag value 2 works for dynamic properties (PropertyContainer.cpp:211), but this should be explicitly tested since no existing Python code in this codebase uses it.

Acceptance criteria

  • At least 5 .kc test fixtures exist covering the cases above
  • kc_format.py round-trip tests pass
  • silo_tree.py conditional creation tests pass
  • silo_objects.py transient property tests pass
  • Prop_Transient flag is verified to exclude property content from Document.xml
  • All tests can be run via freecadcmd in CI
  • Tests are documented in a test manifest or README

Dependencies

  • Phase 1 foundation (#37) — for silo_objects.py, silo_tree.py, silo_document.py
  • Layer 2 KindredDocument (#45) — for kindred_document.py tests

References

  • docs/KC_SPECIFICATION.md §6 (acceptance criteria per layer)
  • docs/SILO_VIEWPORT_PLAN.md (Risks section — Prop_Transient verification)
  • FreeCAD test documentation: src/Mod/Test/
## Summary Create `.kc` test fixtures and automated tests that verify the full document lifecycle: open, parse `silo/` entries, create tree objects, edit metadata, save, reopen, and confirm round-trip integrity. Currently there are zero tests and zero `.kc` fixtures in the repository. ## Background The `.kc` file handling system spans multiple components: - `kc_format.py` — ZIP round-trip preservation - `silo_tree.py` — tree object creation from `silo/` entries - `silo_objects.py` — transient document objects - `silo_document.py` — document observer lifecycle hooks - `kindred_document.py` — `silo/` parsing and serialization - `silo_viewers.py` — viewer widgets (dirty tracking, save-back) None of these have tests. The `Prop_Transient` flag behavior, observer registration ordering, and ZIP manipulation all have edge cases that need automated coverage. ## Scope ### Test fixtures Create minimal `.kc` ZIP files in a fixtures directory for test use: | Fixture | Contents | |---------|----------| | `minimal.kc` | FreeCAD standard zone (minimal `Document.xml`, empty `GuiDocument.xml`) + `silo/manifest.json` only | | `full.kc` | All `silo/` entry types: manifest, metadata, history, approvals, dependencies, one job YAML, one macro .py | | `no-silo.fcstd` | Standard `.fcstd` with no `silo/` directory (regression: must not create Silo tree) | | `stale-stubs.kc` | `.kc` with Silo object stubs in `Document.xml` from a previous save (tests cleanup) | | `empty-groups.kc` | `.kc` with empty `silo/jobs/` and `silo/macros/` directories (tests conditional node creation — no empty groups) | Fixture location: `tests/fixtures/` or `src/Mod/Create/tests/fixtures/` ### Unit tests #### `kc_format.py` tests - [ ] Round-trip: save a `.kc`, verify `silo/` entries are preserved - [ ] Manifest auto-creation: save a file without `silo/manifest.json`, verify it is created - [ ] `modified_at` update: save twice, verify timestamp changes - [ ] `pre_reinject` callback: register callback, verify it receives and can modify cache dict - [ ] Non-`.kc` files: save a `.fcstd`, verify no `silo/` entries are injected #### `silo_tree.py` tests - [ ] Conditional node creation: parse `full.kc`, verify all expected tree nodes are created - [ ] Minimal node creation: parse `minimal.kc`, verify only Silo > Manifest exists - [ ] Empty groups suppressed: parse `empty-groups.kc`, verify no Jobs/Macros groups created - [ ] Stale stub cleanup: parse `stale-stubs.kc`, verify old stubs are removed before new tree is created - [ ] `.fcstd` no-op: parse `no-silo.fcstd`, verify no Silo tree objects created #### `silo_objects.py` tests - [ ] Transient properties: create `SiloViewerObject`, verify all properties have `Prop_Transient` flag - [ ] Serialization: verify `__getstate__` returns `None` - [ ] Content types: verify JSON content is correctly serialized/deserialized via `RawContent` #### `silo_document.py` tests - [ ] Observer registration: verify `slotCreatedDocument` fires and triggers tree creation for `.kc` - [ ] Observer no-op for `.fcstd`: verify `slotCreatedDocument` does not trigger tree creation - [ ] Document close cleanup: verify Silo tree objects are removed on `slotDeletedDocument` #### `kindred_document.py` tests - [ ] Parse all entry types: open `full.kc`, verify each `silo/` entry is correctly parsed - [ ] Save-back round-trip: modify metadata via `RawContent`, save, reopen, verify changes persisted - [ ] Promotion: promote a `.fcstd` to `.kc`, verify `silo/manifest.json` is created with UUID ### Integration tests (require FreeCAD runtime) - [ ] Full lifecycle: open `full.kc` → verify tree → double-click Manifest → verify viewer opens → edit metadata → save → reopen → verify edits persisted - [ ] Demotion: open `.kc`, Save As `.fcstd`, verify no `silo/` directory in result - [ ] Vanilla FreeCAD compatibility: open `.kc` fixture in FreeCAD without Create module, verify no errors ## Technical notes - **FreeCAD test harness**: FreeCAD provides `unittest`-based testing via `freecad.app` module. Tests can be run headless with `freecadcmd -t TestModule`. - **GUI tests**: Viewer widget tests require `freecad.gui` (needs display or `xvfb`). Keep these separate from headless tests. - **ZIP manipulation**: Use Python's `zipfile` module to create fixtures programmatically in test setup, or check in pre-built `.kc` files. - **`Prop_Transient` verification**: The C++ source confirms flag value `2` works for dynamic properties (`PropertyContainer.cpp:211`), but this should be explicitly tested since no existing Python code in this codebase uses it. ## Acceptance criteria - [ ] At least 5 `.kc` test fixtures exist covering the cases above - [ ] `kc_format.py` round-trip tests pass - [ ] `silo_tree.py` conditional creation tests pass - [ ] `silo_objects.py` transient property tests pass - [ ] `Prop_Transient` flag is verified to exclude property content from `Document.xml` - [ ] All tests can be run via `freecadcmd` in CI - [ ] Tests are documented in a test manifest or README ## Dependencies - Phase 1 foundation (#37) — for `silo_objects.py`, `silo_tree.py`, `silo_document.py` - Layer 2 KindredDocument (#45) — for `kindred_document.py` tests ## References - `docs/KC_SPECIFICATION.md` §6 (acceptance criteria per layer) - `docs/SILO_VIEWPORT_PLAN.md` (Risks section — `Prop_Transient` verification) - FreeCAD test documentation: `src/Mod/Test/`
forbes added the enhancement label 2026-02-18 21:19:33 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: kindred/silo-mod#46