Test lifecycle management, subtests, planning, timeouts, and utility functions.
Control the expected number of assertions for deterministic test completion.
/**
* Set the number of assertions expected in this test
* @param n - Number of assertions expected (must be positive integer)
*/
plan(n: number): void;Usage Examples:
test("planned test", (t) => {
t.plan(3);
t.ok(true, "first assertion");
t.is(2 + 2, 4, "second assertion");
t.pass("third assertion");
// Test automatically ends when plan is reached
});
test("async planned test", async (t) => {
t.plan(2);
const result = await someAsyncOperation();
t.ok(result, "async operation succeeded");
const data = await anotherAsyncOperation();
t.is(data.length, 3, "data has expected length");
// No need to call t.end() - plan completion ends the test
});Explicitly end tests, especially useful in inverted mode.
/**
* Explicitly end the test (required for inverted tests without plan)
*/
end(): void;Usage Examples:
// Inverted test requires explicit end
const t = test("inverted test");
t.is(1 + 1, 2);
t.ok(true);
t.end(); // Required
// Callback test with early end
test("early end", (t) => {
if (process.env.SKIP_TEST) {
t.pass("test skipped");
t.end(); // End early
return;
}
// Continue with normal test
t.is(2 + 2, 4);
});Create nested tests within a parent test for organized test hierarchies.
/**
* Create a subtest within the current test
* @param name - Optional subtest name
* @param options - Optional test configuration
* @param callback - Optional test function for callback mode
* @returns Test instance (inverted mode) or Promise<boolean> (callback mode)
*/
test(name?: string, options?: TestOptions, callback?: (t: Test) => void): Test | Promise<boolean>;
/**
* Create a stealth subtest (minimal output)
* @param name - Optional subtest name
* @param options - Optional test configuration
* @param callback - Optional test function for callback mode
* @returns Test instance (inverted mode) or Promise<boolean> (callback mode)
*/
stealth(name?: string, options?: TestOptions, callback?: (t: Test) => void): Test | Promise<boolean>;Usage Examples:
test("user management", async (t) => {
// Setup
const user = { name: "Alice", age: 30 };
// Subtest for user creation
await t.test("create user", (st) => {
st.is(user.name, "Alice", "user has correct name");
st.is(user.age, 30, "user has correct age");
});
// Subtest for user validation
await t.test("validate user", (st) => {
st.ok(user.name.length > 0, "user name is not empty");
st.ok(user.age >= 0, "user age is non-negative");
});
// Stealth subtest (minimal output)
await t.stealth("internal checks", (st) => {
st.ok(typeof user === "object");
st.ok(user.hasOwnProperty("name"));
});
t.pass("all user tests completed");
});Set timeouts for individual tests or clear existing timeouts.
/**
* Set a timeout for the current test
* @param ms - Timeout in milliseconds, or 0 to clear timeout
*/
timeout(ms: number): void;Usage Examples:
test("quick test", (t) => {
t.timeout(1000); // 1 second timeout
// Test must complete within 1 second
t.is(1, 1);
});
test("long running test", async (t) => {
t.timeout(30000); // 30 second timeout
await longRunningOperation();
t.pass("operation completed");
});
test("no timeout test", (t) => {
t.timeout(0); // Clear any default timeout
// Test can run indefinitely
doSomethingThatMightTakeAWhile();
t.pass("completed");
});Register cleanup functions that run after the test completes.
/**
* Register a teardown function to run after test completion
* @param fn - Cleanup function to execute
* @param options - Optional teardown configuration
*/
teardown(fn: Function, options?: TeardownOptions): void;
interface TeardownOptions {
/** Execution order (lower numbers run first, default: 0) */
order?: number;
/** Run even if test fails (default: false) */
force?: boolean;
}Usage Examples:
test("resource management", async (t) => {
const resource = await createResource();
// Basic teardown
t.teardown(() => {
resource.cleanup();
});
// Ordered teardown
t.teardown(() => {
console.log("cleanup 1");
}, { order: 1 });
t.teardown(() => {
console.log("cleanup 2");
}, { order: 0 }); // Runs first
// Force teardown (runs even on test failure)
t.teardown(() => {
criticalCleanup();
}, { force: true });
// Use the resource
t.ok(resource.isValid(), "resource is valid");
});Add comments to test output for debugging and documentation.
/**
* Add a comment to the test output
* @param message - Comment message parts
*/
comment(...message: any[]): void;Usage Examples:
test("debugging example", (t) => {
t.comment("Starting test with debug info");
const data = processData();
t.comment("Processed data:", data);
t.is(data.length, 3, "data has expected length");
t.comment("Test completed successfully");
});Create temporary directories for test file operations.
/**
* Create a temporary directory for this test
* @returns Promise<string> - Path to the temporary directory
*/
tmp(): Promise<string>;Usage Examples:
import fs from "fs/promises";
import path from "path";
test("file operations", async (t) => {
const tmpDir = await t.tmp();
t.comment("Using temp directory:", tmpDir);
// Create test file
const filePath = path.join(tmpDir, "test.txt");
await fs.writeFile(filePath, "hello world");
// Verify file
const content = await fs.readFile(filePath, "utf8");
t.is(content, "hello world", "file content matches");
// Directory is automatically cleaned up after test
});Access test state and statistics during execution.
interface Test {
/** Test name */
readonly name: string;
/** Number of passed assertions */
readonly passes: number;
/** Number of failed assertions */
readonly fails: number;
/** Total number of assertions */
readonly assertions: number;
}Usage Examples:
test("test statistics", (t) => {
t.comment("Test name:", t.name);
t.comment("Initial stats - passes:", t.passes, "fails:", t.fails);
t.pass("first assertion");
t.is(2 + 2, 4, "second assertion");
t.comment("Current stats - passes:", t.passes, "fails:", t.fails);
t.is(t.assertions, 2, "total assertions count");
// Use stats for conditional logic
if (t.fails === 0) {
t.comment("All assertions passing so far");
}
});These control utilities work together for comprehensive test management:
test("comprehensive test example", async (t) => {
t.plan(4);
t.timeout(5000);
t.comment("Starting comprehensive test");
const tmpDir = await t.tmp();
const resource = await setupResource(tmpDir);
t.teardown(async () => {
await resource.cleanup();
t.comment("Resource cleaned up");
});
// Subtests count toward parent plan
await t.test("resource creation", (st) => {
st.ok(resource.isValid());
}); // Counts as 1 assertion
t.is(resource.type, "test", "resource type"); // 2
t.ok(resource.ready, "resource ready"); // 3
t.pass("test completed"); // 4 - plan complete
});