Skip to main content


Testing webgl programs can be tricky...

  • test-utils
  • probe
  • headless gl
  • puppeteer
  • ...

Test device creation

A small but still annoying issue is that creating too many devices in tests can lead to problems with context loss etc as the test scripts grow. exports reusable test devices for WebGL and WebGPU.

Accessing GPU in Node.js and CI environments

A frequent problem with WebGL and WebGPU libraries is that they are supported in browsers, but tests typically run on CI machines in the cloud that often do not even have a GPU. has integrations with headless gl and puppeteer that allows tests to be run outside of browser.s

Render Tests

A powerful way to test GPU programs is to render into a texture and compare against a golden image. provides a library that handles complications like waiting for resources to load before rendering the image, and doing pixel diffs that accept a small error tolerance.

SnapshotTestRunner provides this client-side utility for browser-based WebGL render tests.

This class is intended to be used with BrowserTestDriver from Together they support the following workflow:

  • Launch a Puppeteer instance (headless or non-headless) to run a test application
  • In the test application, create a canvas and WebGLContext.
  • For each test case, render something to the WebGLContext, take a screenshot, and perform pixel-diffing with a pre-defined "golden image". Report the matching result.
  • Proceed to the next test case until done.


In your node.js start script:

// This is the script that runs in Node.js and starts the browser
const {BrowserTestDriver} = require('');
new BrowserTestDriver().run({
server: {
// Bundles and serves the browser script
command: 'webpack-dev-server',
arguments: ['--env.render-test']
headless: true

In your script that is run on the browser:

const {SnapshotTestRunner} = require('');
const {Cube} = require('');

const TEST_CASES = [
name: 'Render A Cube',
// `onRender` receives animation props from the AnimationLoop
onRender: ({gl, done}) => {
const model = new Cube(gl);
// ready for capture and diffing
goldenImage: './test/render/golden-images/cube.png'

new TestRender({width: 800, height: 600})
onTestFail: window.browserTestDriver_fail