Skip to main content

Vitest · WebGPU · WebGL · Open source

Test your GPU code.
Skip the browser.

Two Vitest environments put a real WebGPU or WebGL context on globalThis, and a matcher compares the pixels you read back with committed image baselines. Native GPU testing is up to 2.4x faster than a browser.

A WebGPU test in Node
// gpu.test.ts
import { expect, it } from 'vitest';
import { createCanvas } from 'vitest-environment-webgpu-node';

it('clears to red on a real GPU', async () => {
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter!.requestDevice();
const canvas = createCanvas(4, 4);
const context = canvas.getContext('webgpu');
context.configure({ device, format: 'rgba8unorm' });

const encoder = device.createCommandEncoder();
encoder
.beginRenderPass({
colorAttachments: [
{
view: context.getCurrentTexture().createView(),
loadOp: 'clear',
storeOp: 'store',
clearValue: [1, 0, 0, 1],
},
],
})
.end();
device.queue.submit([encoder.finish()]);

const { data } = await canvas.readPixels();
expect([...data.slice(0, 4)]).toEqual([255, 0, 0, 255]);
});
01Install

Add an environment package next to Vitest

02Configure

Set environment to webgpu-node or webgl-node

03Render

Draw to a canvas on a real GPU in Node

04Compare

Match the pixels to a committed baseline

Real GPU, no mocks

Dawn for WebGPU.
ANGLE for WebGL.

The environments run in the Node process, so there is no browser to install or start. Your code gets real drivers: Metal on macOS, Direct3D on Windows, and Mesa on Linux. three.js, Babylon.js and plain WebGPU or WebGL code run unchanged.

Read about the environments →
vitest.config.ts
// vitest.config.ts
import { defineConfig } from 'vitest/config';

export default defineConfig({
test: { environment: 'webgpu-node' },
});
Image snapshots
import { extendMatchers } from 'vitest-screenshot';

extendMatchers();

it('renders a cube', async () => {
await renderer.renderAsync(scene, camera);
await expect(canvas).toMatchScreenshot('cube.png');
});

Pixels, not stubs

Commit a baseline.
Get a diff when it changes.

toMatchScreenshot() takes a canvas, ImageData or raw pixels. It supports png, jpg, gif and webp baselines, pixelmatch and ImageMagick-style metric comparators, and writes actual and diff images on failure.

Explore screenshots →

Keep reading

Find the part you need.

Vitest 4 and 5 · Node.js 22+ · MIT

From first canvas to green CI.

pnpm add -D vitest vitest-environment-webgpu-node

Using Jest? See jest-gpu.