test-first

test-first is a skill for Claude Code, Codex from pingfanfan/hello-dsh. It costs 48 tokens per session (1,028 once invoked), scanned A, original, MIT.

A test-first development guide, where tests are written before the code they check. TDD, or test-driven development, means first writing a test that fails, then writing the simplest code that makes it pass.

In plain words
What is it for?
Use it when adding features, fixing defects, or refactoring code to define expected behavior, test edge cases, and verify that tests fail when the implementation is removed.
Why use it?
It shows that a test checks the intended behavior instead of merely passing because the implementation was already written, and it helps reproduce bugs before fixing them.

Skill for Claude CodeCodex

Install

Getting it into your agent

One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.

agentmods
npx agentmods add skills/pingfanfan/hello-dsh/test-first
Any agent
npx skills add pingfanfan/hello-dsh --skill test-first
Clone the repo
git clone --depth 1 https://github.com/pingfanfan/hello-dsh

Made for: Claude Code, Codex.

Wrote this? Show the measurements

A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.

agentmods badge for test-first

README.md
[![agentmods](https://agentmods.dev/badge/skills/pingfanfan/hello-dsh/test-first.svg)](https://agentmods.dev/skills/pingfanfan/hello-dsh/test-first)
Your own site
<a href="https://agentmods.dev/skills/pingfanfan/hello-dsh/test-first"><img src="https://agentmods.dev/badge/skills/pingfanfan/hello-dsh/test-first.svg" alt="Measured on agentmods" height="20"></a>
Per session 48 Skills are progressive disclosure: only the name and description are preloaded; the body loads when the skill is used.
When invoked 1,028 The whole file, excluding the scripts and references it only reads on demand.
Security scan A 0 findings. Scan, not verified.
Origin original No closer match found in the catalogue.
Token cost

What it costs to keep this loaded

Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.

ModelPer sessionOnce invoked
Fable 5 $0.00048 $0.01028
Opus 5 $0.00024 $0.00514
Sonnet 5 $0.00010 $0.00206
Haiku 4.5 $0.00005 $0.00103

Measured 4d ago against content hash 2501a91f7505, method: parsed. Prices are Anthropic first-party input rates as of 2026-08-30, from the pricing page.

Security

Grade A, and why

test-first scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 4d ago.

A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.

Nothing flagged

None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.

examples/skills/test-first/SKILL.md · 100 lines

What it actually says

先写测试

核心判断标准只有一条:把实现回退掉,这个测试会不会失败?

不会失败的测试等于没有。它不保护任何东西,只制造覆盖率数字和维护成本。

顺序

先写测试有个具体的好处,跟"纪律"无关:它是唯一能证明测试有效的方法。

如果你先写实现再补测试,测试一上来就是绿的,你无法知道它是因为实现正确而绿,还是因为它根本没断言到关键的东西。先写测试的话,你会亲眼看到它从红变绿,这就是证明。

修 bug

  1. 写一个能复现这个 bug 的测试,跑,看它失败
  2. 确认失败信息就是这个 bug 的表现,不是别的原因
  3. 修实现
  4. 跑,看它变绿

第 2 步经常被跳过。测试失败了不代表它失败在你以为的地方,可能只是参数写错了。

加功能

  1. 写一个描述期望行为的测试,跑,看它失败
  2. 用最简单的方式让它通过
  3. 重构,保持绿
  4. 下一个行为,回到第 1 步

「最简单的方式」是认真的:如果硬编码返回值能让第一个测试通过,就先硬编码。第二个测试会逼你写出真实逻辑。这不是浪费,它避免了你一上来就构造一个想象中的通用方案。

测什么

测行为,不测实现。

测这个 不测这个
输入 X 得到输出 Y 内部调用了哪个私有方法
出错时抛什么、状态如何 中间变量的值
副作用(写了什么、发了什么事件) 具体的调用次数(除非次数本身是契约)
边界:空、单个、超长、零、负数 私有字段

判断方法:重构实现但不改行为时,这个测试要不要跟着改? 要改,说明它测的是实现。

断言要具体

// 没用:任何非空返回都能过
expect(result).toBeTruthy()

// 有用
expect(result).toEqual({ id: 'a1', status: 'active', retries: 0 })
// 没用:任何错误都能过,包括拼写错误导致的 TypeError
expect(() => parse(bad)).toThrow()

// 有用
expect(() => parse(bad)).toThrow(/unexpected token at line 3/)

一个测试一件事

测试名要能说清它在测什么。如果名字里出现「以及」,就该拆。

✗ test('创建会话并加载历史并处理错误')
✓ test('创建会话时生成唯一 id')
✓ test('加载不存在的会话时返回 undefined')

好处是失败时你直接从名字就知道哪儿坏了,不用读测试体。

覆盖率的真相

覆盖率只说明代码被执行过,不说明行为被验证过。

一个真实的例子:DSH 的 ACP 服务器曾经有 178 个绿色测试、100% 行覆盖率,但真实编辑器一连上就崩。因为所有测试都是手动挂载插件的,绕过了真实的加载路径,那条路径上的 bug 一个都没碰到。

所以:覆盖率是必要条件,不是证据。 100% 覆盖率的测试套件完全可能对真实的失败模式一无所知。

补充的判断:

  • 有没有测失败路径,还是只测了成功路径
  • 有没有走真实的入口(真实的 CLI、真实的加载器、真实的子进程),还是全在测试专用的挂载方式上
  • 边界条件覆盖了吗

不要做的事

  • 不要写只调用一下函数就 expect(true) 的测试
  • 不要为了覆盖率数字写测试
  • 不要在测试里复述实现逻辑(那样实现错了测试也跟着错)
  • 不要 mock 掉你真正想验证的那个东西
  • 不要跳过"看它失败"这一步
  • 不要相信「测试全绿」等于「功能正确」
Changes

What this file has done since we first saw it

Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.

  1. 4d ago First seen · 100 lines · 48 tokens per session scan A 2501a91f7505

Subscribe to this mod's changes

test-first is a skill published in the GitHub repository pingfanfan/hello-dsh (87 stars, last pushed 20d ago), licensed MIT. It adds 48 tokens to every session and 1,028 once invoked, about $0.0002 per session on Opus 5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-30.

Related

Other skills, from other repositories

dsh-plugin-guide

Use when developing, reviewing, packaging, debugging, or answering questions about DeepSeek Harness (DSH) plugins — the plugin-based agent harness on vendored Cordis. Applies the official plugin-development constraints (plugin contract, cordis.yml layers, services/events/effects, tool DSL, bundles/profiles) backed by…

PerryLink/dsh-plugin-guide · 76 tokens

tdd

测试驱动开发(Test-Driven Development)。当用户希望以测试优先的方式构建功能或修复 bug、提到 "red-green-refactor"(红-绿-重构),或需要集成测试时使用。.

gongyijie85/mattpocock-skills-dsh-zh · 52 tokens

tdd

Test-driven development. Use when the user wants to build features or fix bugs test-first, mentions "red-green-refactor", or wants integration tests.

gongyijie85/mattpocock-skills-dsh · 33 tokens

dsh-web-release

Release and publish the dsh-web monorepo (DSH Web GUI plugin family + skin collection) — bump all packages to one unified version, commit and tag (tags are cut from main after dev integration; dev is the integration branch), push the vX.Y.Z tag that triggers the GitHub Actions publish pipeline, and verify the npm…

zhu1090093659/dsh-web · 151 tokens

dsh-web-community-plugin-developer

Develop a DSH community plugin and register it in the dsh-web Community Plugins index — author the plugin in the contributor's own repository following the official cordis bundle standard, add its entry to packages/dsh-community-plugins/community.json, regenerate the index with scripts/community-index, rebuild and…

zhu1090093659/dsh-web · 123 tokens

dsh-web-skin-developer

Build a new skin for the dsh-web skin collection (DSH Web GUI) and publish it into the Skin Center — the first-level settings section — scaffold with scripts/dsh-skin-new, author the v2 skin.json manifest plus skin.css token remap (pure asset directory, no package.json, no build step), validate with scripts/dsh-skin…

zhu1090093659/dsh-web · 120 tokens