🔥 Test Automation — Assertions, CLI & CI/CD
Test Automation — Assertions, CLI &: Clicking "Send" and eyeballing the response is like tasting soup once while cooking.
Clicking "Send" and eyeballing the response is like tasting soup once while cooking. Automated assertions are a kitchen timer and a thermometer that check the soup every single time, automatically, even at 3am when nobody's awake to taste it — that's what lets a computer (CI) decide pass/fail instead of a human. But if you already looked at the response and it was clearly correct, why write an assertion for it? Because what you verified was this response, on this day, with this data — and the thing that breaks an API is almost never the part you were watching. A field quietly changes type from number to string, a nullable field starts arriving as null, the status code stays 200 while the body loses half its contents. Your eye scans for what it expects to see; an assertion checks what must be true. That gap is where most production API bugs live. The Java parallel is exact: this is `System.out.println(result)` versus `assertEquals(expected, result)`. Both show you the value; only one fails the build when the value is wrong six months from now, in a run nobody is watching. For QA the CLI is what turns this from a personal habit into team infrastructure: the same collection you click through by hand runs headless in the pipeline on every pull request. A broken contract then fails at the merge, not in the release call — and "it worked on my machine" stops being a defensible sentence.
Writing Checks — Assert Tab vs Script Tab
Assert tab — no JavaScript needed:
How Does res.status: eq 200 Work Without Writing JavaScript?
The Assert tab reads every line…
The Assert tab READS every written line in its OWN mini-language — res.status: eq 200 is NOT real JavaScript, it's a COMPARISON expression Bruno INTERPRETS internally.
Operators like eq, lt, gt…
Operators like eq, lt, gt are a PREDEFINED set — you cannot INVENT a new operator, you can only USE the handful of comparison types Bruno SUPPORTS.
res.body.email: contains @…
res.body.email: contains @ checks WHETHER the "@" character APPEARS INSIDE the email field of the response body — not an EXACT match, a PARTIAL text search.
res.responseTime: lt 500 compares…
res.responseTime: lt 500 COMPARES the ACTUAL response time (in milliseconds) that Bruno ITSELF measured against 500 — this value doesn't COME from the server, it's CALCULATED client-side.
EACH of these lines is an INDEPENDENT…
EACH of these lines is an INDEPENDENT assertion — even if one FAILS, the others keep RUNNING, and ALL results are shown TOGETHER in a single run report.