tdd-workflow
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseTest-Driven Development (TDD) Workflow
测试驱动开发(TDD)工作流
Overview
概述
Write the test first. Watch it fail. Write minimal code to pass.
Core principle: If you didn't watch the test fail, you don't know if it tests the right thing.
Violating the letter of the rules is violating the spirit of the rules.
先编写测试,看着测试失败,再编写最少的代码让测试通过。
核心原则: 如果你没看到测试失败,你就无法确定它是否测试了正确的内容。
违反规则的字面要求,就是违反规则的精神。
When to Use
使用场景
Always:
- New features
- Bug fixes
- Refactoring
- Behavior changes
Exceptions (ask your human partner):
- Throwaway prototypes
- Generated code
- Configuration files
Thinking "skip TDD just this once"? Stop. That's rationalization.
始终适用:
- 新功能开发
- Bug修复
- 代码重构
- 行为变更
例外情况(需咨询团队成员):
- 一次性原型
- 自动生成的代码
- 配置文件
如果你在想“就这一次跳过TDD”?打住,这只是自我合理化的借口。
Session-Management Integration
会话管理集成
Enhanced when session-management is active:
If session has "TDD" in objective or uses flag:
--tdd- Automatic RED-GREEN-REFACTOR checkpoint tracking
- Test coverage metrics in session report
- TDD cycle enforcement (blocks skipping steps)
- Session handoff includes test statistics
Works standalone without session-management - all core TDD functionality available.
当会话管理激活时的增强功能:
如果会话目标包含“TDD”或使用了标志:
--tdd- 自动跟踪RED-GREEN-REFACTOR各阶段的检查点
- 会话报告中包含测试覆盖率指标
- 强制遵循TDD循环步骤(阻止跳过环节)
- 会话交接时包含测试统计数据
无需会话管理也可独立使用 - 所有核心TDD功能均可用。
The Iron Law
铁律
NO PRODUCTION CODE WITHOUT A FAILING TEST FIRSTWrite code before the test? Delete it. Start over.
No exceptions:
- Don't keep it as "reference"
- Don't "adapt" it while writing tests
- Don't look at it
- Delete means delete
Implement fresh from tests. Period.
NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST先写了生产代码再写测试?删掉它,重新开始。
没有例外:
- 不要把它当作“参考”保留
- 不要在写测试时“改编”它
- 不要看它
- 删就是彻底删掉
从测试开始重新实现,就这么简单。
Red-Green-Refactor
RED-GREEN-REFACTOR循环
RED → Verify RED → GREEN → Verify GREEN → REFACTOR → RepeatRED → 验证RED状态 → GREEN → 验证GREEN状态 → REFACTOR → 重复RED - Write Failing Test
RED - 编写失败的测试
Write one minimal test showing what should happen.
Good:
typescript
test('retries failed operations 3 times', async () => {
let attempts = 0;
const operation = () => {
attempts++;
if (attempts < 3) throw new Error('fail');
return 'success';
};
const result = await retryOperation(operation);
expect(result).toBe('success');
expect(attempts).toBe(3);
});Clear name, tests real behavior, one thing.
Bad:
typescript
test('retry works', async () => {
const mock = jest.fn()
.mockRejectedValueOnce(new Error())
.mockRejectedValueOnce(new Error())
.mockResolvedValueOnce('success');
await retryOperation(mock);
expect(mock).toHaveBeenCalledTimes(3);
});Vague name, tests mock not code.
Requirements:
- One behavior
- Clear name
- Real code (no mocks unless unavoidable)
Session Integration: If session-management active, I'll prompt for checkpoint label.
编写一个最小化的测试,明确预期行为。
示例:好的测试
typescript
test('retries failed operations 3 times', async () => {
let attempts = 0;
const operation = () => {
attempts++;
if (attempts < 3) throw new Error('fail');
return 'success';
};
const result = await retryOperation(operation);
expect(result).toBe('success');
expect(attempts).toBe(3);
});名称清晰,测试真实行为,只聚焦一件事。
示例:不好的测试
typescript
test('retry works', async () => {
const mock = jest.fn()
.mockRejectedValueOnce(new Error())
.mockRejectedValueOnce(new Error())
.mockResolvedValueOnce('success');
await retryOperation(mock);
expect(mock).toHaveBeenCalledTimes(3);
});名称模糊,测试的是模拟对象而非真实代码。
要求:
- 只测试一个行为
- 名称清晰明确
- 使用真实代码(除非万不得已,否则不要用模拟对象)
会话集成: 如果会话管理已激活,我会提示你输入检查点标签。
Verify RED - Watch It Fail
验证RED状态 - 确认测试失败
MANDATORY. Never skip.
bash
npm test path/to/test.test.tsConfirm:
- Test fails (not errors)
- Failure message is expected
- Fails because feature missing (not typos)
Test passes? You're testing existing behavior. Fix test.
Test errors? Fix error, re-run until it fails correctly.
Session Integration: RED checkpoint automatically created with test file path.
这是强制性步骤,绝对不能跳过。
bash
npm test path/to/test.test.ts确认:
- 测试失败(不是报错)
- 失败信息符合预期
- 失败原因是功能缺失(而非拼写错误)
测试通过了? 说明你在测试已有的行为,需要修改测试。
测试报错了? 修复错误,重新运行直到测试正确失败。
会话集成: 自动创建RED状态检查点,并记录测试文件路径。
GREEN - Minimal Code
GREEN - 编写最小化代码
Write simplest code to pass the test.
Good:
typescript
async function retryOperation<T>(fn: () => Promise<T>): Promise<T> {
for (let i = 0; i < 3; i++) {
try {
return await fn();
} catch (e) {
if (i === 2) throw e;
}
}
throw new Error('unreachable');
}Just enough to pass.
Bad:
typescript
async function retryOperation<T>(
fn: () => Promise<T>,
options?: {
maxRetries?: number;
backoff?: 'linear' | 'exponential';
onRetry?: (attempt: number) => void;
}
): Promise<T> {
// YAGNI - You Aren't Gonna Need It
}Over-engineered.
Don't add features, refactor other code, or "improve" beyond the test.
编写最简单的代码让测试通过。
示例:好的实现
typescript
async function retryOperation<T>(fn: () => Promise<T>): Promise<T> {
for (let i = 0; i < 3; i++) {
try {
return await fn();
} catch (e) {
if (i === 2) throw e;
}
}
throw new Error('unreachable');
}刚好满足测试要求。
示例:不好的实现
typescript
async function retryOperation<T>(
fn: () => Promise<T>,
options?: {
maxRetries?: number;
backoff?: 'linear' | 'exponential';
onRetry?: (attempt: number) => void;
}
): Promise<T> {
// YAGNI - 你不会用到这些
}过度设计。
不要添加额外功能、重构其他代码,或者超出测试要求“优化”代码。
Verify GREEN - Watch It Pass
验证GREEN状态 - 确认测试通过
MANDATORY.
bash
npm test path/to/test.test.tsConfirm:
- Test passes
- Other tests still pass
- Output pristine (no errors, warnings)
Test fails? Fix code, not test.
Other tests fail? Fix now.
Session Integration: GREEN checkpoint created, cycle count incremented.
这是强制性步骤。
bash
npm test path/to/test.test.ts确认:
- 当前测试通过
- 其他测试仍然通过
- 输出干净(无错误、无警告)
测试失败了? 修复代码,不要修改测试。
其他测试失败了? 立即修复。
会话集成: 创建GREEN状态检查点,循环计数加1。
REFACTOR - Clean Up
REFACTOR - 代码清理
After green only:
- Remove duplication
- Improve names
- Extract helpers
Keep tests green. Don't add behavior.
Session Integration: Optional REFACTOR checkpoint if significant changes.
只有在测试通过后才能进行:
- 移除重复代码
- 改进命名
- 提取辅助函数
保持测试通过,不要添加新行为。
会话集成: 如果有重大变更,可选择创建REFACTOR状态检查点。
Repeat
重复循环
Next failing test for next feature.
为下一个功能编写新的失败测试。
Session-Management Commands
会话管理命令
When session-management is installed and active:
当会话管理已安装并激活时:
Start TDD Session
启动TDD会话
bash
undefinedbash
undefinedExplicit TDD session
显式启动TDD会话
python scripts/session.py start feature/auth --objective "Add auth (TDD)"
python scripts/session.py start feature/auth --objective "Add auth (TDD)"
Or with TDD flag
或使用TDD标志
python scripts/session.py start feature/auth --tdd
Activates enhanced TDD mode with:
- Automatic checkpoint prompts
- Cycle tracking
- Test coverage monitoring
- Enforced verification stepspython scripts/session.py start feature/auth --tdd
激活增强型TDD模式,包含:
- 自动检查点提示
- 循环跟踪
- 测试覆盖率监控
- 强制验证步骤TDD Checkpoints
TDD检查点命令
bash
undefinedbash
undefinedRED checkpoint (test written, verified failing)
RED状态检查点(测试已编写,且已验证失败)
python scripts/session.py checkpoint --label "red-user-validation" --tdd-phase RED
python scripts/session.py checkpoint --label "red-user-validation" --tdd-phase RED
GREEN checkpoint (minimal code, test passing)
GREEN状态检查点(已编写最小化代码,测试通过)
python scripts/session.py checkpoint --label "green-user-validation" --tdd-phase GREEN
python scripts/session.py checkpoint --label "green-user-validation" --tdd-phase GREEN
REFACTOR checkpoint (optional, when refactoring)
REFACTOR状态检查点(可选,重构时使用)
python scripts/session.py checkpoint --label "refactor-extract-validator" --tdd-phase REFACTOR
undefinedpython scripts/session.py checkpoint --label "refactor-extract-validator" --tdd-phase REFACTOR
undefinedView TDD Metrics
查看TDD指标
bash
undefinedbash
undefinedSession summary with TDD stats
包含TDD统计数据的会话摘要
python scripts/session.py status
python scripts/session.py status
Shows:
显示内容:
- RED-GREEN-REFACTOR cycles completed
- 已完成的RED-GREEN-REFACTOR循环数
- Tests written vs passing
编写的测试数 vs 通过的测试数
- Average cycle time
- 平均循环时间
- Coverage trend
- 覆盖率趋势
undefinedundefinedEnd TDD Session
结束TDD会话
bash
python scripts/session.py end --handoffGenerates handoff including:
- Total TDD cycles completed
- Test files created
- Coverage metrics
- Discipline adherence (skipped verifications flagged)
bash
python scripts/session.py end --handoff生成交接文档,包含:
- 已完成的TDD循环总数
- 创建的测试文件
- 覆盖率指标
- 准则遵守情况(标记跳过的验证步骤)
Good Tests
优质测试的标准
| Quality | Good | Bad |
|---|---|---|
| Minimal | One thing. "and" in name? Split it. | |
| Clear | Name describes behavior | |
| Shows intent | Demonstrates desired API | Obscures what code should do |
| 质量维度 | 好的测试 | 差的测试 |
|---|---|---|
| 最小化 | 只测试一件事。名称中有“和”?拆分它。 | |
| 清晰性 | 名称描述行为 | |
| 意图明确 | 展示期望的API | 模糊代码应有的行为 |
Why Order Matters
为什么顺序很重要
"I'll write tests after to verify it works"
Tests written after code pass immediately. Passing immediately proves nothing:
- Might test wrong thing
- Might test implementation, not behavior
- Might miss edge cases you forgot
- You never saw it catch the bug
Test-first forces you to see the test fail, proving it actually tests something.
"I already manually tested all the edge cases"
Manual testing is ad-hoc. You think you tested everything but:
- No record of what you tested
- Can't re-run when code changes
- Easy to forget cases under pressure
- "It worked when I tried it" ≠ comprehensive
Automated tests are systematic. They run the same way every time.
"Deleting X hours of work is wasteful"
Sunk cost fallacy. The time is already gone. Your choice now:
- Delete and rewrite with TDD (X more hours, high confidence)
- Keep it and add tests after (30 min, low confidence, likely bugs)
The "waste" is keeping code you can't trust. Working code without real tests is technical debt.
"TDD is dogmatic, being pragmatic means adapting"
TDD IS pragmatic:
- Finds bugs before commit (faster than debugging after)
- Prevents regressions (tests catch breaks immediately)
- Documents behavior (tests show how to use code)
- Enables refactoring (change freely, tests catch breaks)
"Pragmatic" shortcuts = debugging in production = slower.
"Tests after achieve the same goals - it's spirit not ritual"
No. Tests-after answer "What does this do?" Tests-first answer "What should this do?"
Tests-after are biased by your implementation. You test what you built, not what's required. You verify remembered edge cases, not discovered ones.
Tests-first force edge case discovery before implementing. Tests-after verify you remembered everything (you didn't).
30 minutes of tests after ≠ TDD. You get coverage, lose proof tests work.
“我会先写代码,之后再写测试验证”
后写的测试会立即通过,而立即通过的测试无法证明任何事情:
- 可能测试了错误的内容
- 可能测试的是实现细节而非行为
- 可能遗漏了你忘记的边缘情况
- 你永远看不到它捕捉Bug的过程
先写测试会迫使你看到测试失败,证明它确实测试了某些内容。
“我已经手动测试了所有边缘情况”
手动测试是临时的。你以为你测试了所有情况,但:
- 没有记录你测试了什么
- 代码变更时无法重新运行测试
- 压力下很容易忘记某些情况
- “我试的时候是好的” ≠ 全面测试
自动化测试是系统化的,每次运行的方式都完全相同。
“删掉X小时的工作太浪费了”
这是沉没成本谬误。时间已经花了,你现在的选择是:
- 删掉代码,用TDD重写(再花X小时,获得高可信度)
- 保留代码,之后补测试(花30分钟,可信度低,可能存在Bug)
真正的“浪费”是保留你无法信任的代码。没有可靠测试的可用代码就是技术债务。
“TDD太教条了,务实意味着要灵活调整”
TDD本身就是务实的:
- 在提交前发现Bug(比提交后调试更快)
- 防止回归(测试会立即捕捉到代码破坏)
- 文档化行为(测试展示了如何使用代码)
- 支持重构(可以自由修改代码,测试会捕捉到问题)
所谓的“务实”捷径 = 生产环境中调试 = 更慢。
“后写测试也能达到同样的目标 - 重要的是精神而非形式”
不对。后写的测试回答的是“这段代码做了什么?”,先写的测试回答的是“这段代码应该做什么?”
后写的测试会被你的实现方式带偏,你测试的是你构建的东西,而非需求要求的东西。你验证的是你记得的边缘情况,而非你发现的边缘情况。
先写测试会迫使你在实现前发现边缘情况。后写测试只能验证你是否记得所有情况(你肯定会忘)。
花30分钟后写测试 ≠ TDD。你得到了覆盖率,但失去了测试有效的证明。
Common Rationalizations
常见的自我合理化借口
| Excuse | Reality |
|---|---|
| "Too simple to test" | Simple code breaks. Test takes 30 seconds. |
| "I'll test after" | Tests passing immediately prove nothing. |
| "Tests after achieve same goals" | Tests-after = "what does this do?" Tests-first = "what should this do?" |
| "Already manually tested" | Ad-hoc ≠ systematic. No record, can't re-run. |
| "Deleting X hours is wasteful" | Sunk cost fallacy. Keeping unverified code is technical debt. |
| "Keep as reference, write tests first" | You'll adapt it. That's testing after. Delete means delete. |
| "Need to explore first" | Fine. Throw away exploration, start with TDD. |
| "Test hard = design unclear" | Listen to test. Hard to test = hard to use. |
| "TDD will slow me down" | TDD faster than debugging. Pragmatic = test-first. |
| "Manual test faster" | Manual doesn't prove edge cases. You'll re-test every change. |
| "Existing code has no tests" | You're improving it. Add tests for existing code. |
| 借口 | 现实 |
|---|---|
| “太简单了,不需要测试” | 简单代码也会出错,写测试只需要30秒。 |
| “我之后再写测试” | 立即通过的测试无法证明任何事情。 |
| “后写测试也能达到同样目标” | 后写测试=“这段代码做了什么?”,先写测试=“这段代码应该做什么?” |
| “已经手动测试过了” | 临时测试≠系统化测试,没有记录,无法重跑。 |
| “删掉X小时的工作太浪费了” | 沉没成本谬误,保留未验证的代码是技术债务。 |
| “保留作为参考,先写测试” | 你会忍不住改编它,这本质上还是后写测试。删就是彻底删掉。 |
| “需要先探索一下” | 没问题,扔掉探索性代码,用TDD重新开始。 |
| “测试难写=设计不清晰” | 倾听测试的反馈:难测试的代码也难使用。 |
| “TDD会拖慢我的速度” | TDD比调试更快,务实的做法就是先写测试。 |
| “手动测试更快” | 手动测试无法覆盖所有边缘情况,每次代码变更你都要重新测试。 |
| “现有代码没有测试” | 你正在改进它,为现有代码添加测试。 |
Red Flags - STOP and Start Over
危险信号 - 立即停止并重新开始
- Code before test
- Test after implementation
- Test passes immediately
- Can't explain why test failed
- Tests added "later"
- Rationalizing "just this once"
- "I already manually tested it"
- "Tests after achieve the same purpose"
- "It's about spirit not ritual"
- "Keep as reference" or "adapt existing code"
- "Already spent X hours, deleting is wasteful"
- "TDD is dogmatic, I'm being pragmatic"
- "This is different because..."
All of these mean: Delete code. Start over with TDD.
- 先写了生产代码
- 实现后才写测试
- 测试立即通过
- 无法解释测试失败的原因
- “后来”才添加测试
- 自我合理化“就这一次”
- “我已经手动测试过了”
- “后写测试也能达到同样目的”
- “重要的是精神而非形式”
- “保留作为参考”或“改编现有代码”
- “已经花了X小时,删掉太浪费了”
- “TDD太教条,我是务实的”
- “这次情况特殊因为...”
所有这些情况都意味着:删掉代码,用TDD重新开始。
Example: Bug Fix
示例:Bug修复
Bug: Empty email accepted
RED
typescript
test('rejects empty email', async () => {
const result = await submitForm({ email: '' });
expect(result.error).toBe('Email required');
});Verify RED
bash
$ npm test
FAIL: expected 'Email required', got undefinedGREEN
typescript
function submitForm(data: FormData) {
if (!data.email?.trim()) {
return { error: 'Email required' };
}
// ...
}Verify GREEN
bash
$ npm test
PASSREFACTOR
Extract validation for multiple fields if needed.
Bug: 空邮箱被接受
RED状态
typescript
test('rejects empty email', async () => {
const result = await submitForm({ email: '' });
expect(result.error).toBe('Email required');
});验证RED状态
bash
$ npm test
FAIL: expected 'Email required', got undefinedGREEN状态
typescript
function submitForm(data: FormData) {
if (!data.email?.trim()) {
return { error: 'Email required' };
}
// ...
}验证GREEN状态
bash
$ npm test
PASSREFACTOR状态
如果需要,提取多字段验证逻辑。
Verification Checklist
验证检查清单
Before marking work complete:
- Every new function/method has a test
- Watched each test fail before implementing
- Each test failed for expected reason (feature missing, not typo)
- Wrote minimal code to pass each test
- All tests pass
- Output pristine (no errors, warnings)
- Tests use real code (mocks only if unavoidable)
- Edge cases and errors covered
Can't check all boxes? You skipped TDD. Start over.
在标记工作完成前:
- 每个新函数/方法都有对应的测试
- 每个测试在实现前都看到了失败
- 每个测试的失败原因符合预期(功能缺失,而非拼写错误)
- 编写了最少的代码让每个测试通过
- 所有测试都通过
- 输出干净(无错误、无警告)
- 测试使用真实代码(除非万不得已,否则不用模拟对象)
- 覆盖了边缘情况和错误场景
如果无法勾选所有选项?说明你跳过了TDD步骤,重新开始。
When Stuck
遇到困难时的解决方法
| Problem | Solution |
|---|---|
| Don't know how to test | Write wished-for API. Write assertion first. Ask your human partner. |
| Test too complicated | Design too complicated. Simplify interface. |
| Must mock everything | Code too coupled. Use dependency injection. |
| Test setup huge | Extract helpers. Still complex? Simplify design. |
| 问题 | 解决方案 |
|---|---|
| 不知道如何测试 | 写出你期望的API,先写断言,咨询团队成员。 |
| 测试太复杂 | 设计太复杂,简化接口。 |
| 必须到处用模拟对象 | 代码耦合度太高,使用依赖注入。 |
| 测试设置太繁琐 | 提取辅助函数。如果还是复杂?简化设计。 |
Debugging Integration
调试集成
Bug found? Write failing test reproducing it. Follow TDD cycle. Test proves fix and prevents regression.
Never fix bugs without a test.
发现Bug?先编写能复现Bug的失败测试,遵循TDD循环。测试既能证明Bug已修复,又能防止回归。
永远不要在没有测试的情况下修复Bug。
Final Rule
最终规则
Production code → test exists and failed first
Otherwise → not TDDNo exceptions without your human partner's permission.
Production code → test exists and failed first
Otherwise → not TDD除非获得团队成员的许可,否则没有例外。
CCMP Plugin Integration
CCMP插件集成
TDD workflow automatically integrates with other CCMP plugins via :
.ccmp/state.jsonTDD工作流自动与其他CCMP插件集成,通过文件实现:
.ccmp/state.jsonIntegration Detection (Modern API)
集成检测(现代API)
python
from lib.ccmp_integration import is_session_active, is_tdd_mode
if is_session_active():
# Enhanced TDD mode with session integration
passLegacy detection (still supported):
- directory exists
.git/sessions/<branch>/ - Session config has TDD objective or flag
--tdd - commands available
session.py
python
from lib.ccmp_integration import is_session_active, is_tdd_mode
if is_session_active():
# 带会话集成的增强型TDD模式
pass旧版检测方式(仍支持):
- 目录存在
.git/sessions/<branch>/ - 会话配置包含TDD目标或标志
--tdd - 可使用命令
session.py
With session-management 🔄
与session-management 🔄集成
Automatic activation:
bash
python scripts/session.py start feature/auth --tdd自动激活:
bash
python scripts/session.py start feature/auth --tdd→ TDD workflow detects via integration API
→ TDD工作流通过集成API检测到
→ Enhanced mode activates automatically
→ 自动激活增强模式
**TDD metrics in sessions:**
- Cycles completed tracked in session state
- Session status shows TDD discipline score
- Handoffs include test coverage metrics
**会话中的TDD指标:**
- 会话状态中跟踪已完成的循环数
- 会话状态显示TDD准则遵守得分
- 交接文档包含测试覆盖率指标With claude-context-manager 📚
与claude-context-manager 📚集成
Test context updates:
When TDD GREEN checkpoints succeed:
- Can trigger updates
tests/*/claude.md - Documents discovered test patterns
- Keeps test strategy current
Integration example:
python
from lib.ccmp_integration import CCMPIntegration
integration = CCMPIntegration()
integration.update_state("tdd-workflow", {
"active": True,
"cycles_today": 5,
"current_phase": "GREEN",
"discipline_score": 100
})If detected: Enhanced TDD mode with automatic checkpoints and metrics.
If not detected: Standard TDD guidance works perfectly standalone.
测试上下文更新:
当TDD GREEN状态检查点成功时:
- 可触发文件更新
tests/*/claude.md - 记录发现的测试模式
- 保持测试策略最新
集成示例:
python
from lib.ccmp_integration import CCMPIntegration
integration = CCMPIntegration()
integration.update_state("tdd-workflow", {
"active": True,
"cycles_today": 5,
"current_phase": "GREEN",
"discipline_score": 100
})如果检测到集成: 激活带自动检查点和指标统计的增强型TDD模式。
如果未检测到集成: 标准TDD指南可完美独立使用。
Integration Benefits
集成优势
With session-management:
- 📊 Track RED-GREEN-REFACTOR cycles in session metrics
- 📍 Automatic checkpoints at each TDD phase
- 📈 Test coverage trends across session
- 🎯 TDD discipline enforcement (harder to skip steps)
- 📝 Rich handoff documents with test statistics
- ⏱️ Cycle time tracking and optimization insights
Without session-management:
- ✅ Full TDD guidance and discipline
- ✅ All core principles and workflows
- ✅ Verification checklists
- ✅ Common rationalization detection
Best of both worlds: Works great alone, better together.
与session-management集成时:
- 📊 在会话指标中跟踪RED-GREEN-REFACTOR循环
- 📍 在每个TDD阶段自动创建检查点
- 📈 会话期间的测试覆盖率趋势
- 🎯 强制遵守TDD准则(更难跳过步骤)
- 📝 包含测试统计数据的丰富交接文档
- ⏱️ 循环时间跟踪和优化洞察
不与session-management集成时:
- ✅ 完整的TDD指南和准则
- ✅ 所有核心原则和工作流
- ✅ 验证检查清单
- ✅ 常见自我合理化借口检测
两全其美:单独使用效果出色,集成后功能更强。