WESL Logo

#wgsl-test

Test WGSL and WESL shaders with the CLI or vitest.

#Installation

npm install wgsl-test

#Native WESL Testing

Write tests directly in WESL with the @test attribute. Minimal boilerplate, assertions run on the GPU:

/// interp_test.wesl
import package::interp::smootherstep;
import wgsl_test::expectNear;

@test
fn smootherstepQuarter() {
  expectNear(smootherstep(0.0, 1.0, 0.25), 0.103516);
}

See the assertion functions reference for expect, expectNear, expectNearV2f, and more.

#CLI

Run tests directly from the command line:

wgsl-test run                      # discover **/*.test.wesl, run all
wgsl-test run path/to/test.wesl    # run specific file(s)
wgsl-test run --projectDir ./foo   # specify project root

#Vitest Integration

Or run GPU shader tests from vitest with a minimal TypeScript wrapper:

import { getGPUDevice, testWesl } from "wgsl-test";

const device = await getGPUDevice();

await testWesl({ device, moduleName: "interp_test" });

#Visual Regression Testing

Test complete rendered images in vitest:

import { expectFragmentImage } from "wgsl-test";
import { imageMatcher } from "vitest-image-snapshot";

imageMatcher(); // setup once

test("blur shader matches snapshot", async () => {
  await expectFragmentImage(device, "effects/blur.wgsl");
  // snapshot compared against __image_snapshots__/effects-blur.png
});

Update snapshots with vitest -u.

See the visual regression testing reference for details.

#Testing Compute Shaders

If you want to validate results in TypeScript, use testCompute() for compute shader tests. A test::results buffer is automatically provided:

import { testCompute, getGPUDevice } from "wgsl-test";

const device = await getGPUDevice();

const src = ` // test function can be an inline WESL string or a .wesl file
  import package::hash::lowbias32;

  @compute @workgroup_size(1)
  fn main() {
    test::results[0] = lowbias32(0u);
    test::results[1] = lowbias32(42u);
  }
`;

// results returned to TypeScript for validation
const result = await testCompute({ device, src, size: 2 });
// result = [0, 388445122]