Token导航 LogoToken导航TokenDH.com
待分类权限需确认github未标认证来源可访问许可证需确认审计通过

characterisation-tests特性测试

Agent Skill

用于辅助测试设计、自动化测试、用例整理和回归验证。它适合让 Agent 编写单元测试、端到端测试、测试计划或根据失败日志定位问题。使用时需要确认项目测试框架、运行命令和夹具数据,避免为了通过测试而改坏真实逻辑;涉及浏览器或外部服务时,应区分本地模拟、测试环境和生产环境。

总安装

259

周安装

11

GitHub Stars

643

下载量

91
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:characterisation-tests(特性测试)
来源仓库:https://github.com/citypaul/.dotfiles
仓库路径:skills/characterisation-tests
安装命令:
npx skills add https://github.com/citypaul/.dotfiles --skill characterisation-tests
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/citypaul/.dotfiles --skill characterisation-tests

简介

用于辅助测试设计、自动化测试和回归验证,帮助 Agent 编写单元测试或端到端测试。

  • 适合在 Codex、Claude、Cursor 和 Gemini CLI 中提升测试覆盖率和问题定位效率。
  • 通过确认项目测试框架和运行命令,让 Agent 生成测试用例或分析失败日志。
  • 安装方式:通过 npx skills add 从 GitHub 仓库安装,需确认本地环境和测试数据路径。
  • 注意区分测试环境与生产环境,避免因模拟不当导致逻辑错误或数据泄露。

SKILL.md

name
characterisation-tests
description
Use when modifying existing code that lacks tests and you need to document its actual current behavior before making changes -- the legacy code dilemma where you need tests to refactor safely but the code was not written for testability. Specifically for understanding and pinning down what code currently does, not what it should do. Do NOT use for test-driving new behavior (see tdd), general test writing patterns (see testing), verifying test effectiveness (see mutation-testing), or making untestable code testable (see finding-seams).

Characterisation Tests

For making untestable code testable first, load the finding-seams skill. For test-driving new behavior, load the tdd skill. For general test patterns, load the testing skill. For verifying test effectiveness after characterising, load the mutation-testing skill.

Deep-dive resources are in the resources/ directory. Load them on demand:

ResourceLoad when...
writing-process.mdNeed a worked example of the full characterisation process with targeted testing, async code, and when-to-stop guidance
modern-tooling.mdNeed guidance on Vitest snapshots, combination testing, approval testing, or handling non-determinism

Core Concept

A characterisation test is a test that characterizes the actual behavior of a piece of code. There's no "it should do this" -- the tests document what the system really does.

Characterisation tests have no moral authority. They don't assert correctness -- they detect *change*. When a characterisation test breaks, a human decides whether the change was intended. Also known as golden master testing or approval testing -- same concept, different names.

*-- Michael Feathers, Working Effectively with Legacy Code (2004)*

When to Use

  • Modifying existing code that has no tests (or inadequate tests)
  • Specifications are missing, incomplete, or contradict the running system
  • Code is too complex to reason about by reading alone
  • Facing the legacy code dilemma: need tests to refactor safely, but code resists testing
  • Need to understand what a function actually returns before changing it

When NOT to Use

  • Greenfield code -- new code should be test-driven from the start (see tdd skill)
  • You already have specs -- if requirements are clear and code is new, write behavior-driven tests that assert intended behavior, not characterisation tests that document whatever the code does
  • Code already has adequate tests -- characterise only the untested parts; don't duplicate existing coverage
  • As a permanent testing strategy -- characterisation tests are scaffolding; replace them with proper tests as you refactor

Naming and Identification

Characterisation tests must be immediately recognisable as characterisation tests -- to other LLMs, to humans, and to your future self. Someone reading the test file should understand at a glance: these tests document actual behavior, they are not assertions of correctness, and they are intended to be temporary.

Test Naming

Use characterises in the test name to distinguish from behavior-driven tests:

// ✅ Clearly identified as characterisation tests
describe('calculateDiscount characterisation', () => {
  it('characterises premium customer discount for < 5 years', () => { ... });
  it('characterises business customer loyalty bonus threshold', () => { ... });
});

// ❌ Indistinguishable from behavior-driven tests
describe('calculateDiscount', () => {
  it('should apply 15% discount for premium customers', () => { ... });
});

File Naming

Use a distinct file suffix so characterisation tests are visually separable in the file tree:

pricing.characterisation.test.ts    ← characterisation tests (temporary)
pricing.test.ts                     ← behavior-driven tests (permanent)

Documentation Within Tests

Add a block comment at the top of each characterisation test file explaining the purpose and the planned lifecycle. This is one of the few places where comments are essential -- the tests themselves document *what* the code does, but the comment documents *why these tests exist and when to remove them*:

/**
 * CHARACTERISATION TESTS -- documenting actual behavior, NOT asserting correctness.
 *
 * These tests pin down the current behavior of calculateDiscount so we can
 * safely refactor it. They should be replaced with behavior-driven tests
 * as the code is understood and restructured.
 *
 * See: characterisation-tests skill for the methodology.
 */
describe('calculateDiscount characterisation', () => { ... });

Suspicious Behavior

When a characterisation test captures behavior that looks like a bug, mark it explicitly:

