test(parity): assert Node and Python mappers emit equivalent project-map (closes #98)#113
Merged
Merged
Conversation
Closes #98. The repo carries two independent implementations of the same mapping logic — `bin/mapper-artifacts.js` + `bin/map.js` on the Node side and `simplicio_mapper.mapper` + `simplicio_mapper.cli` on the Python side — that both emit the `simplicio.*/v1` schemas defined in `SIMPLICIO_INTEGRATION.md`. Until now nothing verified the two stay in lockstep, so any heuristic change to one (roles, importance, symbol/import regexes, layer detection) could silently diverge. Adds: - `tests/fixtures/parity-host/` — a small deterministic Node fixture with `package.json`, two source files (entrypoint + helper module), one test file, and an `express` dependency so the architecture-signal detector has something to find. - `tests/python/test_parity.py` — runs `node bin/cli.js map` and the Python `write_mapping_artifacts` against the same fixture (copied into two temp trees so they do not clobber each other) and asserts the resulting `project-map.json` agrees on schema, the file inventory set, entry points, test files, architecture signals, and the per-path roles map. A helper strips the intentionally volatile `generated_at` and `product.root` fields before comparison. The whole class is `@skipUnless(node-on-PATH)` so local Python-only contributors still get a clean run. - `.gitignore` whitelist for `tests/fixtures/` so the fixture can ship. - `.github/workflows/python-ci.yml` now installs Node 22 in the pytest matrix so the parity assertions run in CI. Any heuristic change applied to only one implementation will fail at least one of the seven parity assertions. https://claude.ai/code/session_01JdmemqddwFnvbceWyuDE8m
The fixture file was named `tests/server.test.js` to make role detection classify it as a test file, but `node --test` discovers `**/*.test.js` recursively across the repo, so it tried to load the fixture from outside its sandbox — failing because the fixture's `express` dependency is not installed in the main CI suite. Rename it to `tests/server-fixture.js`. Path-based role detection (`tests/`) still classifies it as a test file, so the parity assertion on `test_files` continues to hold. https://claude.ai/code/session_01JdmemqddwFnvbceWyuDE8m
Contributor
There was a problem hiding this comment.
Pull request overview
Adiciona um teste de paridade para garantir que os mappers em Node e Python emitam resultados equivalentes ao mapear um fixture determinístico, evitando divergências silenciosas entre as duas implementações.
Changes:
- Adiciona fixture determinístico
tests/fixtures/parity-host/para servir de input comum aos dois runtimes. - Cria
tests/python/test_parity.pyque executa o mapper em Node e em Python e compara campos-chave doproject-map.json. - Ajusta
.gitignorepara versionartests/fixtures/e atualiza o workflowpython-ci.ymlpara instalar Node (necessário para o teste de paridade).
Reviewed changes
Copilot reviewed 6 out of 7 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/python/test_parity.py | Adiciona teste de paridade Node ↔ Python (atualmente focado em project-map.json). |
| tests/fixtures/parity-host/tests/server-fixture.js | Fixture: arquivo de teste JS para acionar detecção de “test files/roles”. |
| tests/fixtures/parity-host/src/index.js | Fixture: entrypoint simples com express para sinais/roles. |
| tests/fixtures/parity-host/src/greet.js | Fixture: módulo auxiliar para símbolos/imports. |
| tests/fixtures/parity-host/package.json | Fixture: manifest com dependency express para arquitetura/sinais. |
| .gitignore | Passa a versionar tests/fixtures/. |
| .github/workflows/python-ci.yml | Instala Node 22 no job de pytest para rodar o teste de paridade. |
Comment on lines
+3
to
+7
| Both `bin/mapper-artifacts.js` (invoked via `node bin/cli.js map`) and the | ||
| Python `simplicio_mapper.cli` emit `simplicio.*/v1` artifacts. Running them | ||
| against the same fixture must produce equivalent shape — schema, file set, | ||
| entry points, roles, architecture signals, symbol names, call-graph edge | ||
| counts — modulo intentionally volatile fields like `generated_at` and the |
Comment on lines
+55
to
+68
| def _node_map(self) -> dict: | ||
| result = subprocess.run( | ||
| ["node", str(ROOT / "bin" / "cli.js"), "map", "--root", str(self.node_root)], | ||
| capture_output=True, | ||
| text=True, | ||
| check=False, | ||
| timeout=60, | ||
| ) | ||
| self.assertEqual(result.returncode, 0, msg=result.stderr) | ||
| return json.loads((self.node_root / ".simplicio" / "project-map.json").read_text()) | ||
|
|
||
| def _python_map(self) -> dict: | ||
| write_mapping_artifacts(cwd=str(self.python_root), meta={"product_name": "parity-host"}) | ||
| return json.loads((self.python_root / ".simplicio" / "project-map.json").read_text()) |
Comment on lines
+113
to
+116
| # generated_at must be absent from both after normalize. | ||
| self.assertNotIn("generated_at", n) | ||
| self.assertNotIn("generated_at", p) | ||
|
|
Comment on lines
+64
to
+68
| return json.loads((self.node_root / ".simplicio" / "project-map.json").read_text()) | ||
|
|
||
| def _python_map(self) -> dict: | ||
| write_mapping_artifacts(cwd=str(self.python_root), meta={"product_name": "parity-host"}) | ||
| return json.loads((self.python_root / ".simplicio" / "project-map.json").read_text()) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Resumo
Fecha #98. Adiciona teste de paridade Node ↔ Python para os artefatos do mapper.
Mudanças
tests/fixtures/parity-host/— fixture determinística (package.json +expressdep, 2 sources, 1 test).tests/python/test_parity.py— copia o fixture para 2 temp dirs, rodanode bin/cli.js mapem um ewrite_mapping_artifactsno outro, compara:files[]set (paths)entry_pointstest_filesarchitecture.signals_normalizeremovegenerated_ateproduct.root(volatile).@skipUnless(node-on-PATH)para dev local Python-only..gitignore— whitelisttests/fixtures/..github/workflows/python-ci.yml— instala Node 22 no matrix pytest pra rodar o teste em CI.Acceptance
generated_at,product.root) excluídos.Validação local
python -m unittest tests.python.test_parityRefs #98.
https://claude.ai/code/session_01JdmemqddwFnvbceWyuDE8m
Generated by Claude Code