Index of every page on this site: llms.txt
All skills
harlan-zw avatar

/unit-tests

@2a530d0
Run it yourself

Write or review unit tests through exported behavior. Use for new tests, bug-fix regression tests, coverage, replacing brittle implementation checks, or a test that went red because behaviour changed on purpose.

  • 1 file
  • 4.6 KB
  • MIT
  • Updated last month
  • GitHub
Use this Skill: https://skilld.dev/gh/harlan-zw/harlan-agent-kit/unit-tests

Nothing lands on disk. Nothing to clean up.

Fork this Skill

Edit a local copy. It keeps the author and licence.

SKILL.md

≈56 tokens for metadata: the name and description. ≈1.1k when used: this file.

Description uses 2.8% of example budget

Before choosing a Skill, your Agent reads its name and description. All available Skills share that space.

  • A shorter description leaves more room for other Skills. This entry exceeds our 1% size suggestion.

In our Claude Code example, all Skill names and descriptions share 8,000 characters. This Skill uses ≈224 characters, or 2.8%.

The 1% threshold is a size suggestion. Longer descriptions can still fit.

Your model, settings, and other Skills decide how much text your Agent can read.

Example settings and source

The example uses a 200k-token context and default Claude Code settings. The count includes the name, description, separators, and when_to_use when present. Codex also counts local file paths.

Skit's source and limits: Codex 0.160.1, Claude Code 2.1.292.

Unit Tests

A unit test exercises an API. Input goes in, output gets asserted. Everything else is a fact check against the source file and should be deleted.

Worktree isolation

Before writing or deleting tests, read and follow the worktree isolation contract. Keep mutation in a task-owned wt worktree with a live claim. Keep the primary checkout read only.

The failure mode this exists to stop

Fact-check tests restate what the file already says. They pass by construction, break on harmless refactors, and prove nothing.

// all of these are fact checks, not tests
expect(Object.keys(config)).toEqual(['name', 'hooks', 'setup'])
expect(source).toContain('export function resolvePath')
expect(module.default.name).toBe('my-module')
expect(handlers).toHaveLength(3)
expect(typeof createClient).toBe('function')

They feel productive because the file goes green. The suite grows, review cost grows, and no bug is ever caught.

The two questions

Before keeping any assertion:

  1. Delete it if it can fail while the code is still correct. Renaming an internal, reordering an array, adding a config key must never turn the suite red.
  2. Delete it if it can pass while the code is broken.

An assertion that survives both is testing behaviour. Anything else is ballast.

Shape

Every test is three lines of intent: build an input, call an export, assert the result.

it('rejects a path outside the root', () => {
  const result = resolvePath('/srv/app', '../../etc/passwd')
  expect(result).toEqual({ _tag: 'Err', reason: 'escapes-root' })
})
  • Call it the way a consumer calls it: through exports, not through a deep internal import.
  • Assert on the returned value, the thrown error, or a recorded side effect at the boundary. Not on internal state.
  • One concrete input, one concrete expectation. Table-drive the variants with it.each.
  • Prefer a real fixture over a mock. Mocking the module under test means you are testing the mock.

Tests are scratchpad

Cheap to write, cheap to throw away. Deleting a test is a normal outcome, not a regression.

  • When behaviour intentionally changes, delete the test and write the new one. Do not repair old assertions until they go green; that is how a suite ossifies around an API nobody wants.
  • Never write a test to raise coverage. Untested trivial code is fine.
  • If a test costs more to maintain than the bug it would catch, it is negative value. Remove it.
  • A test file should be deletable in one commit without anyone needing to reconstruct why it existed.

Never test

  • File contents, dist/ output, or source text as a string
  • That a symbol exists, is a function, or has N keys
  • The shape of a config or options object
  • Snapshots of anything except stable output a human actually reads (rendered markup, generated file a user opens, CLI output). Never snapshot an internal data structure.
  • "Does not throw" as the only assertion
  • Private/internal functions reached by deep import

Worth testing

  • Pure functions: input to output, including the boring edges (empty, zero, unicode).
  • Error paths: bad input produces the tagged Err or the thrown error with the right discriminant.
  • Boundary parsers: untrusted input becomes a precise type, or is rejected.
  • Transforms and builds: feed a real fixture in, assert on the parsed output value, not the emitted text.
  • Regressions: the failing test written before a bug fix, named for the behaviour, not the ticket.

Reviewing an existing suite

Read the file and bucket every expect into fact check, behaviour, or unclear. Report the counts, list the fact checks with line numbers, and propose deletions. Do not rewrite a fact check into a behaviour test unless the underlying behaviour is genuinely worth covering; usually the right patch is a deletion.

Report in this shape:

resolve-path.test.ts — 14 expects: 9 fact check, 4 behaviour, 1 unclear

Delete (fact check):
  L12  expect(Object.keys(opts)).toEqual([...])   restates the options type
  L27  expect(typeof resolvePath).toBe('function') passes by construction
  L31-38  snapshot of the internal config object

Unclear:
  L44  asserts cache.size === 1 — internal state; is the caching itself a documented guarantee?

Keep: L52, L58, L63, L70 (input to output, incl. two error paths)

Source: SKILL.md on GitHub

No rule matched.

skilld matched fixed text patterns in SKILL.md and file names. Patterns miss obfuscated code.

skilld run checks every file with the same patterns. It asks for approval before it loads a Skill with a behavior marked Needs approval.

No third-party reports yet.

Signed by skilld at 2a530d0. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 days ago.

Activeupdated last month
argument-hint
[file or directory to test or review]

README badge

README badge for harlan-zw/harlan-agent-kit/unit-tests