CtrlK
BlogDocsLog inGet started
Tessl Logo

testland/flake-pattern-reference

Reference catalog of the eight flake patterns - async/timing, test ordering, shared parallel state, resource leaks, network, locator drift, environment variance, randomness - with detection heuristics, remediation per pattern, and the concrete code-level fixes: replacing fixed sleeps with framework auto-waits, isolating state in beforeEach fixtures, per-worker DB schemas via workerIndex, try/finally teardown, mocking network + clock at the boundary, stable role-based locators, TZ pinning, and RNG seeding. Use when triaging an unknown flake to identify the category before bisecting, or when a classified flake needs the specific code change to apply.

98

1.07x
Quality

91%

Does it follow best practices?

Impact

99%

1.07x

Average score across 10 eval scenarios

SecuritybySnyk

Passed

No findings from the security scan

Overview
Quality
Evals
Security
Files

task.mdevals/scenario-6/

One of the two API test files dies before its tests run

Problem Description

Since we split the API tests into two files, node --test is red on almost every run:

Error: listen EADDRINUSE: address already in use 127.0.0.1:4300
    at Server.setupListenHandle [as _listen2] (node:net:1908:21)

✖ test/orders.test.js

The file that dies reports no test results at all - none of its tests ever ran. Which of the two files it is depends on the machine: it is test/orders.test.js on the CI image and on most laptops, and one developer sees test/health.test.js instead. On the two-core box we keep for smoke runs, the whole suite is green.

Running the files one at a time is always green: node --test test/health.test.js then node --test test/orders.test.js. Someone proposed making that the CI command permanently, and someone else proposed retrying the suite once on EADDRINUSE. We would rather the tests just worked, including when we add a third file next sprint and when two of us run the suite at the same time on the shared dev box.

Output Specification

  1. Fix test/health.test.js and test/orders.test.js so a plain node --test (default concurrency, both files) passes every time, and so would two copies of the suite running side by side on one machine.
  2. Do not modify src/server.js. Keep every test and its assertions.
  3. Write collision-notes.md: what the two files were competing for, why the file that reports the error is not the file with the problem, why the two-core box is green, and what a third test file must do to stay out of this.

Run node --test before you finish; it must pass.

Input Files

Extract the following files before beginning.

=============== FILE: package.json =============== { "name": "orders-api", "version": "0.9.4", "private": true, "scripts": { "test": "node --test" } }

=============== FILE: src/server.js =============== 'use strict';

const http = require('node:http');

function createServer({ orders = [] } = {}) { return http.createServer((req, res) => { if (req.url === '/health') { res.writeHead(200, { 'content-type': 'application/json' }); res.end(JSON.stringify({ status: 'ok' })); return; } if (req.url === '/orders') { res.writeHead(200, { 'content-type': 'application/json' }); res.end(JSON.stringify(orders)); return; } res.writeHead(404); res.end(); }); }

module.exports = { createServer };

=============== FILE: test/health.test.js =============== 'use strict';

const { test, before, after } = require('node:test'); const assert = require('node:assert/strict'); const { createServer } = require('../src/server');

const PORT = 4300; const BASE = http://127.0.0.1:${PORT};

let server;

before(async () => { server = createServer(); await new Promise((resolve) => server.listen(PORT, '127.0.0.1', resolve)); });

after(async () => { await new Promise((resolve) => server.close(resolve)); });

test('health reports ok', async () => { const res = await fetch(${BASE}/health);

assert.equal(res.status, 200); assert.deepEqual(await res.json(), { status: 'ok' }); });

test('an unknown route is a 404', async () => { const res = await fetch(${BASE}/nope);

assert.equal(res.status, 404); });

=============== FILE: test/orders.test.js =============== 'use strict';

const { test, before, after } = require('node:test'); const assert = require('node:assert/strict'); const { createServer } = require('../src/server');

const PORT = 4300; const BASE = http://127.0.0.1:${PORT};

const ORDERS = [ { id: 'ord-1', total: 4200 }, { id: 'ord-2', total: 900 }, ];

let server;

before(async () => { server = createServer({ orders: ORDERS }); await new Promise((resolve) => server.listen(PORT, '127.0.0.1', resolve)); });

after(async () => { await new Promise((resolve) => server.close(resolve)); });

test('orders are listed', async () => { const res = await fetch(${BASE}/orders);

assert.equal(res.status, 200); assert.deepEqual(await res.json(), ORDERS); });

test('an order total is in cents', async () => { const res = await fetch(${BASE}/orders); const [first] = await res.json();

assert.equal(first.total, 4200); });

SKILL.md

tile.json