Context
bashunit::spy accepts an optional second argument that is either an exit code or
a replacement implementation (src/test_doubles.sh:66-96):
bashunit::spy curl 1 # record calls AND return 1
bashunit::mock has no equivalent. Making a mocked command fail requires a
throwaway helper function:
function _fail() { return 1; }
bashunit::mock curl _fail
or an inline body whose exit code is easy to get wrong, because
bashunit::mock cmd echo something exits with echo's status (0), not the
status the caller wanted to simulate.
Proposal
Teach bashunit::mock the same all-digits second-argument convention spy
already uses, so the two doubles are symmetric:
bashunit::mock curl 1 # exits 1, no output
Reuse the exact case glob from bashunit::spy ('' | *[!0-9]*) — it is what
keeps the interpolated value provably numeric and so keeps return $code free of
shell injection. Do not reimplement the check.
Open question worth settling in the issue discussion: how to express "output X
and exit 1" in one call. Options: a third argument, or leave it to the
existing replacement-implementation form. Prefer not to grow the signature unless
there is demand.
Why this matters for agentic coding
Error-path tests are the ones an agent is most often asked to add ("what happens
when curl fails?"). The current answer requires a helper function whose only job
is return 1, which agents both write inconsistently and shadow across tests.
A documented one-liner removes a step and makes the two doubles learnable as one
rule instead of two.
Acceptance criteria
Context
bashunit::spyaccepts an optional second argument that is either an exit code ora replacement implementation (
src/test_doubles.sh:66-96):bashunit::spy curl 1 # record calls AND return 1bashunit::mockhas no equivalent. Making a mocked command fail requires athrowaway helper function:
or an inline body whose exit code is easy to get wrong, because
bashunit::mock cmd echo somethingexits withecho's status (0), not thestatus the caller wanted to simulate.
Proposal
Teach
bashunit::mockthe same all-digits second-argument conventionspyalready uses, so the two doubles are symmetric:
bashunit::mock curl 1 # exits 1, no outputReuse the exact
caseglob frombashunit::spy('' | *[!0-9]*) — it is whatkeeps the interpolated value provably numeric and so keeps
return $codefree ofshell injection. Do not reimplement the check.
Open question worth settling in the issue discussion: how to express "output X
and exit 1" in one call. Options: a third argument, or leave it to the
existing replacement-implementation form. Prefer not to grow the signature unless
there is demand.
Why this matters for agentic coding
Error-path tests are the ones an agent is most often asked to add ("what happens
when curl fails?"). The current answer requires a helper function whose only job
is
return 1, which agents both write inconsistently and shadow across tests.A documented one-liner removes a step and makes the two doubles learnable as one
rule instead of two.
Acceptance criteria
bashunit::mock cmd 1makescmdreturn 1bashunit::mock cmd 0returns 0bashunit::mock cmd echo hi,bashunit::mock cmd <<< "out",bashunit::mock cmd some_functionthe argument position, not the command)
tests/functional/doubles_test.shdocs/test-doubles.md+docs/public/bashunit-skill.mdmake sa+make lintgreen