Testing
Here are some tips for testing your application or library with LogTape.
Reset configuration
You can reset the configuration of LogTape to its initial state. This is useful when you want to reset the configuration between tests. For example, the following code shows how to reset the configuration after a test (regardless of whether the test passes or fails):
import { , } from "@logtape/logtape";
Deno.("my test", async () => {
await .("set up", async () => {
await ({ /* ... */ });
});
await .("run test", () => {
// Run the test
});
await .("tear down", async () => {
await ();
});
});import { , } from "@logtape/logtape";
import { , , , } from "node:test";
("my test", async () => {
(async () => {
await ({ /* ... */ });
});
(async () => {
await ();
});
("is a sub-test", () => {
// Run the test
});
});Log recorder
This API is available since LogTape 2.2.0.
For testing purposes, you may want to collect log records in memory and assert on them. The @logtape/testing package provides createLogRecorder() for this:
deno add jsr:@logtape/testingnpm add @logtape/testingpnpm add @logtape/testingyarn add @logtape/testingbun add @logtape/testingimport { , , } from "@logtape/logtape";
import { } from "@logtape/testing";
const = ();
try {
await ({
: {
: .,
},
: [
{
: ["my-lib"],
: "debug",
: ["recorder"],
},
{ : ["logtape", "meta"], : [] },
],
});
(["my-lib"]).("User {userId} logged in.", {
: 123,
});
.({
: ["my-lib"],
: "info",
: "User 123 logged in.",
: { : 123 },
});
} finally {
await ();
}The recorder stores records in sink call order. It snapshots lazy callback messages when the sink receives them, so assertions see the same message a normal sink would observe at emit time. The records property returns a snapshot, and the recorder also provides clear(), take(), find(), filter(), assertLogged(), and assertNotLogged(). Matchers can check category, category prefix, level, rendered message, raw message, and a shallow partial set of structured properties. Most property values are compared with Object.is(), Date values are compared by timestamp, and regular expression matcher values match string property values. Rendered message matching uses the same value rendering as LogTape's default text formatter. Use a property predicate when a test needs absence checks or deep matching.
createLogRecorder() is a synchronous sink. If a log call uses async lazy properties, await the log call before asserting. If your test also uses async sinks, still call await dispose() or await reset() as usual.
Buffer sink
For very small tests that only need raw LogRecord objects, you can still implement a buffer sink directly:
import { type LogRecord, } from "@logtape/logtape";
const : LogRecord[] = [];
await ({
: {
: ..(),
},
// Omitted for brevity
});