Skip to content

CI (PR 820): nested-package addons — tests not discovered/loaded; need recursive discovery + per-addon import root #52

Description

@eduralph

Summary

The CI test pipeline (PR 820) assumes a flat addon layout. A nested-package
addon — one whose tests live in sub-packages under <Addon>/tests/ and import
the addon's own top-level package — is neither discovered nor loadable by
the current unit-test job. The suite silently does not run.

Background

NameSuite (upstream PR 941) is the first nested-package addon. Its tests sit
under NameSuite/tests/{controllers,models,presentation,repositories,e2e,…}/test_*.py
and import both the addon library and the addon's own test helpers as top-level
packages:

from name_processor.controllers.gramplet import GrampletController
from tests.fakes.sync_task_runner import SynchronousTaskRunner
from tests.fixtures import setup_sample_family

i.e. the suite expects to run with NameSuite/ as the import root (where both
name_processor and tests resolve), exactly as Gramps' plugin loader puts the
addon dir on sys.path at runtime (gramps/gen/plug/_manager.py:311).

Problem

1. Discovery is one level deep. The unit-test job globs */tests/test_*.py
(and the integration job */tests/test_integration_*.py). NameSuite has no
flat test_*.py under tests/ — every suite is nested — so the glob matches
nothing and the entire suite is skipped with no signal. Silent zero coverage.

2. The runner can't load nested-package tests even if found.
run_addon_tests.py loads by dotted module name from the repo root with
PYTHONPATH=. (unittest.defaultTestLoader.loadTestsFromName,
run_addon_tests.py:88). A nested test imports top-level name_processor, which
is only importable when the addon dir is on sys.path. The unit runner never
adds it — unlike the plugin-registration test, which goes through Gramps'
pmgr.load_plugin (tests/test_plugin_registration.py:200), and unlike Gramps
itself (_manager.py:311). So a nested module hits an import-time load error,
and since its system deps are satisfiable, run_addon_tests.py:133 classifies it
a hard FAIL.

3. Interaction with the reserved top-level tests namespace (PR 950).
PR 950 reserves the repo-root top-level tests package as the shared
Gramps-emulation environment, consumed as from tests.gramps_test_env import GrampsTestCase with the repo root on sys.path. An addon that (a) gets its own
dir put on sys.path and (b) also defines a top-level tests package collides
with that shared name. NameSuite does both. The resolution is a split:

  • Addon side: addons must namespace their private test support and not squat
    the reserved top-level tests name — i.e. relative imports within the addon's
    own package (from .fixtures import …, addressed as <Addon>.tests.*).
  • CI side: the runner must add the per-addon dir as the import root while
    keeping the shared top-level tests env intact.

Per-module subprocess isolation (run_addon_tests.py:111) makes this safe: only
one addon's namespace is ever live per worker process, so generic names like
tests / name_processor don't clash across addons.

Proposed fix

  • Recursive discovery for both the unit and integration buckets — walk
    <Addon>/tests/**/test_*.py instead of one level.
  • Per-addon import root — when running an addon's modules, insert <Addon>/
    on sys.path and load by the addon-relative name, mirroring Gramps' loader.
    This is also more correct for flat addons, whose tests already import the
    addon's own top-level module — so it's a general fix, not a NameSuite special
    case.
  • Document/enforce the namespace contract — top-level tests is reserved for
    the shared env; addons use relative imports for private test support.
  • Coordinate with Extend make.py with a 'unittest' command to run an addon's tests with the Gramps environment applied #49 (the planned make.py unittest command): it shares
    this runner, and as specified there (python3 -m unittest Form.tests.test_x)
    it carries the same flat-addon assumption. The per-addon-import-root change
    should land in that command too, so a nested addon's suite runs through the
    same single entry point.

Caveat — verify before switching

Confirm how the existing flat-addon suites import today (whether any rely on
the addon dir being on sys.path, or only import gramps + stdlib) before moving
to per-addon import roots, so we don't regress suites that currently pass. The
change should be a strict superset of today's behaviour for flat addons.

Acceptance criteria

  • A nested-package addon's tests are discovered and executed (verify the
    NameSuite suites run and report real pass/fail counts, not a silent skip).
  • Flat-addon suites continue to pass unchanged.
  • The shared top-level tests Gramps-emulation env still loads
    (from tests.gramps_test_env import GrampsTestCase works in the full-suite run).
  • An addon defining its own <Addon>/tests/<subpkg>/ does not shadow the shared
    tests package.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions