Skip to content

soccer-scoreboard: all 22 favorite-team tests fail on main — stub list is missing src.common.sports_shared #468

Description

@ChuckBuilds

Summary

All 22 tests in soccer-scoreboard/test_favorite_team_diagnostics.py fail on main. The file stubs the core modules the plugin's import chain reaches, but the stub list never gained src.common.sports_shared, which soccer-scoreboard/sports.py now imports at module load.

E   ModuleNotFoundError: No module named 'src.common.sports_shared'
22 failed in 0.72s

Reproduction

cd <ledmatrix-plugins>/plugins/soccer-scoreboard
PYTHONPATH=<core> LEDMATRIX_CORE=<core> python3 -m pytest test_favorite_team_diagnostics.py -q

Fails identically with a core checkout of main that does contain src/common/sports_shared.py, because the stubs are installed into sys.modules before the real import is attempted.

Cause

test_favorite_team_diagnostics.py:20-25:

# manager.py's import chain reaches src.logo_downloader, src.background_data_service,
# src.common.scroll_helper and src.plugin_system.base_plugin at module load. Stub
# them so the import succeeds; instances are built via __new__ so none is called.
if "src.logo_downloader" not in sys.modules:
    ...

That comment is an accurate list of what the chain reached when it was written. sports.py has since added src.common.sports_shared (and src.common.sports_card in the sibling lineages), and the stub list did not follow.

Why nobody noticed

This is one of the 11 pytest-style files at plugin root that scripts/run_plugin_tests.py runs as a script and reports as passing without executing (#464). Before that fix the runner prints:

  [pass] test_favorite_team_diagnostics.py
24 passed, 0 skipped, 0 failed

and after it:

  [FAIL] test_favorite_team_diagnostics.py -- FAILED ... (+19 more)
23 passed, 0 skipped, 1 failed

Same code, same core — the second is simply the first honest report.

Suggested fix

Add the missing module to the stub block, and consider stubbing by prefix rather than by name so the next core dependency doesn't silently break it:

for name in ("src.common.sports_shared", "src.common.sports_card"):
    if name not in sys.modules:
        sys.modules[name] = types.ModuleType(name)

The mixin names the plugin imports from it (SportsCoreSharedMixin, SportsLiveSharedMixin, SportsRecentSharedMixin) need to exist on the stub for the from ... import to succeed.

Worth checking the sibling lineages at the same time — per docs/plugin-development/08-shared-sports-code.md, sports.py is copied rather than shared, so afl / baseball / basketball / football / hockey / lacrosse / nrl likely have the same stale stub lists.

Context

This is the fifth stale hand-built test double found in quick succession — after _font_cache (baseball, #463), _Ticker (odds-ticker, on #462), and fake_fetch + FakeLogger (flights, #465). Each was invisible until something forced the test to actually execute. That consistency is probably an argument for a CI check that stand-ins stay compatible with what they stand in for.

Environment

Found while validating ChuckBuilds/LEDMatrix#534 and #466 on a 256x64 rig. Confirmed identical on main and on the PR branch, so it is pre-existing and not introduced by either.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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