Skip to the content

Test strategy

The layers of the tests, the rule suites, the leak check and the browsers.

Why the old tests were not sufficient

The old tests used one context at a time, so a leaked value was the same as the correct value. They read the variable only at the start of a statement, and only in callbacks that the runtime wrapped. Thus, a runtime with no async support passed 82 of the 217 old tests. The results page shows this with the mutants of the review.

The rules for each test

  1. Use two or more contexts. Let a different context continue immediately before each read.
  2. Read the value at the points of risk. These are the same expression after await, the callbacks that the library does not wrap and the code that the transform does not change.
  3. Do not put assertions in callbacks that the test does not wait for.
  4. Do not use time limits to examine correctness. Put the speed checks in the benchmarks.
  5. Do not skip a test silently. Use test.skipIf with a reason.
  6. Use a fixed seed for random values. Record the seed when a test fails.
  7. Make each test name tell the rule and the expected result.

The test layers

LayerToolWhat the layer shows
UnitVitest on Node.jsEach part of the runtime operates correctly.
RulesVitest on Node.js and in browsersThe context rules C1 to C13.
Transform fixturesVitest and BabelThe output and the results of transformed code.
ReferenceVitest and AsyncLocalStorageThe library gives the same results as Node.js.
Order variationVitest with a random scheduler that has a fixed seedNo leak occurs in many different orders of steps.
Browser APIsVitest browser mode in three enginesThe patched APIs operate correctly.
MemoryNode.js with --expose-gcRule C12.
MutationStrykerJSThe tests find errors that a mutant adds to the runtime.
Speedtinybench in separate processesThe benchmarks.

The projects

One Vitest configuration starts the same rule tests on each runtime:

ProjectRuntimeTransform
rules (browser runtime, Node.js)The browser runtime, on Node.jsYes
rules (node runtime)The Node.js entry with the native AsyncLocalStorageYes
rules (node runtime, no transform)The Node.js entryNo
browser (chromium), browser (firefox), browser (webkit)The browser runtime, in a real browserYes

The test files import the package by its name, as your code does. The Vite plugin of the library transforms the test files.

The leak check

After each test of the browser runtime, a check makes sure that the root context is current. A test that leaves a context current fails, also if its assertions pass.

The tests of this site

The site has its own tests. One test starts each scenario of the context timeline in Chromium and examines each read. Another test opens each page of the site and fails at an error.

To change this page, edit site/content/testing/index.mdx.

async-browser-context: AsyncLocalStorage and the TC39 AsyncContext API for browsers. The source code is on GitHub.

To change a page, edit its file in site/content/. The writing style guide tells you how.

An AI model (Claude, from Anthropic) wrote most of the text and the code of this site and of the library, under the direction of the author. The tests and the STE linter examine them.