Workerd Testing Strategies and the .wd-test Format: A Complete Technical Guide
Workerd employs a three-tier testing strategy that pairs JavaScript test files with Cap'n Proto .wd-test configuration files to define runtime environments, while C++ unit tests handle low-level components, all orchestrated through Bazel with multiple compatibility variants.
The Cloudflare workerd runtime uses a sophisticated, multi-layered testing architecture to validate JavaScript APIs, runtime behavior, and internal C++ components. Understanding these workerd testing strategies and the .wd-test format is essential for contributing to the codebase or extending the runtime with new features.
Workerd Testing Architecture Overview
Workerd organizes its test suite around three orthogonal concepts that cover different layers of the stack:
- JavaScript/TypeScript test files — Pure JavaScript test logic using
node:assertwithout external test frameworks. These live insrc/workerd/api/tests/*.js(or*.tsfor Node.js compatibility tests) and exporttestobjects orfetchhandlers. - Cap'n Proto
.wd-testfiles — Runtime configuration files that defineWorkerd.Configschemas to start a worker for the paired test file. These reside in the same directory with matching basenames (e.g.,feature-test.jspairs withfeature-test.wd-test). - C++ unit tests — Low-level component tests using the
kj_testframework, located insrc/workerd/*/tests/*.c++.
Each .js test is automatically paired with a .wd-test file that describes a complete Workerd.Config. The test harness loads this configuration, starts a temporary workerd instance, and executes the exported test functions.
Understanding the .wd-test File Format
A .wd-test file is a Cap'n Proto source that imports the global schema and creates a Workerd.Config constant. The schema definition resides in src/workerd/server/workerd.capnp.
Cap'n Proto Schema and Structure
The minimal structure imports the workerd schema and defines a constant configuration:
using Workerd = import "/workerd/workerd.capnp";
const unitTests :Workerd.Config = (
services = [
( name = "worker-test",
worker = (
modules = [
(name = "worker", esModule = embed "worker-test.js"),
(name = "inline-module", esModule = "export default 42")
],
compatibilityFlags = [
"nodejs_compat",
"allow_eval_during_startup"
]
)
)
]
);
The embed keyword inlines the source file content, while literal strings allow inline JavaScript definitions.
Key Configuration Sections
The .wd-test format supports several critical configuration sections that map 1-to-1 to the Cap'n Proto schema:
services— Defines named services. Most tests declare a singleworkerservice with a descriptive name.worker.modules— Specifies the modules available inside the worker. Useembed "<file>"to reference external files or provide strings for inline code.worker.compatibilityFlags— Enables specific runtime behaviors via flags defined insrc/workerd/io/compatibility-date.capnp(e.g.,"nodejs_compat","allow_fetch").worker.autogates— Optional list of experimental features controlled by autogates defined insrc/workerd/util/autogate.handsrc/workerd/util/autogate.c++.worker.bindings— Connects the worker to mock services such as KV namespaces, Durable Objects, or Queues.
The test harness compiles the file on-the-fly using wd_cc_embed, feeds the resulting binary config to the workerd binary, and then invokes the test code.
Writing and Running .wd-test Configurations
Creating a new test requires pairing a JavaScript test file with its configuration and verifying it against multiple compatibility variants.
Creating a New Test File Pair
Follow this sequence to add a validated test to the suite:
- Create the JavaScript test file at
src/workerd/api/tests/<feature>-test.js:
import assert from "node:assert";
export const test = {
async test(ctrl) {
const res = await fetch("https://example.com/");
assert.strictEqual(res.status, 200);
},
};
- Create the matching
.wd-testfile with the same basename:
using Workerd = import "/workerd/workerd.capnp";
const unitTests :Workerd.Config = (
services = [
( name = "my-feature-test",
worker = (
modules = [ (name = "worker", esModule = embed "<feature>-test.js") ],
compatibilityFlags = [ "nodejs_compat" ],
bindings = [
(name = "KV", kvNamespace = "my-kv"),
]
)
),
]
);
- Add mock bindings if required. Mock services reside in
src/workerd/api/tests/*-mock.jsand are referenced by name in thebindingslist.
Test Variants and Compatibility Modes
Every test target can be exercised with three Bazel variants to ensure backward and forward compatibility:
name@— Default variant using the oldest compatibility date (2000-01-01).name@all-compat-flags— Newest compatibility date (2999-12-31) with all compatibility flags enabled.name@all-autogates— Same as above plus all autogates enabled for experimental feature testing.
Run a specific variant using the just command:
just test //src/workerd/api/tests:worker-test@all-compat-flags
Debugging with VS Code
The repository includes a dedicated launch configuration for debugging .wd-test files. The "workerd wd-test case (dbg)" configuration, documented in [docs/vscode.md](https://github.com/cloudflare/workerd/blob/main/docs/vscode.md), prompts for a .wd-test file (defaulting to src/workerd/api/node/path-test.wd-test) and launches workerd with --inspect.
Set breakpoints directly in the embedded JavaScript modules or the test file itself. This integration allows stepping through code execution as the test harness runs the configuration against the runtime.
Summary
- Workerd testing strategies rely on three layers: JavaScript test files for API logic,
.wd-testCap'n Proto files for runtime configuration, and C++kj_testunit tests for internal components. - The
.wd-testformat uses Cap'n Proto syntax to defineWorkerd.Configwith modules, compatibility flags, autogates, and service bindings. - Test files must share the same basename (e.g.,
feature-test.jsandfeature-test.wd-test) to be automatically paired by the harness. - Run tests with
just testand specify compatibility variants (@,@all-compat-flags,@all-autogates) to validate behavior across runtime versions. - Reference schemas are located in
src/workerd/server/workerd.capnp,src/workerd/io/compatibility-date.capnp, andsrc/workerd/util/autogate.h.
Frequently Asked Questions
What is the relationship between .wd-test files and JavaScript test files?
Each JavaScript test file in src/workerd/api/tests/ must have a corresponding .wd-test file with an identical basename. The .wd-test file defines the Workerd.Config that the test harness uses to start a workerd instance, specifying which JavaScript modules to load, which compatibility flags to enable, and which mock services to bind. The harness then executes the exported test functions or fetch handlers from the JavaScript file within that configured environment.
How do I enable experimental features in a .wd-test configuration?
Experimental features are controlled through autogates in the worker.autogates section of your .wd-test file. Add the specific autogate identifier (e.g., "experimental_fetch") to the list to enable cutting-edge functionality. The available autogates are defined in the C++ headers src/workerd/util/autogate.h and src/workerd/util/autogate.c++. You can also run the @all-autogates test variant to enable every experimental gate simultaneously.
Where are the mock services like KV and Durable Objects defined for testing?
Mock services are defined in separate JavaScript files following the *-mock.js naming convention in src/workerd/api/tests/. These mocks simulate Cloudflare platform APIs like KV, D1, Durable Objects, and Queues. You reference them in your .wd-test file's worker.bindings section (e.g., (name = "KV", kvNamespace = "kv-test")), and the test harness wires them to your worker during initialization.
How do I run a specific compatibility variant of a workerd test?
Append the variant suffix to the Bazel target name when invoking just test. The three supported variants are @ (oldest compatibility date), @all-compat-flags (newest date with all flags), and @all-autogates (newest date with all flags and autogates). For example, to test with all compatibility flags enabled, run: just test //src/workerd/api/tests:worker-test@all-compat-flags. This ensures your code behaves correctly across the full compatibility matrix.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →