Test: pin the usage-error contract for bare intermediate command groups - #705
Open
AmaadMartin wants to merge 2 commits into
Open
Test: pin the usage-error contract for bare intermediate command groups#705AmaadMartin wants to merge 2 commits into
AmaadMartin wants to merge 2 commits into
Conversation
added 2 commits
August 6, 2026 01:14
`deploy` and `integration` exist only to namespace their children. Their missing action handler is deliberate, not an omission: commander then treats a bare group as a usage error and keeps its unknown-subcommand check. State that at the definition site so a later refactor does not attach a handler.
… groups Nothing in the suite exercised `adk deploy` or `adk integration` without a subcommand, so the stream and the exit code were incidental. Pin all five rows of the contract: both groups write help to stderr and exit 1, both reject an unknown subcommand, and an explicit --help writes to stdout and exits 0.
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.
Please ensure you have read the contribution guide before creating a pull request.
Link to Issue or Description of Change
Link to an existing issue (if applicable):
Or, if no issue exists, describe the change:
Problem:
deployandintegrationare intermediate groups that only namespace their children. Neither has an action handler, socommanderprints the group help to stderr and exits 1. That answer is correct, but no test pins it and no comment records the decision, so a later refactor can attach a handler and flip it silently.Solution: This change adds a comment and tests. No runtime behaviour changes. The adopted contract: a group named without a subcommand is a usage error (help to stderr, exit 1), and an explicit
--helpis a success (help to stdout, exit 0). Five new cases pin the stream, theCommanderErrorcode and the exit code fordeploy,integration, both unknown-subcommand forms, anddeploy --help.Why not print help to stdout and exit 0. An action handler on
deploydisablescommander's unknown-subcommand check, andDEPLOY_COMMANDalready setsallowExcessArguments()for thegcloudpass-through.adk deploy cloud-run --project=x— a hyphen typo — would then print help and exit 0, reporting success for a deploy that never ran. I measured this, see mutation M1 below. The implicithelp [command]subcommand also disappears, because_getHelpCommand()requires no action handler.Collision check. I listed all open pull requests on this fork and diffed every candidate that touches
dev/src/cli/cli.tsordev/test/cli/cli_test.ts. No open pull request asserts anything about a bare group. Two overlap without colliding: #597 changes the root command (this change asserts nothing about bareadk, and its assertions avoid the program name, so it survives theADK CLI->adkrename), and #587 adds help-text assertions fordeploy cloud_run. I did not stack, because stacking on one of two overlapping branches is arbitrary, and it would couple a test-only change to an unmerged runtime change.Testing Plan
Please describe the tests that you ran to verify your changes. This is required for all PRs that are not small documentation or typo fixes.
Unit Tests:
[x] I have added or updated unit tests for my change.
[x] All unit tests pass locally.
npx vitest run --project unit:dev dev/test/cli/cli_test.ts— 31 passed (26 existing, 5 new). No existing test was edited; the newdescribeblock is appended at the end of the file.Mutation proof. Coverage is not proof, so I ran each new test against mutated source and recorded the failure.
dev/src/cli/cli.ts.action(() => DEPLOY_COMMAND.outputHelp())ondeployexpected 'adk deploy' to throw;expected 'adk deploy bogus' to throw.action(() => CONFORMANCE_COMMAND.outputHelp())onintegrationexpected 'adk integration' to throw;expected 'commander.excessArguments' to be 'commander.unknownCommand'.helpOption(false)ondeployexpected 'commander.help' to be 'commander.helpDisplayed'M1 and M2 are option (b) applied to each group. They reproduce both regressions:
deploy bogusstops throwing at all, andintegration bogusdegrades toexcessArguments. All three mutations were reverted; the suite is green at the pushed commit.One note on the test harness.
Command.prototype.command()snapshots the parent exit callback and output config when the child is created, so the outerprogram.exitOverride()covers the root only. The newbeforeEachwalksprogram.commandsand applies both to every child. Without that walk, parsing['deploy']calls the realprocess.exit(1)and kills the vitest worker.Manual End-to-End (E2E) Tests:
Please provide instructions on how to manually test your changes, including any necessary setup or configuration.
Run
npm run build, then run the built entrypoint. Measured output:Checklist
[x] I have read the CONTRIBUTING.md document.
[x] I have performed a self-review of my own code.
[x] I have commented my code, particularly in hard-to-understand areas.
[x] I have added tests that prove my fix is effective or that my feature works.
[x] New and existing unit tests pass locally with my changes.