Skip to content

Characterize LivingEntity with a dedicated test suite, and add the missing src/world/__init__.py - #48

Merged
dmccoystephenson merged 3 commits into
masterfrom
feature/living-entity-tests
Aug 11, 2026
Merged

Characterize LivingEntity with a dedicated test suite, and add the missing src/world/__init__.py#48
dmccoystephenson merged 3 commits into
masterfrom
feature/living-entity-tests

Conversation

@dmccoystephenson

@dmccoystephenson dmccoystephenson commented Aug 11, 2026

Copy link
Copy Markdown
Member

Summary

Two gaps in src/ structural quality, both found during the same triage pass, are addressed here.

  • LivingEntity is now characterized end to end. The core domain class had no dedicated test file and sat at 53% line coverage, with getNextAction, reproduce, befriend, the four chance adjusters and regenerateHealth entirely unexercised. tests/test_living_entity.py adds 57 tests across construction, movement rolls, action selection, reproduction, fighting, befriending, behavioural-chance adjustment, relationship tracking, isAlive and regeneration. src/entity/livingEntity.py goes from 53% to 100%; the repository total goes from 59% to 72%.
  • src/world/__init__.py is added. src/world was the only package directory under src/ without one, which contradicts the rule stated at .github/copilot-instructions.md:39 ("Each module should have an __init__.py file"). Imports resolve today only because the directory is picked up as an implicit namespace package; a future find_packages() build would silently omit it while including its five siblings. The file carries the same two-line header those siblings carry and nothing else.

No production behavior is changed by this pull request. Per the test-expansion convention, the new tests assert what the code does today rather than what it arguably should do.

Behavior deliberately pinned rather than fixed

Four quirks were surfaced while writing these tests. Each is asserted as-is, with a comment recording why, and none is changed here:

Test plan

  • python3 -m compileall -q src — clean
  • python3 -m pytest --verbose -vv --cov=src --cov-report=term-missing --cov-report=xml:cov.xml — 123 passed, up from 66 on master
  • src/entity/livingEntity.py reports 100% line coverage, with no lines listed as missing
  • black run against the two changed files only; no unrelated file was reformatted
  • Every new test exercises a real branch: the suite was written against the coverage report's missing-line list, and the remaining gap at lines 98-99 was closed by a dedicated counter-attack damage-reduction test

Closes #47

Backlog deferred this cycle

Every other open issue was left untouched, for the reasons below:

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 11, 2026 01:05
src/world was the only package under src/ without an __init__.py, which contradicts the file-structure rule in .github/copilot-instructions.md and would leave the package out of a setuptools find_packages() build. The file carries the same two-line header as its five siblings.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
LivingEntity is the core domain class and had no dedicated test file, sitting at 53% line coverage. These 57 characterization tests assert current behavior across construction, movement rolls, action selection, reproduction, fighting, befriending, the four chance adjusters, relationship tracking, isAlive and regeneration, taking the module to 100%.

No production behavior is changed. Several quirks are deliberately pinned rather than fixed: friendship is matched by name rather than identity, the "nothing" branch of getNextAction does not increment numActionsTaken, befriend permits duplicate friendships, and regenerateHealth does not check isAlive.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A directory without __init__.py is still importable as an implicit namespace package, so nothing fails at run time and the omission goes unnoticed until packaging. This asserts the convention directly, and was confirmed to fail when src/world/__init__.py is moved aside.

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

Copy link
Copy Markdown
Member Author

Self-review

Scored against the local test suite as the external anchor, on head 796995e. Each line cites the command output or diff hunk it is grounded in rather than a judgement.

Anchor: python3 -m pytest --verbose -vv --cov=src --cov-report=term-missing --cov-report=xml:cov.xml126 passed, up from 66 on master. python3 -m compileall -q src is clean. No CI check is reported for this branch: .github/workflows/run-program.yml is the repository's only workflow and it scripts an expect play-through rather than running pytest, so it would be informational regardless.

Item Score Grounding
Scope PASS git diff --stat origin/master...HEAD is 3 files, 563 insertions and 0 deletions — no existing file is touched, so no unrelated formatting or comment churn is possible. black was run against the three changed files individually, never ./format.sh tree-wide.
Tests-new PASS src/world/__init__.py declares no callable. The other two files are themselves tests; their one helper, getPackageDirectories, is exercised by all three tests in that class.
Tests-fix PASS Confirmed empirically, not by reasoning. With src/world/__init__.py moved aside via git mv, test_every_source_directory_is_a_regular_package fails with AssertionError: Lists differ: ['world'] != []; with it restored, 126 pass.
Sibling structure PASS with a noted deviation Both new files open with the two-line # Copyright (c) 2022 Daniel McCoy Stephenson / # Apache License 2.0 header and close with if __name__ == "__main__": unittest.main(), matching tests/test_names.py and tests/test_integration.py. src/world/__init__.py is byte-identical to src/stats/__init__.py (diff reports no difference). The deviation is recorded below.
Sibling renames Not applicable Nothing is renamed; the diff is additions only.
Docs PASS The Phase 7 table was walked. No claim in README.md, .github/copilot-instructions.md or COPYRIGHT.md is invalidated by an additive test-only change. .github/copilot-instructions.md:39 ("Each module should have an __init__.py file") becomes true for the first time. src/config/names.json is untouched and still self-consistent at metadata.total_count == len(names) == 403.
Issue resolution PASS #47's named surface area is src/world/__init__.py; that file now exists with the contents the issue specified.
Local test suite PASS See anchor above.
Copyright header PASS Verified on all three new files by reading the first two bytes-on-disk lines, not by assumption.
Indentation PASS grep -c "\t" returns 0 for all three files. 4-space throughout, matching the real source rather than the tab claim .github/copilot-instructions.md still carries (tracked separately as #42).
Names-config sync Not applicable src/config/names.json is not modified by this pull request.

Findings

An all-PASS table invites suspicion, so the three things that were genuinely close calls are recorded here rather than smoothed over.

  • tests/test_living_entity.py:278test_the_fight_always_ends_with_exactly_one_survivor is the only test in this pull request that runs against unpatched randomness. It is not a flake: fight()'s counter-attack is guarded by if kreature.health > 0, so a creature that has just been killed never swings back, and exactly one survivor is a structural invariant of the loop rather than a probabilistic outcome. It is kept because that invariant is worth stating and cannot be expressed by a deterministic single-round test.

  • tests/test_package_structure.py:1-7 — this file deliberately omits the sys.path.insert(0, ...src) preamble that every sibling test file carries. It imports nothing from src, inspecting the directory tree with os instead, so the preamble would be dead code. The deviation from the sibling pattern is intentional and is called out here so it is not read as an oversight.

  • tests/test_living_entity.py has no tracking issue. It is the product of a test-expansion cycle rather than a filed request, so only src/world/ is missing the __init__.py every sibling package has #47 is referenced by Closes. No Closes reference is claimed for work that has not been done.

Observations outside the diff

Recorded here rather than as inline comments, since they fall on lines this pull request does not touch.

  • tests/test_survival_mechanism.py:37 and :109-110 verify damage reduction by re-implementing the int(damage * (1 - reduction)) formula inside the test and asserting against the re-implementation, so those tests would keep passing if fight() dropped the reduction entirely. The tests added here call fight() and assert on the resulting log entry, which closes that particular blind spot without modifying the existing file.

  • src/kreatures.py remains at 50% line coverage and is now the only substantially uncovered module in the repository. It is the natural target for the next test-expansion cycle.

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 31cf764 into master Aug 11, 2026
1 check passed
@dmccoystephenson
dmccoystephenson deleted the feature/living-entity-tests branch August 11, 2026 07:09
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.

src/world/ is missing the __init__.py every sibling package has

1 participant