Convert test_bootstrap.py to unittest so discover collects it - #755
Merged
Conversation
test_bootstrap.py defined its ten checks as module-level test_* functions with its own check()/failures collector and main() runner, no unittest.TestCase. validate-task.yml's only invocation is 'unittest discover -s scripts/tests', which loads TestCase subclasses from each module it imports; a bare test_* function is not one, so none of the loader-invariant or spec-to-installer coverage checks ran. Convert the file to unittest.TestCase, matching the other six files under scripts/tests/: TestLoaderInvariant, TestSpecCoverage, and TestScriptPresence group the ten checks, subTest reports each item in a loop rather than lumping failures into one list, and a TestHarness case floors the collected count. Confirmed discover now collects and runs all eleven cases, and that a fault (a payload path added to bootstrap.sh) is caught rather than passing silently. Fixes #754
Contributor
There was a problem hiding this comment.
Pull request overview
This pull request fixes a CI test-discovery gap by converting scripts/tests/test_bootstrap.py from a custom module-level test_* + manual runner pattern into unittest.TestCase classes so python -m unittest discover -s scripts/tests actually collects and runs the checks (loader invariant + spec-to-installer coverage).
Changes:
- Refactors the bootstrap checks into
unittest.TestCasesuites usingassert*+subTest, replacing the prior globalfailurescollector andmain()runner. - Adds a small “harness” test to assert the module collects a minimum number of test cases (guarding against silent collection failures).
- Adds a shebang and enables direct execution via
unittest.main(verbosity=2).
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
ptr727
added a commit
that referenced
this pull request
Aug 16, 2026
… Default (#768) Promote `develop` to `main`, carrying the remaining stages of the hub-hosted reusable-workflow rollout and the changes that landed beside them: - #759 Host Get-Version and Publish-Plan as Hub Reusable Tasks - #760 Host the Validate Task and Reshape the Test Pull Request Stub (settles #729 by design: the hub's validate task runs `uvx <tool>@latest`, since Dependabot tracks the action pins and not a uvx version) - #761 Host the Type-Specific Tasks and Retire the Date Badge - #762 Host the Release Chain and the Docker Core in the Hub - #748 and #752, the staged rollout tracker and the PhotoCleaner merge-bot pilot record - #758 Flip the Fleet Line-Ending Default from CRLF to LF - #753, #755, #756, #764, host-setup and test-collection changes The release that follows this promotion is the first tag carrying every hub task, so it is the pin the stage 2 to 5 adoptions and their catalog snippets use. It is also the first run of the hub's own `publish-release.yml` through `build-release-task.yml` with every target disabled, which is the live proof that `github-release` runs when its build needs are skipped. Closes #729. Refs #521 (hub half shipped, the merge-bot adoption sweep is what remains).
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.
scripts/tests/test_bootstrap.pydefined its ten checks as module-leveltest_*functions with its owncheck()/failurescollector andmain()runner, nounittest.TestCase. CI's only invocation,validate-task.yml'sunittest discover -s scripts/tests, loadsTestCasesubclasses from each module it imports; a baretest_*function is not one, so none of the loader-invariant or spec-to-installer coverage checks ran.What changed
Converted the file to
unittest.TestCase, matching the other six files underscripts/tests/:TestLoaderInvariant— the two loaders each read exactly one path into the fetched tree, and need no Python.TestSpecCoverage— every toolspec/host-tools.jsonrequires is one the platform installers can provide, and every floored tool carries a total remedy mapping.TestScriptPresence— every script a loader hands control to is present and, on Linux, tracked executable; the Windows scripts andbootstrap.ps1carry no shebang.TestHarness— floors the collected test count, matching the sibling files' pattern.Dropped the
check()/failuresglobal collector forself.assert*andself.subTest, so a loop over multiple items (tools, platforms, forbidden paths) reports each failing item as its own subtest instead of one lumped list. Added the shebang and executable bit the other six sibling files carry.Verification
python3 scripts/tests/test_bootstrap.py— 11 tests, OK.python3 -m unittest discover -s scripts/tests— 686 tests, OK (previously ran none of this file's checks; confirmed by grepping the-voutput forbootstrapbefore this change).uvx coverage@latest run --source=scripts,spec,host-setup -m unittest discover -s scripts/tests— the exact CI invocation — 686 tests, OK.uvx ruff@latest check .,uvx ruff@latest format --check .,uvx mypy@latest— clean.python3 scripts/prose_lint.py,python3 scripts/repo_gate.py— clean.docker run ... mstruebing/editorconfig-checker:latest— clean on the changed file (only gitignored local tool caches flagged, not part of the change).$TREE/spec/...read to a scratch copy ofhost-setup/bootstrap.shand reran —TestLoaderInvariantfailed with the expected message, confirming the converted checks actually catch a violation rather than passing vacuously. Reverted before committing.Fixes #754