Caliber Testing
caliber-ai-org/ai-setup
Writes Vitest tests following project patterns: tests/ directories, vi.mock() for module mocking with vi.hoisted() for test-time factories, global LLM mock from src/test/setup.ts, environment…
This skill should be used when writing, running, or fixing tests in the brepjs repository — when a task says "add a test", "write a regression test", "tests are failing", "test timed out", "coverage…
$ npx skills add andymai/brepjs --skill writing-tests -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install andymai/brepjs writing-tests --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/andymai/brepjs.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/writing-tests .claude/skills/writing-tests && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "writing-tests" agent skill from https://github.com/andymai/brepjs/tree/main/.claude/skills/writing-tests into .claude/skills/writing-tests/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "writing-tests", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/andymai/brepjs/tree/main/.claude/skills/writing-testsType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add andymai/brepjs --skill writing-tests -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install andymai/brepjs writing-tests --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/andymai/brepjs.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.claude/skills/writing-tests .agents/skills/writing-tests && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "writing-tests" agent skill from https://github.com/andymai/brepjs/tree/main/.claude/skills/writing-tests into .agents/skills/writing-tests/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "writing-tests", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add andymai/brepjs --skill writing-tests -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install andymai/brepjs writing-tests --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/andymai/brepjs.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.claude/skills/writing-tests .cursor/skills/writing-tests && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "writing-tests" agent skill from https://github.com/andymai/brepjs/tree/main/.claude/skills/writing-tests into .cursor/skills/writing-tests/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "writing-tests", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/andymai/brepjs.git --path .claude/skills/writing-tests--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add andymai/brepjs --skill writing-tests -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install andymai/brepjs writing-tests --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/andymai/brepjs.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.claude/skills/writing-tests .gemini/skills/writing-tests && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "writing-tests" agent skill from https://github.com/andymai/brepjs/tree/main/.claude/skills/writing-tests into .gemini/skills/writing-tests/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "writing-tests", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install andymai/brepjs writing-testsInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add andymai/brepjs --skill writing-tests -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/andymai/brepjs.git skills-src && mkdir -p .github/skills && cp -r skills-src/.claude/skills/writing-tests .github/skills/writing-tests && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "writing-tests" agent skill from https://github.com/andymai/brepjs/tree/main/.claude/skills/writing-tests into .github/skills/writing-tests/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "writing-tests", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add andymai/brepjs --skill writing-tests -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install andymai/brepjs writing-tests --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/andymai/brepjs.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.claude/skills/writing-tests .opencode/skills/writing-tests && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "writing-tests" agent skill from https://github.com/andymai/brepjs/tree/main/.claude/skills/writing-tests into .opencode/skills/writing-tests/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "writing-tests", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
writing-testsThis skill should be used when writing, running, or fixing tests in the brepjs repository — when a task says "add a test", "write a regression test", "tests are failing", "test timed out", "coverage…
Writing Tests is an agent skill from andymai/brepjs. This skill should be used when writing, running, or fixing tests in the brepjs repository — when a task says "add a test", "write a regression test", "tests are failing", "test timed out", "coverage threshold failed", "run tests against brepkit/manifold/occt", "skip this test on kernel X", or when a new operation needs test coverage before merge. Covers the test skeleton, geometry assertions, multi-kernel projects, divergence skips, and coverage gates.
Its SKILL.md is about 4.3k tokens, which your agent loads only when the skill is triggered. The skill folder holds 2 other files, including reference files (for example `references/multi-kernel.md`).
It sits in Testing & QA, covering Test coverage and Failing and flaky tests. It works with Vitest. The repository describes itself as: Web CAD library with exact B-Rep geometry. The licence is Apache-2.0.
6 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit 6e20740. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
npmnpxFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use npm and npx, which can reach the network depending on how they are called.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Writing Tests loads about 4.3k tokens when it runs, and up to ~6.6k if it reads all its reference files. Until then it costs about 118 tokens; SKILL.md has 1,483 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from andymai/brepjs at commit 6e20740, republished under its Apache-2.0 licence (© andymai). 1,483 words, ~4,260 tokens.
.claude/skills/writing-tests/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.Tests live in /tests/, named <moduleName>.test.ts (e.g. tests/shapeFns.test.ts); api*.test.ts for public-API surface tests. Extend an existing file for the module before creating a new one.
Exact boilerplate (from tests/booleanFns.test.ts):
import { describe, expect, it, beforeAll } from 'vitest';
import { initKernel } from './setup.js';
import { box, fuse, isOk, unwrap, measureVolume } from '@/index.js';
beforeAll(async () => {
await initKernel();
}, 30000);Rules:
initKernel from ./setup.js — not initOC. initOC is a backward-compat alias (tests/setup.ts) that force-boots the legacy OpenCascade.js kernel regardless of which vitest project is running. initKernel() (tests/helpers/kernelInit.ts) reads the TEST_KERNEL env var set by the vitest project, so the same test runs correctly under all four kernels. CLAUDE.md's "Writing a test" section still names initOC; prefer initKernel.30000 is the beforeAll hook timeout (WASM boot can be slow on first run). It is NOT the per-test timeout — that is 90 s (testTimeout: 90000 in vitest.config.ts; CLAUDE.md's "30s timeout" claim is stale).@/index.js. Cross-directory imports use the @/ alias (→ src/), always with .js extensions. Vitest globals are enabled, but files still import describe/it/expect explicitly.@/core/shapeTypes.js, helpers in tests/helpers/) only when the public API cannot express the assertion.expect(isOk(result)).toBe(true) first, then unwrap(result) to get the value. Use isErr()/unwrapErr() for error-path tests. unwrap is fine in tests; production code in layers 2–3 uses isOk()/match() — see the result-error-handling skill.toBeCloseTo(expected, precision), never exact equality. Convention for unit-scale geometry: toBeCloseTo(2000, 0) (within 0.5 absolute). Round-trip serialization checks use precision 6 (tests/parity/README.md).isSolid(), isFace(), isWire(), isCompound(), isShape3D(), or getShapeKind().unwrap(measureVolume(shape)), unwrap(measureArea(shape)) — not just "operation returned Ok".expectClose(actual, expected, relTol?, absTol?) and expectKernelsAgree(valA, valB, label) from tests/helpers/kernelDivergences.ts (default relTol 1e-4).Worked example:
describe('fuse', () => {
it('fuses two boxes', () => {
const result = fuse(boxA, boxB);
expect(isOk(result)).toBe(true);
const shape = unwrap(result);
expect(isShape3D(shape)).toBe(true);
expect(unwrap(measureVolume(shape))).toBeCloseTo(2000, 0);
});
});| Command | What it runs |
|---|---|
npm run test | occt-wasm project, changed files only, no coverage (the pre-commit tier-2 gate) |
npm run test:full | occt-wasm project, full suite with coverage thresholds enforced |
npm run test:ci | occt-wasm project, full suite, no coverage (CI shards this 4-way) |
npm run test:watch | occt-wasm project, watch mode |
npm run test:occt / npm run test:brepkit | legacy OpenCascade.js / brepkit projects |
npx vitest run --project manifold tests/x.test.ts | manifold project (no npm script exists) |
npm run test:stress | tests/io-stress.test.ts only, via vitest.stress.config.ts |
npm run test:docs | extracts doc snippets, runs generated tests/docs/extracted.test.ts |
Single file — always pass --project:
npx vitest run --project occt-wasm tests/booleanFns.test.tsA bare npx vitest run tests/x.test.ts fans out to all four kernel projects (manifold, occt, brepkit, occt-wasm) and will fail on kernels the test was never gated for. This corrects the bare-run example in CLAUDE.md.
Runner facts (vitest.config.ts): pool: 'forks' with --max-old-space-size=6144; maxWorkers defaults to 4 because OCCT WASM linear memory grows monotonically per fork and more forks swap-thrash — raise locally with VITEST_MAX_WORKERS=<n>. Pre-commit runs changed-file tests (or the full coverage run with FULL_TESTS=1); pre-push runs no tests. See the quality-gates skill for the full gate stack and ci-triage for CI behavior.
Four vitest projects are generated from tests/helpers/kernelRegistry.ts: occt, brepkit, occt-wasm (the default and the merge gate), and manifold. Each project sets TEST_KERNEL=<id>; initKernel() and currentKernel (from ./setup.js) read it.
Decision table for a test that misbehaves on some kernel:
| Situation | Do this |
|---|---|
| Feature exists only on some kernels (capability gap) | Check getKernelCapabilities(id) flags in tests/helpers/kernelRegistry.ts; gate with it.skipIf(currentKernel !== 'occt-wasm')(...) (see tests/curves.test.ts) |
| Kernel produces a genuinely different-but-valid result | Add an entry to the divergence registry in tests/helpers/kernelDivergences.ts, then it('...', (ctx) => { skipIfDiverges(ctx, 'module.case'); ... }) |
| A whole describe block diverges | describe.skipIf(shouldSkipSuite('module.case'))(...) |
| Test file cannot run at all on one kernel | Add it to that kernel's excludeTests in kernelRegistry.ts |
Never inline if (isBrepkit) ctx.skip() — the registry is the single source of truth, and docs/kernel-conformance.md is generated from it (npm run conformance:generate). Registry entry format, divergence kinds, capability flags, and the excluded-suite inventory are in references/multi-kernel.md.
Kernel-agnostic behavioral specs (closed-form reference values, fast-check invariants) live in tests/parity/ — read tests/parity/README.md before adding one. Note its gate table predates the occt-wasm default; the required gate is now the occt-wasm project.
Root thresholds (vitest.config.ts): statements 85, branches 71, functions 91, lines 88. These are measured floors for the occt-wasm project, not aspirational targets — new code below the floor fails npm run test:full locally. Per-kernel: the occt project has its own thresholds; brepkit, occt-wasm, and manifold projects are 'informational' (thresholds enforced at the root config level for the default kernel). Each kernel's coverage excludes the other kernels' adapter dirs (coverageExcludesFor() in kernelRegistry.ts).
CI nuance: coverage is not a PR gate — the coverage job runs only on push to main with continue-on-error: true (.github/workflows/ci.yml). The enforcement point that bites during development is local npm run test:full (also pre-commit with FULL_TESTS=1). If a function-coverage miss blocks a commit, add tests for the new code rather than lowering thresholds; only re-floor after re-measuring with npm run test:full (and say so in the PR).
Performance benches live in benchmarks/*.bench.test.ts (~20 files), separate from the correctness suite. They share benchmarks/harness.ts (the bench() timer + printResults/writeResultsJSON/compareResults) and benchmarks/setup.ts (initBenchKernels(), driven by the BENCH_KERNELS env var). They run under their own config, vitest.bench.config.ts (include: ['benchmarks/**/*.bench.test.ts'], testTimeout: 120000, forks pool) — the root vitest.config.ts excludes benchmarks/ entirely.
Bench tests do not assert. Each it() runs bench() and prints a markdown/JSON table; nothing fails on slowness. Read the numbers by eye against a baseline.
Run commands:
| Command | What it runs |
|---|---|
npm run bench | all bench files; BENCH_KERNELS defaults to occt (legacy OpenCascade.js), single-kernel for speed |
npm run bench:compare | BENCH_KERNELS=both — occt + brepkit + occt-wasm side by side |
npm run bench:json | BENCH_KERNELS=both BENCH_OUTPUT_JSON=1 — emits the JSON block CI parses |
npx vitest run benchmarks/gridPattern.bench.test.ts --config vitest.bench.config.ts | one bench file |
Baselines are committed markdown reports under benchmarks/results/, not JSON fixtures: v8-baseline.md is a frozen snapshot; latest.md is auto-generated by kernel-comparison.bench.test.ts (generateReport writes it, header says "Do not edit manually"). The regression-oriented bench files (regression.bench.test.ts, regression-885.bench.test.ts, booleanBatch, gridPattern, optimization-targets) each pin a set of named scenarios whose medians are the thing you compare across runs.
Interpreting a regression: compareResults(current, baseline, threshold = 0.1) (in harness.ts) flags any benchmark whose median grew more than threshold (10% default) over the baseline. Match by the exact name string. Noise on shared machines runs ±9–15%, so treat a single sub-25% delta as noise and re-run before believing it.
Add or update a baseline:
benchmarks/<name>.bench.test.ts, import init from ./setup.js and helpers from ./harness.js, and follow an existing file (e.g. gridPattern.bench.test.ts).npm run bench:compare, which rewrites benchmarks/results/latest.md. Do not hand-edit it.<tag>-baseline.md alongside v8-baseline.md rather than overwriting the old frozen snapshot.CI blind spot. Only regression.bench.test.ts runs in CI — the dedicated benchmark job (.github/workflows/ci.yml) runs it PR-only, compares PR-vs-main medians at a 25% threshold, posts a comparison comment, and core.setFaileds (it is in the ci-pass needs-list, so a >25% regression blocks merge). Every other bench file sits in alwaysExclude (vitest.config.ts) and never runs in CI, so their committed baseline reports rot silently — run the suite locally when touching a hot path. See the ci-triage skill's "Blind spots" section.
| Symptom | Cause | Fix |
|---|---|---|
| Test passes locally, fails in another kernel project in CI-adjacent runs | Ran bare npx vitest run <file> or test isn't kernel-portable | Pass --project occt-wasm; use initKernel() not initOC; gate via capabilities or the divergence registry |
| Test hangs then fails at 90 s | Per-test testTimeout (90000 ms), often memory pressure from too many forks | Lower/raise VITEST_MAX_WORKERS; on CI this is why the test job is sharded (see ci-triage) |
beforeAll timeout at 30 s | First WASM boot slow, or the hook timeout argument was omitted | Keep the , 30000 third argument on beforeAll |
| Flaky float comparison | Exact equality or too-tight precision | toBeCloseTo(expected, 0) for unit-scale geometry; expectClose with relative tolerance for derived values |
| New test never runs in CI | File matches alwaysExclude in vitest.config.ts or a kernel excludeTests list | Check both lists; excluded suites (kernel-agreement, brepkit-validation, …) run only by explicit path — see references/multi-kernel.md |
Coverage functions threshold fails on test:full but CI is green | Coverage is main-only + non-blocking in CI; local run enforces | Add tests for uncovered functions before pushing |
| fast-check parity test flakes with huge volume error | Raw fc.double offsets create sub-micron near-coincident solids | Use the quantized fcOffset generator (tests/parity/README.md, "Input generators") |
| Import errors like "Cannot find module './foo'" | Missing .js extension on a .ts import | All imports use .js extensions; @/ for cross-directory |
initKernel() in beforeAll(..., 30000), imported from ./setup.js.@/index.js; .js extensions everywhere.isOk + unwrap, toBeCloseTo, type guards, measureVolume/measureArea.npx vitest run --project occt-wasm tests/<file>.test.ts green.npx vitest run --project brepkit tests/<file>.test.ts.references/multi-kernel.md — divergence registry entry format, capability flags, excluded-suite inventory and how each actually runs, parity-suite pointers.tests/parity/README.md — parity philosophy, tolerance policy, input generators.docs/kernel-conformance.md — generated capability/divergence matrix (npm run conformance:generate).adding-operations (what to test when adding an op), kernel-abstraction (adapter/kernel structure), debugging-geometry (when an assertion fails for geometric reasons), result-error-handling (Result semantics), quality-gates (pre-commit/validate stack), ci-triage (shard failures, CI-only reds, bench blind spots), memory-and-disposal (using/handle leaks that surface as test crashes).© andymai, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 1 other file (references) in .claude/skills/writing-tests of andymai/brepjs.
Open the folder on GitHubat commit 6e20740
Writing Tests next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Writing Tests this skillandymai/brepjs | 115 | — | ~4.3k | Automated safety check: Pass | Apache-2.0 | |
| Caliber Testingcaliber-ai-org/ai-setup | 1.3k | — | ~3.2k | Automated safety check: Pass | MIT | |
| LobeHub Testing Guidelobehub/lobehub | 83k | — | ~1.6k | Automated safety check: Pass | Custom licence | |
| Test Writing WorkflowiOfficeAI/AionUi | 33k | 1 repos | ~1.2k | Automated safety check: Pass | Apache-2.0 | |
| Ckeditor5 TestingTriliumNext/Trilium | 38k | — | ~3.3k | Automated safety check: Pass | AGPL-3.0 | |
| Issue To Regression Testbrunosabot/streamline-card | 269 | — | ~529 | Automated safety check: Pass | MIT |
caliber-ai-org/ai-setup
Writes Vitest tests following project patterns: tests/ directories, vi.mock() for module mocking with vi.hoisted() for test-time factories, global LLM mock from src/test/setup.ts, environment…
lobehub/lobehub
Explains how to write and run Vitest tests in the LobeHub monorepo: single-file commands, mocking rules, database model tests and regression tests for fixes.
iOfficeAI/AionUi
Sets the test-writing workflow for the repository: risk-first scenario lists, behavior-focused Vitest tests, a full run before each commit and a coverage target.
TriliumNext/Trilium
Testing CKEditor 5 plugins in the Trilium monorepo. An agent skill from TriliumNext/Trilium.
brunosabot/streamline-card
A skill your agent uses when the user asks to fix a bug, references a GitHub issue number, or describes an issue and wants a fix.
getsentry/sentry-dart
Enforce Sentry Dart/Flutter SDK test conventions for naming, structure, and fixtures.
andymai/brepjs
A skill your agent uses when authoring or editing a brepjs .brep.ts part — writing the geometry with the functional API (box, cylinder, fuse, cut, fillet, sketch→extrude…), declaring an expected…
andymai/brepjs
This skill should be used when managing WASM handle lifetimes or hunting memory leaks in brepjs — when a task mentions "createHandle() without using keyword risks WASM memory leak"…
andymai/brepjs
A skill your agent uses when a valid brepjs part should look designed rather than glued-from-primitives (products, toys, mechanisms, anything a human eyeballs), and when exporting/handing off the…
andymai/brepjs
This skill should be used when working across the JS/WASM boundary in brepjs — writing or debugging code in src/kernel/occt, src/kernel/occtWasm, or src/kernel/brepkit, or diagnosing symptoms like…
andymai/brepjs
This skill should be used when adding or extending a geometric shape operation in brepjs — the end-to-end recipe once the target module is chosen (which is decided by architecture-navigation) — when…
andymai/brepjs
This skill should be used when deciding which layer or module a new file, function, or directory belongs in, or when a layer-boundary check fails.
Works with
Categories
This skill should be used when writing, running, or fixing tests in the brepjs repository — when a task says "add a test", "write a regression test", "tests are failing", "test timed out", "coverage…. Writing Tests is an agent skill from andymai/brepjs. This skill should be used when writing, running, or fixing tests in the brepjs repository — when a task says "add a test", "write a regression test", "tests are failing", "test timed out", "coverage threshold failed", "run tests against brepkit/manifold/occt", "skip this test on kernel X", or when a new operation needs test coverage before merge.
Writing Tests fits situations like: tasks that involve Test coverage; tasks that involve Failing and flaky tests.
Run `npx skills add andymai/brepjs --skill writing-tests -a claude-code`. Or copy the skill folder (.claude/skills/writing-tests in andymai/brepjs) into .claude/skills/writing-tests in your project. Claude Code loads it when a task matches its description.
Run `npx skills add andymai/brepjs --skill writing-tests -a codex`. Or copy the skill folder (.claude/skills/writing-tests in andymai/brepjs) into .agents/skills/writing-tests in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add andymai/brepjs --skill writing-tests -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/writing-tests, .gemini/skills/writing-tests, .github/skills/writing-tests and .opencode/skills/writing-tests in your project.
Going by SKILL.md and its folder, Writing Tests needs the command-line tools its instructions call (npm and npx). Our summary lists: Node.js.
SKILL.md contains no URLs. Its commands use npm and npx, which can reach the network depending on how they are called. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Writing Tests is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 4.3k tokens (SKILL.md is roughly 17k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 2.4k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Writing Tests: Caliber Testing (caliber-ai-org/ai-setup, 1.3k stars), LobeHub Testing Guide (lobehub/lobehub, 83k stars), Test Writing Workflow (iOfficeAI/AionUi, 33k stars) and Ckeditor5 Testing (TriliumNext/Trilium, 38k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
andymai (a GitHub user) maintains it in andymai/brepjs, which has 115 GitHub stars. The repository holds 21 skills in this directory. The repository was last updated on October 8, 2026.
Source: andymai/brepjs on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.