it('characterises negative quantity handling -- SUSPICIOUS: returns negative discount', () => {
  // This may be a bug -- negative quantities produce negative discounts.
  // Documented as-is; escalate before changing.
  expect(calculateDiscount(-5, 'premium', 3)).toBe(-0.75);
});

The Algorithm

  1. Use a piece of code in a test harness
  2. Write an assertion you know will fail (use a dummy value like "PLACEHOLDER")
  3. Let the failure tell you the behavior -- the test runner shows the actual value
  4. Change the test so it expects the behavior the code actually produces
  5. Repeat -- let curiosity guide you; the code itself suggests what to test next
// Step 2: write assertion you know will fail
it('characterises formatPrice', () => {
  expect(formatPrice(1999)).toBe('PLACEHOLDER');
});
// Test output: expected 'PLACEHOLDER' but received '$19.99'

// Step 4: change test to expect actual behavior
it('characterises formatPrice', () => {
  expect(formatPrice(1999)).toBe('$19.99');
});

Heuristics

  1. Use coverage as your guide -- run vitest --coverage to find untested paths, then write tests to exercise them
  2. Production behavior IS the specification -- if deployed code does something, assume someone depends on it, even if it looks wrong
  3. Focus on the change area -- you don't need to characterise the entire codebase, only the code you're about to modify
  4. Mark suspicious behavior -- when you find something that looks like a bug, document it in the test but mark it as suspicious; don't silently "fix" it
  5. Look at the code -- these aren't black-box tests; read the code to guide which paths to characterise
  6. Validate with mutation testing -- after characterising, run the mutation-testing skill against the change area to verify your tests would catch real bugs. Coverage tells you which paths are *exercised*; mutation testing tells you which are *protected*.

When to Stop

You don't need 100% coverage of the entire codebase. Stop when:

  • Every branch your upcoming change touches has a characterisation test exercising it
  • One layer out from the change point is also covered (the branches that call into or are called by the code you're changing)
  • Mutation testing on the change area shows no surviving mutants in paths you'll modify

If you can't feel confident that your tests would detect a mistake in the specific code you're about to change, add more tests. If you can, stop.

When You Find Bugs

All legacy code has bugs. When you find one during characterisation:

  • If the system is deployed: someone may depend on the "buggy" behavior. Document it, mark the test as suspicious, escalate before changing it.
  • If the system is not yet deployed: fix it.
  • Always: include the characterisation test in your suite. Even if it captures a bug, it's documenting *reality*.

Characterisation Tests Are Temporary

They enable refactoring, then get replaced by proper behavior-driven tests:

  1. Characterise -- pin down current behavior as a safety net
  2. Refactor -- restructure code while characterisation tests detect any behavioral change
  3. Replace -- as you understand the code, write proper tests that assert *intended* behavior
  4. Remove -- retire characterisation tests once proper tests cover the same behavior
Like walking into a forest and drawing a line: "I own all of this area." After you know that, you can develop it by refactoring and writing more tests. Over time, the characterisation tests can go away.

Characterising Async Code

Async legacy code requires the same algorithm -- the key difference is awaiting results and controlling timing.

// Step 1: dummy assertion, same algorithm
it('characterises fetchUserOrders', async () => {
  const result = await fetchUserOrders('user-123');
  expect(result).toBe('PLACEHOLDER');
});
// Output: expected 'PLACEHOLDER' but received [{ id: 'order-1', ... }]

// Step 2: record actual behavior
it('characterises fetchUserOrders for known user', async () => {
  const result = await fetchUserOrders('user-123');
  expect(result).toEqual([
    expect.objectContaining({ id: 'order-1', status: 'shipped' }),
  ]);
});

Key concerns for async characterisation:

  • Use real seams for I/O -- pass async dependencies as parameters rather than hitting real services (see finding-seams skill)
  • Error paths -- characterise both resolved and rejected states: await expect(fn()).rejects.toThrow()
  • Timing-dependent behavior -- use vi.useFakeTimers() and vi.advanceTimersByTime() to control time (see modern-tooling.md)
  • Streams and events -- collect emitted values into an array, then assert on the collected result
// Characterising an event emitter
it('characterises order processor events', async () => {
  const events: string[] = [];
  processor.on('status', (s: string) => events.push(s));
  await processor.process(testOrder);
  expect(events).toEqual(['validating', 'processing', 'complete']);
});

Common Mistakes

MistakeFix
Treating characterisation tests as permanentThey are scaffolding -- replace with behavior-driven tests as you refactor
"Fixing" bugs in characterisation testsDocument the actual behavior, mark as suspicious, escalate
Trying to characterise the entire codebaseFocus on the area you're about to change + one layer out
Writing characterisation tests based on what code *should* doLet the code tell you what it does -- use the algorithm above
Skipping mutation testing after characterisingCoverage says paths ran; mutation testing says tests would catch changes
Using characterisation tests for new codeNew code should be test-driven (see tdd skill)
Using vi.mock() for sensing instead of parameter injectionPass a sensing function as a parameter (see finding-seams skill)
Not awaiting async resultsUse async/await in characterisation tests -- a synchronous assertion on a promise always passes

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

36.79%
按下载量换算33

Claude

28.75%
按下载量换算26

Cursor

19.74%
按下载量换算18

Gemini CLI

9.2%
按下载量换算8

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

权限需确认

当前来源未能明确判断权限范围,默认进入异常复核队列。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills