mcpField
C
clean-tests

clean-tests

github.com/ertugrul-dmr测试与质量208114 次安装27 周前更新
代码仓库

关于 clean-tests

clean-tests 是一项面向开发者的测试实践技能,帮助编写可靠且易维护的测试。内容涵盖覆盖率、边界情况、测试组织、失败模式和测试速度。

主要功能

  1. 01测试边界情况
  2. 02用覆盖率工具发现遗漏
  3. 03保留简单测试并处理跳过项
  4. 04分析失败模式
  5. 05每个测试围绕一个概念
  6. 06保持测试快速且独立

适用场景

  1. 01检查测试套件是否遗漏边界情况
  2. 02利用覆盖率结果定位未测代码
  3. 03诊断反复出现的测试失败
  4. 04改善测试速度和组织方式

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/ertugrul-dmr/clean-code-skills --skill clean-tests

安装后在 Claude Code 中输入/clean-tests确认已加载。

详细介绍

简洁测试

T1:测试不足

测试所有可能出问题的内容。将覆盖率工具作为参考,而不是目标。

# Bad - only tests happy path
def test_divide():
    assert divide(10, 2) == 5

# Good - tests edge cases too
def test_divide_normal():
    assert divide(10, 2) == 5

def test_divide_by_zero():
    with pytest.raises(ZeroDivisionError):
        divide(10, 0)

def test_divide_negative():
    assert divide(-10, 2) == -5

T2:使用覆盖率工具

覆盖率工具会指出测试策略中的缺口。不要忽视它们。

# Run with coverage
pytest --cov=myproject --cov-report=term-missing

# Aim for meaningful coverage, not 100%

T3:不要跳过简单测试

简单测试能记录行为并捕获回归问题。它们的价值远超成本。

# Worth having - documents expected behavior
def test_user_default_role():
    user = User(name="Alice")
    assert user.role == "member"

T4:被忽略的测试说明存在歧义

不要用 @pytest.mark.skip 来掩盖问题。要么修复测试,要么删除测试。

# Bad - hiding a problem
@pytest.mark.skip(reason="flaky, fix later")
def test_async_operation():
    ...

# Good - either fix it or document why it's skipped
@pytest.mark.skip(reason="Requires Redis, see CONTRIBUTING.md for setup")
def test_cache_invalidation():
    ...

T5:测试边界条件

Bug 常出现在边界处。要明确测试这些情况。

def test_pagination_boundaries():
    items = list(range(100))
    
    # First page
    assert paginate(items, page=1, size=10) == items[0:10]
    
    # Last page
    assert paginate(items, page=10, size=10) == items[90:100]
    
    # Beyond last page
    assert paginate(items, page=11, size=10) == []
    
    # Page zero (invalid)
    with pytest.raises(ValueError):
        paginate(items, page=0, size=10)
    
    # Empty list
    assert paginate([], page=1, size=10) == []

T6:全面测试 Bug 附近的情况

发现一个 Bug 时,要为所有类似情况编写测试。Bug 往往成簇出现。

# Found bug: off-by-one in date calculation
# Now test ALL date boundaries
def test_month_boundaries():
    assert last_day_of_month(2024, 1) == 31  # January
    assert last_day_of_month(2024, 2) == 29  # Leap year February
    assert last_day_of_month(2023, 2) == 28  # Non-leap February
    assert last_day_of_month(2024, 4) == 30  # 30-day month
    assert last_day_of_month(2024, 12) == 31 # December

T7:失败模式能揭示问题

测试失败时,要观察其中的模式。它们往往指向更深层的问题。

# If all async tests fail intermittently,
# the problem isn't the tests—it's the async handling

T8:测试覆盖模式能揭示问题

查看哪些代码路径尚未测试。它们往往暴露设计问题。

# If you can't easily test a function, it probably does too much
# Refactor for testability

T9:测试应当快速

运行缓慢的测试不会被执行。将每个单元测试控制在 100 ms 以内。

# Bad - hits real database
def test_user_creation():
    db = connect_to_database()  # Slow!
    user = db.create_user("Alice")
    assert user.name == "Alice"

# Good - uses mock or in-memory
def test_user_creation():
    db = InMemoryDatabase()
    user = db.create_user("Alice")
    assert user.name == "Alice"

测试组织

F.I.R.S.T. 原则
  • 快速(Fast):测试应快速运行
  • 独立(Independent):测试不应相互依赖
  • 可重复(Repeatable):在任何环境中每次都得到相同结果
  • 自验证(Self-Validating):自动通过或失败,无需人工检查
  • 及时(Timely):在编写代码之前或同时编写,而不是事后编写
每个测试只验证一个概念
# Bad - testing multiple things
def test_user():
    user = User("Alice", "[email protected]")
    assert user.name == "Alice"
    assert user.email == "[email protected]"
    assert user.is_valid()
    user.activate()
    assert user.is_active

# Good - one concept each
def test_user_stores_name():
    user = User("Alice", "[email protected]")
    assert user.name == "Alice"

def test_user_stores_email():
    user = User("Alice", "[email protected]")
    assert user.email == "[email protected]"

def test_new_user_is_valid():
    user = User("Alice", "[email protected]")
    assert user.is_valid()

def test_user_can_be_activated():
    user = User("Alice", "[email protected]")
    user.activate()
    assert user.is_active

快速参考

规则原则
T1测试所有可能出问题的内容
T2使用覆盖率工具
T3不要跳过简单测试
T4忽略测试 = 存在歧义
T5测试边界条件
T6全面测试 Bug 附近的情况
T7查找失败模式
T8调试时检查覆盖率
T9测试必须快速(<100 ms)

评论

支持 Markdown