Skip to content

feat: add text-matching assertions (expect_matches, expect_output_contains, expect_pcre_matches); bump to 0.5.0 - #23

Merged
helly25 merged 1 commit into
mainfrom
feat/expect-matches-output-contains
Jul 2, 2026
Merged

helly25 merged 1 commit into
mainfrom
feat/expect-matches-output-contains

Conversation

@helly25

@helly25 helly25 commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

Why

bashtest had no matcher for "does this (multi-line) captured text match a substring/regex" — the existing string matchers are exact-equality (expect_eq/expect_ne) and array-membership (expect_contains). That gap forces users of CLI-output tests to hand-roll printf '%s' "$out" | grep -qE ..., which is a footgun under set -o pipefail (which bashtest.sh sets and its examples mandate for test scripts): grep -q exits on the first match, the producer takes SIGPIPE, and pipefail flips a passing test into a flaky failure on large output.

What

Six new matchers, all following the existing matcher conventions (verbose-on-success, _BASHTEST_HAS_ERROR + actionable stderr on failure, 50-char display truncation):

Matcher Engine Notes
expect_output_contains / expect_output_not_contains [[ == *x* ]] literal substring; glob metacharacters are inert
expect_matches / expect_not_matches bash [[ =~ ]] (ERE) zero subprocess — structurally cannot SIGPIPE; ^/$ anchor the whole text, not per line (documented in the help text and doc comments)
expect_pcre_matches / expect_pcre_not_matches external tool detects grep -Pggrep -Ppcre2greppcregrep once and caches; text is fed via a here-string (no pipe); fails with an install hint when no backend exists

Design notes:

  • Two separately-named matchers per engine instead of an engine-selection flag: the name is the selector, expect_matches stays dependency-free/portable, and PCRE (\d, lookahead, non-greedy) is an explicit opt-in.
  • The output_ prefix on the substring matchers avoids collision with the array-membership expect_contains.
  • Also documents the SIGPIPE-under-pipefail pitfall in the README and extends bazel run //bashtest:bashtest_help.

Backwards-compatible API addition → minor bump to 0.5.0 (MODULE.bazel + CHANGELOG).

Testing

  • New test:: functions in bashtest_test.sh mirroring the existing pattern (positive/negative cases, runner-counter integrity checks). PCRE cases gate on backend availability: positive-path assertions where a backend exists (Linux CI), graceful-failure assertion on stock macOS (BSD grep has no -P).
  • Verified matcher semantics empirically on macOS bash 3.2 (oldest supported bash), including whole-text anchoring (^SECOND against $'a\nSECOND\nc' correctly does not match), literal-glob inertness, and the positive PCRE path via pcre2grep.
  • bazel test //...: 3/3 pass. shellcheck 0.11.0 clean; all pre-commit hooks pass.

@helly25
helly25 force-pushed the feat/expect-matches-output-contains branch from e516dd2 to 6aed53e Compare July 2, 2026 22:14
Add six new matchers for asserting on captured (multi-line) command
output, closing the gap that forced users to hand-roll
`printf '%s' "$out" | grep -qE ...` pipelines - a footgun under
`set -o pipefail` (which bashtest mandates): `grep -q` exits on first
match, the producer takes SIGPIPE, and pipefail turns that into a
flaky failure.

* expect_output_contains / expect_output_not_contains: literal
  substring via `[[ == *x* ]]` (glob metacharacters inert).
* expect_matches / expect_not_matches: ERE via bash built-in
  `[[ =~ ]]` - zero subprocess, so it cannot SIGPIPE. `^`/`$` anchor
  the whole text, not individual lines (documented).
* expect_pcre_matches / expect_pcre_not_matches: PCRE via an external
  tool (grep -P, ggrep -P, pcre2grep, or pcregrep; detected once and
  cached), fed through a here-string so no pipe is involved. Fails
  with an actionable install hint when no backend is available.

Also document the SIGPIPE-under-pipefail pitfall in the README and
extend the built-in help output.
@helly25
helly25 force-pushed the feat/expect-matches-output-contains branch from 6aed53e to 9c1a727 Compare July 2, 2026 22:15
@helly25
helly25 requested a review from Fab-Cat July 2, 2026 22:16
@helly25
helly25 merged commit 7a084a6 into main Jul 2, 2026
4 checks passed
@helly25
helly25 deleted the feat/expect-matches-output-contains branch July 2, 2026 22:21
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.

2 participants