Skip to content

test: pin five documented behaviors that no test covered - #41

Merged
dmccoystephenson merged 2 commits into
mainfrom
test/pin-documented-behaviors
Aug 24, 2026
Merged

test: pin five documented behaviors that no test covered#41
dmccoystephenson merged 2 commits into
mainfrom
test/pin-documented-behaviors

Conversation

@dmccoystephenson

@dmccoystephenson dmccoystephenson commented Aug 24, 2026

Copy link
Copy Markdown
Member

Summary

Five behaviors are already promised by the docstrings, the README, or a source
comment, but were not exercised by any test. They are pinned here as
characterization tests. No production code is changed.

  • Default display size. Graphik() is documented as falling back to a
    900x600 window; the existing test only asserted that some display was
    created. The size assertion was folded into that existing test rather than
    added as a second one, since it strictly subsumes it.
  • Package __getattr__ miss path. Defining __getattr__ on
    preponderous.graphik takes over every failed attribute lookup, so the miss
    path has to keep raising AttributeError. Nothing covered that branch.
  • Per-path image cache. Both drawImage caches are keyed on filePath
    alone. A second asset getting its own entry — rather than evicting the first
    or being served the first's surface — was untested.
  • drawRectangle fill bounds. drawButton's hit test is written against
    xpos through xpos + width - 1 (see PR fix: make drawButton's clickable region match the box it draws #37), but the bounds were only
    pinned on the button, not on the fill they are anchored to.
  • Font cache across a resize. The session check compares display surface
    objects, and set_mode returns the same object when only the size changes.
    That is what keeps a resize from discarding the font cache, and the existing
    invalidation tests pass either way.

Each addition was confirmed to bite: the source was temporarily mutated (default
size changed, the AttributeError replaced with return None, the image cache
key made constant, the rectangle fill narrowed by a pixel, the session check
forced to always invalidate) and every corresponding test failed, then passed
again once the source was restored. The working tree was verified clean
afterwards.

Deferred issues

The three open issues were all skipped this cycle, each for a reason recorded
here rather than as a comment on the issue:

Test plan

  • python -m pytest — 41 passed (37 before; four tests added and one
    assertion folded into an existing test), headless via conftest.py.
  • python -m py_compile src/main/python/preponderous/graphik/graphik.py
  • Import smoke test: import preponderous.graphik prints 0.3.0.dev20260808.
  • Mutation check per addition, described above.
  • CI (test.yml) green across Python 3.9–3.13.

No tracking issue — this is a test-expansion cycle, so nothing is auto-closed.

This PR description was drafted during a Gardener session (https://github.com/Stephenson-Software/gardener).


drafted by Claude on behalf of Daniel Stephenson

dmccoystephenson and others added 2 commits August 24, 2026 01:09
Adds characterization tests for behavior the docstrings, README and source
comments already promise but the suite never exercised: the 900x600 default
display size, the package __getattr__ miss path, the per-path image cache,
drawRectangle's exact fill bounds, and the font cache surviving a resize.

Each was confirmed to fail against a mutated source before landing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The new test asserted a strict superset of test_no_arg_constructor_creates_
default_display, so keep one test and add the size assertion to it rather than
leaving two tests covering the same constructor call.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@dmccoystephenson

Copy link
Copy Markdown
Member Author

Self-review rubric

  • Scope: PASSgit diff --name-only origin/main...HEAD lists one file, src/test/python/preponderous/graphik/test_graphik.py. No production source, docs, or version file is touched.
  • Tests-new: NOT APPLICABLE — no new public method is added; this is a characterization-only cycle.
  • Tests-fix (empirical): PASS — no bug is fixed here, so the stash-and-run equivalent was run as a mutation check instead. Each addition was verified against a deliberately broken source: displayWidth = 900800, the package __getattr__'s raise AttributeErrorreturn None, drawImage's cache key forced to a constant, pygame.draw.rect's extent narrowed to width - 1/height - 1, and _getFont's if display is not self._fontDisplay forced to if True. Every corresponding test failed under its mutation and passed once the source was restored, and git status confirmed the source was left unmodified.
  • Sibling structure: PASS — no new file is created; each addition sits beside the sibling that covers the same method, and follows the file's existing shape (module-level test_* function, leading _-prefixed helper reuse, a comment stating why the behavior is worth pinning).
  • Sibling renames: NOT APPLICABLE — nothing is renamed.
  • Docs: PASS — no behavior changed, so no row of the documentation sources-of-truth table is affected. The README's 900x600 and xpos + width - 1 claims and the _getFont comment are now asserted by tests rather than described only in prose.
  • Issue resolution: NOT APPLICABLE — no Closes #N is claimed. The three open issues are deferred with reasons recorded in the PR body.
  • CI: PASS — all five matrix jobs (Python 3.9 through 3.13) pass on the PR head; run 32700291260. Locally, python -m pytest reports 41 passed (37 on main).
  • camelCase: PASS — no public member is added or renamed. Local variables in the new tests (redPath, bluePath, resized, constructed) follow the file's existing camelCase/lowercase mix.
  • Backward-compat: PASS — the diff contains no production change, so no member of the public surface consumed by Roam, Apex, Ophidian, Patchwork or Tic-Tak-Toe can have moved.
  • Headless: PASS — every addition reuses _make_graphik / pygame.display.set_mode under the SDL_VIDEODRIVER=dummy and SDL_AUDIODRIVER=dummy defaults set by src/test/python/conftest.py. No new test requires a real display, audio device, or network. Confirmed by the CI matrix, which runs on a headless runner.
  • Version sync: NOT APPLICABLE — no version string changed.
  • No new deps: PASS — the additions import nothing that the file did not already import (pygame, pytest, stdlib).

Findings

Two observations are recorded rather than fixed, both judgment calls:

src/test/python/preponderous/graphik/test_graphik.py:439 — the resize test opens with assert resized is graphik.getGameDisplay(), "resize returned a new surface". That assertion is about pygame's own behavior, not Graphik's, so if a future pygame returns a fresh surface from a resizing set_mode, the failure will be reported by a Graphik font-cache test rather than by something that names the real cause. The message was written to make that legible, and the precondition is kept because without it the test would silently degrade into asserting nothing.

src/test/python/preponderous/graphik/test_graphik.py:279test_draw_rectangle_fills_exactly_the_requested_region sits next to the pre-existing test_draw_rectangle_fills_expected_region_with_color and the two overlap: both draw the same 5x5 rectangle and both check a pixel outside it. They were deliberately left separate because neither subsumes the other — the older test checks an interior pixel (which a hollow outline would fail) and the new one checks the four corners and the four coordinates just past each far edge (which a one-pixel-short fill would fail). The analogous overlap on the constructor test was not left standing: that addition was a strict superset of its sibling, so it was folded into the existing test in 54f4b97 instead of landing as a second test.

One cross-cutting note that is out of this diff's scope: three of the five behaviors pinned here are asserted only by their own source comment or a README line, which is what made them easy to miss. A short convention that a documented invariant carries a test would prevent the next one, but that belongs in the repository's contributing guidance rather than in this PR.

This review was drafted during a Gardener session (https://github.com/Stephenson-Software/gardener).


drafted by Claude on behalf of Daniel Stephenson

@dmccoystephenson
dmccoystephenson merged commit 632bd35 into main Aug 24, 2026
5 checks passed
@dmccoystephenson
dmccoystephenson deleted the test/pin-documented-behaviors branch August 24, 2026 07:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant