综合测试实施技能Skill testing

这个技能提供了全面的软件测试专业知识,涵盖单元测试、集成测试、端到端测试等多种测试类型,适用于数据管道、机器学习模型、基础设施等专业领域。它支持TDD/BDD工作流,帮助设计测试架构、调试不稳定测试和分析覆盖率,确保代码质量和可维护性。关键词:测试、单元测试、集成测试、端到端测试、TDD、BDD、测试覆盖率、调试、测试策略、模拟测试。

测试 0 次安装 0 次浏览 更新于 3/24/2026

name: 测试 description: 跨所有领域的综合测试实施,包括单元测试、集成测试、端到端测试、安全测试、基础设施测试、数据管道测试和机器学习模型测试。覆盖TDD/BDD工作流、测试架构、不稳定测试调试和覆盖率分析。 allowed-tools: 读取、搜索、全局、编辑、写入、Bash trigger-keywords: 测试、测试、规格、断言、期望、模拟、存根、间谍、夹具、快照、覆盖率、TDD、BDD、红绿、回归、单元测试、集成测试、端到端、测试套件、测试用例、pytest、jest、vitest、mocha、junit、testify、测试框架

测试

概述

此技能提供全面的测试专业知识,涵盖所有领域和测试类型。无论是编写单元测试、调试不稳定测试、设计测试架构,还是测试数据管道和机器学习模型等专业系统,此技能都指导测试实施,遵循行业最佳实践。

何时使用

  • 为任何代码库实施测试(单元测试、集成测试、端到端测试)
  • 调试不稳定或失败的测试
  • 提高测试覆盖率
  • 设置测试基础设施和框架
  • 遵循TDD/BDD工作流
  • 测试专业领域(数据、机器学习、基础设施、安全)
  • 设计测试架构和策略

核心指令

1. 分析要测试的代码

  • 识别公共接口和API
  • 映射依赖关系和副作用
  • 找到边缘情况和边界条件
  • 理解预期行为和不变性
  • 审查错误处理路径
  • 记录假设和前提条件

2. 设计测试策略

测试金字塔方法:

  • 单元测试(70%):快速、隔离,测试单个单元
  • 集成测试(20%):测试组件交互
  • 端到端测试(10%):测试完整用户工作流

规划:

  • 为每个组件确定适当的测试类型
  • 设置覆盖率目标(目标80%+行覆盖率,100%关键路径)
  • 识别模拟需求和边界
  • 规划测试夹具和数据管理
  • 考虑性能和稳定性风险

3. 遵循AAA模式编写测试

安排-行动-断言(Arrange-Act-Assert):

  • 安排:设置测试数据、模拟和条件
  • 行动:执行被测试代码
  • 断言:验证预期结果,并提供清晰的失败消息

命名约定:

test_<单元>_<场景>_<预期结果>

示例:test_shopping_cart_add_duplicate_item_increases_quantity

4. 处理特殊情况

异步操作:

  • 使用适当的异步测试工具(async/await、done回调)
  • 设置适当的超时
  • 测试竞争条件和时序问题

错误条件:

  • 显式测试所有错误路径
  • 验证错误消息和类型
  • 测试恢复机制

外部依赖:

  • 模拟HTTP客户端、数据库、文件系统
  • 使用测试替身(模拟、存根、伪造)
  • 考虑API的契约测试

数据库测试:

  • 使用事务和回滚进行隔离
  • 使用内存数据库以提高速度
  • 一致地播种测试数据

领域特定测试

数据管道测试

数据质量测试:

  • 模式验证(列类型、可空性、约束)
  • 数据完整性(行计数、空检查)
  • 数据准确性(统计检查、业务规则验证)
  • 数据新鲜度(时间戳检查)

管道测试:

  • 幂等性:运行两次产生相同结果
  • 增量处理:仅处理新数据
  • 故障恢复:优雅处理部分故障
  • 性能:处理时间在SLA内

示例:

def test_etl_pipeline_preserves_row_count():
    # 安排
    input_data = load_fixture("sales_data_1000_rows.csv")

    # 行动
    result = etl_pipeline.transform(input_data)

    # 断言
    assert len(result) == 1000, "ETL不应丢弃行"
    assert result['customer_id'].notna().all(), "customer_id必填"

ML模型测试

模型行为测试:

  • 不变性测试:预测在不相关变化下保持稳定
  • 方向性期望:特征变化正确影响预测
  • 最小功能:模型在关键示例上优于基线

数据测试:

  • 训练/验证分割完整性
  • 特征分布对齐
  • 标签平衡和质量

性能测试:

  • 测试集上的准确率/精确率/召回率
  • 推断延迟要求
  • 资源使用(内存、CPU)

示例:

def test_sentiment_model_invariance_to_punctuation():
    model = load_model("sentiment_classifier")

    text_base = "This product is amazing"
    text_with_punct = "This product is amazing!!!"

    pred_base = model.predict(text_base)
    pred_punct = model.predict(text_with_punct)

    assert abs(pred_base - pred_punct) < 0.1, \
        "标点不应显著改变情感"

基础设施测试

基础设施即代码测试:

  • 语法验证(terraform validate、yaml lint)
  • 策略合规性(安全组、IAM策略)
  • 资源标记和命名约定
  • 成本估算阈值

集成测试:

  • 部署冒烟测试
  • 健康检查端点
  • 服务连通性
  • 配置验证

示例:

def test_terraform_no_public_s3_buckets():
    tf_plan = load_terraform_plan("main.tfplan.json")

    for resource in tf_plan.get_resources("aws_s3_bucket"):
        acl = resource.get("acl", "private")
        assert acl != "public-read", \
            f"S3桶 {resource['name']} 必须不是公共的"

最佳实践

测试质量

  1. 测试一件事:每个测试验证单个行为或条件
  2. 描述性名称:测试名称描述场景和预期结果
  3. 独立测试:测试间无共享状态,可任意顺序执行
  4. 快速执行:单元测试 < 100ms,集成测试 < 5s
  5. 确定性:相同输入总是产生相同结果(无随机数据)
  6. 避免测试逻辑:测试应是简单断言,不是算法
  7. 测试边缘情况:边界条件、空输入、最大值、null
  8. 可读断言:使用清晰的断言消息以便调试

测试覆盖率

  • 目标80%+行覆盖率,关键路径100%
  • 关注行为覆盖率,而不仅是行覆盖率
  • 使用覆盖率工具查找未测试代码
  • 优先测试业务逻辑和错误路径

调试不稳定测试

常见原因:

  • 竞争条件和时序依赖
  • 测试间共享可变状态
  • 外部服务依赖
  • 非确定性输入(时间戳、随机值)
  • 测试执行顺序依赖

解决方案:

  • 添加显式等待而不是sleep
  • 在设置/清理中重置状态
  • 模拟外部依赖
  • 使用固定种子进行随机生成
  • 隔离运行测试以识别顺序依赖

TDD工作流

红绿重构循环:

  1. :为期望行为编写失败测试
  2. 绿:编写最小代码使测试通过
  3. 重构:改进代码,同时保持测试通过

好处:

  • 强制在实施前思考设计
  • 确保测试实际捕捉失败
  • 提供快速反馈循环
  • 创建全面的测试套件

框架特定模式

Python (pytest)

import pytest
from unittest.mock import Mock, patch

@pytest.fixture
def database():
    db = Database()
    db.connect()
    yield db
    db.disconnect()

@pytest.mark.parametrize("input,expected", [
    (0, 0),
    (1, 1),
    (5, 120),
])
def test_factorial(input, expected):
    assert factorial(input) == expected

@patch('requests.get')
def test_api_client(mock_get):
    mock_get.return_value.json.return_value = {"status": "ok"}
    result = fetch_status()
    assert result == "ok"

JavaScript (Vitest/Jest)

import { describe, it, expect, vi, beforeEach } from "vitest";

describe("UserService", () => {
  let mockDb;

  beforeEach(() => {
    mockDb = {
      query: vi.fn(),
    };
  });

  it("finds user by email", async () => {
    mockDb.query.mockResolvedValue([{ id: 1, email: "test@example.com" }]);

    const service = new UserService(mockDb);
    const user = await service.findByEmail("test@example.com");

    expect(user.id).toBe(1);
    expect(mockDb.query).toHaveBeenCalledWith(
      "SELECT * FROM users WHERE email = ?",
      ["test@example.com"],
    );
  });
});

Rust (built-in + mockall)

#[cfg(test)]
mod tests {
    use super::*;
    use mockall::predicate::*;
    use mockall::mock;

    mock! {
        Database {}
        impl DatabaseTrait for Database {
            fn get_user(&self, id: i64) -> Result<User, Error>;
        }
    }

    #[test]
    fn test_user_service_fetches_from_db() {
        let mut mock_db = MockDatabase::new();
        mock_db
            .expect_get_user()
            .with(eq(1))
            .return_once(|_| Ok(User { id: 1, name: "Alice".into() }));

        let service = UserService::new(mock_db);
        let user = service.get_user(1).unwrap();

        assert_eq!(user.name, "Alice");
    }
}

应避免的反模式

  1. 测试依赖性:测试必须按特定顺序运行
  2. 测试实现:测试私有方法或内部状态
  3. 过度模拟:模拟一切使测试脆弱
  4. 断言轮盘:一个测试中有多个不相关的断言
  5. 隐藏依赖:测试依赖外部文件或服务
  6. 慢测试:由于真实I/O导致测试需要几秒钟运行
  7. 脆弱测试:轻微重构就会破坏的测试
  8. 重复逻辑:将生产代码复制到测试中

测试架构

测试组织

tests/
├── unit/              # 快速、隔离的单元测试
│   ├── models/
│   ├── services/
│   └── utils/
├── integration/       # 组件交互测试
│   ├── api/
│   ├── database/
│   └── external_services/
├── e2e/              # 完整工作流测试
│   └── user_scenarios/
├── fixtures/         # 共享测试数据
└── helpers/          # 测试工具

持续集成

  • 每次提交运行单元测试
  • PR上运行集成测试
  • 部署前运行端到端测试
  • 覆盖率下降时构建失败
  • 并行化测试执行
  • 报告不稳定测试以供调查

示例

示例1:带模拟的单元测试

from unittest.mock import Mock, patch
import pytest
from payment_processor import PaymentProcessor

class TestPaymentProcessor:
    @patch('payment_processor.stripe')
    def test_successful_payment_creates_charge(self, mock_stripe):
        # 安排
        mock_stripe.Charge.create.return_value = Mock(
            id='ch_123',
            status='succeeded'
        )
        processor = PaymentProcessor(api_key='test_key')

        # 行动
        result = processor.charge(amount=1000, token='tok_visa')

        # 断言
        assert result.success is True
        assert result.charge_id == 'ch_123'
        mock_stripe.Charge.create.assert_called_once_with(
            amount=1000,
            currency='usd',
            source='tok_visa'
        )

    @patch('payment_processor.stripe')
    def test_declined_payment_raises_payment_error(self, mock_stripe):
        # 安排
        mock_stripe.Charge.create.side_effect = Exception("Card declined")
        processor = PaymentProcessor(api_key='test_key')

        # 行动 & 断言
        with pytest.raises(PaymentError) as exc_info:
            processor.charge(amount=1000, token='tok_declined')

        assert "Card declined" in str(exc_info.value)

示例2:带数据库的集成测试

import { describe, it, expect, beforeEach, afterEach } from "vitest";
import { createServer } from "../server";
import { db } from "../database";

describe("User API Integration", () => {
  let server;

  beforeEach(async () => {
    server = await createServer();
    await db.migrate.latest();
    await db.seed.run();
  });

  afterEach(async () => {
    await db.migrate.rollback();
    await server.close();
  });

  it("creates user and returns 201 with user data", async () => {
    const response = await server.inject({
      method: "POST",
      url: "/api/users",
      payload: {
        email: "new@example.com",
        name: "New User",
      },
    });

    expect(response.statusCode).toBe(201);
    expect(response.json()).toMatchObject({
      email: "new@example.com",
      name: "New User",
    });

    // 验证数据库状态
    const user = await db("users").where({ email: "new@example.com" }).first();
    expect(user).toBeDefined();
  });

  it("returns 400 for invalid email format", async () => {
    const response = await server.inject({
      method: "POST",
      url: "/api/users",
      payload: {
        email: "invalid-email",
        name: "Test User",
      },
    });

    expect(response.statusCode).toBe(400);
    expect(response.json().error).toContain("email");
  });
});

示例3:快照测试

import { render } from "@testing-library/react";
import { UserCard } from "./UserCard";

it("renders user card correctly", () => {
  const user = {
    id: 1,
    name: "Alice",
    email: "alice@example.com",
    avatar: "/avatars/alice.jpg",
  };

  const { container } = render(<UserCard user={user} />);

  // UI组件的快照测试
  expect(container.firstChild).toMatchSnapshot();
});

总结

此技能提供全面的测试专业知识,涵盖:

  • 所有测试类型(单元测试、集成测试、端到端测试)
  • 所有领域(后端、前端、数据、机器学习、基础设施)
  • 测试架构和策略
  • 调试和维护
  • TDD/BDD工作流

目标是生产质量的测试,以捕捉错误、记录行为并支持自信的重构。