Skip to content

Commit e3c15dc

Browse files
docs: document conditional test-suite abort in BDD tutorial (#3115)
Co-authored-by: lunadogbot <lunadogbot@users.noreply.github.com> Co-authored-by: Bartek Iwańczuk <biwanczuk@gmail.com>
1 parent e0519dd commit e3c15dc

1 file changed

Lines changed: 73 additions & 1 deletion

File tree

examples/tutorials/bdd.md

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
last_modified: 2026-05-13
2+
last_modified: 2026-05-14
33
title: "Behavior-Driven Development (BDD)"
44
description: "Implementing Behavior-Driven Development with Deno's Standard Library's BDD module. Create readable, well organised tests with effective assertions."
55
url: /examples/bdd_tutorial/
@@ -336,6 +336,78 @@ leave only the expensive, read-mostly setup in `beforeAll`.
336336

337337
:::
338338

339+
### Aborting a suite when a precondition isn't met
340+
341+
Sometimes a whole suite depends on something external — a database connection, a
342+
service running on a known port, a file on disk. If that precondition isn't
343+
satisfied, you usually don't want the rest of the suite to run and produce
344+
dozens of confusing failures. There are two patterns that work well with
345+
`@std/testing/bdd`.
346+
347+
**Throw from `beforeAll`.** If you want the suite to fail loudly when the
348+
precondition is missing (so CI surfaces it as a real error), throw from the
349+
hook. Every `it` inside the same `describe` will then be reported as failed
350+
because setup never completed:
351+
352+
```ts
353+
describe("Database operations", () => {
354+
let db: Database;
355+
356+
beforeAll(async () => {
357+
db = await Database.connect(TEST_CONNECTION_STRING);
358+
if (!(await db.ping())) {
359+
throw new Error("Database is not reachable — aborting suite");
360+
}
361+
});
362+
363+
afterAll(async () => {
364+
await db?.close();
365+
});
366+
367+
it("should insert a record", async () => {
368+
const result = await db.insert({ name: "Test" });
369+
assertEquals(result.success, true);
370+
});
371+
});
372+
```
373+
374+
**Skip the suite with the `ignore` option.** If the precondition being unmet is
375+
expected (for example, the integration database isn't available in a
376+
contributor's local environment), it's nicer to skip the suite cleanly rather
377+
than fail it. Both `describe` and `it` accept an `ignore` option that takes a
378+
boolean — compute it once at the top of the file and pass it in:
379+
380+
```ts
381+
import { describe, it } from "jsr:@std/testing/bdd";
382+
import { assertEquals } from "jsr:@std/assert";
383+
384+
async function isDatabaseReachable(): Promise<boolean> {
385+
try {
386+
const db = await Database.connect(TEST_CONNECTION_STRING);
387+
await db.close();
388+
return true;
389+
} catch {
390+
return false;
391+
}
392+
}
393+
394+
const dbReachable = await isDatabaseReachable();
395+
396+
describe("Database operations", { ignore: !dbReachable }, () => {
397+
it("should insert a record", async () => {
398+
const db = await Database.connect(TEST_CONNECTION_STRING);
399+
const result = await db.insert({ name: "Test" });
400+
assertEquals(result.success, true);
401+
await db.close();
402+
});
403+
});
404+
```
405+
406+
When `dbReachable` is `false`, the entire `describe` block — and every `it`
407+
inside it — is reported as ignored, and the rest of your test file still runs
408+
normally. The same `ignore` option works on individual `it` cases if you only
409+
need to skip part of a suite.
410+
339411
## Gherkin vs. JavaScript-style BDD
340412

341413
If you're familiar with Cucumber or other BDD frameworks, you might be expecting

0 commit comments

Comments
 (0)