testing

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Testing Standards Skill

测试标准技能

Level 1: Quick Start (5 minutes)

一级:快速入门(5分钟)

What You'll Learn

你将学到

Implement effective testing strategies to ensure code quality, catch bugs early, and maintain confidence in changes.
实施有效的测试策略,确保代码质量,尽早发现bug,并对代码变更保持信心。

Core Principles

核心原则

  • Test First: Write tests before implementation (TDD)
  • Coverage: Aim for >80% code coverage
  • Isolation: Tests should be independent and repeatable
  • Speed: Keep unit tests fast (<100ms each)
  • 测试先行:在实现代码前编写测试(TDD)
  • 代码覆盖率:目标达到80%以上的代码覆盖率
  • 独立性:测试应独立且可重复执行
  • 速度:保持单元测试执行快速(每个测试<100毫秒)

Testing Pyramid

测试金字塔

      /\
     /  \  E2E Tests (Few)
    /----\
   / Inte \
  / gration \ (Some)
 /  Tests   \
/------------\
/ Unit Tests  \ (Many)
/--------------\
      /\
     /  \  E2E 测试(少量)
    /----\
   / 集 成 \
  / 测 试  \(适量)
 /        \
/------------\
/ 单元测试    \(大量)
/--------------\

Quick Start Example

快速入门示例

typescript
// 1. Write the test first (RED)
describe("calculateDiscount", () => {
  it("should apply 10% discount for premium users", () => {
    const user = { tier: "premium" };
    const order = { total: 100 };

    const result = calculateDiscount(user, order);

    expect(result).toBe(90);
  });
});

// 2. Implement minimal code (GREEN)
function calculateDiscount(user, order) {
  if (user.tier === "premium") {
    return order.total * 0.9;
  }
  return order.total;
}

// 3. Refactor (REFACTOR)
function calculateDiscount(
  user: User,
  order: Order
): number {
  const PREMIUM_DISCOUNT = 0.1;
  return user.tier === "premium"
    ? order.total * (1 - PREMIUM_DISCOUNT)
    : order.total;
}
typescript
// 1. 先编写测试(红阶段)
describe("calculateDiscount", () => {
  it("should apply 10% discount for premium users", () => {
    const user = { tier: "premium" };
    const order = { total: 100 };

    const result = calculateDiscount(user, order);

    expect(result).toBe(90);
  });
});

// 2. 实现最简代码(绿阶段)
function calculateDiscount(user, order) {
  if (user.tier === "premium") {
    return order.total * 0.9;
  }
  return order.total;
}

// 3. 重构代码(重构阶段)
function calculateDiscount(
  user: User,
  order: Order
): number {
  const PREMIUM_DISCOUNT = 0.1;
  return user.tier === "premium"
    ? order.total * (1 - PREMIUM_DISCOUNT)
    : order.total;
}

Essential Checklist

必备检查清单

  • Unit tests for all business logic
  • Integration tests for critical paths
  • Tests run in CI/CD pipeline
  • Coverage >80%
  • Tests are maintainable and readable
  • 为所有业务逻辑编写单元测试
  • 为关键路径编写集成测试
  • 在CI/CD流水线中运行测试
  • 代码覆盖率>80%
  • 测试具备可维护性和可读性

Common Pitfalls

常见误区

  • Testing implementation details instead of behavior
  • Slow tests that discourage running them
  • Flaky tests that fail intermittently
  • Poor test isolation (shared state)

  • 测试实现细节而非业务行为
  • 测试执行缓慢,导致开发者不愿运行
  • 不稳定的测试,间歇性失败
  • 测试独立性差(共享状态)

Level 2: Implementation (30 minutes)

二级:实践落地(30分钟)

Deep Dive Topics

深入主题

1. Test-Driven Development (TDD)

1. 测试驱动开发(TDD)

Red-Green-Refactor Cycle:
typescript
// STEP 1: RED - Write failing test
describe("UserService", () => {
  describe("createUser", () => {
    it("should hash password before saving", async () => {
      const userData = {
        email: "test@example.com",
        password: "SecurePass123!",
      };

      const service = new UserService(mockRepository, mockHasher);
      await service.createUser(userData);

      expect(mockHasher.hash).toHaveBeenCalledWith("SecurePass123!");
      expect(mockRepository.save).toHaveBeenCalledWith(
        expect.objectContaining({
          email: "test@example.com",
          passwordHash: expect.any(String),
        })
      );
    });
  });
});

// STEP 2: GREEN - Minimal implementation
class UserService {
  constructor(
    private repository: UserRepository,
    private hasher: PasswordHasher
  ) {}

  async createUser(userData: UserData): Promise<User> {
    const passwordHash = await this.hasher.hash(userData.password);
    return this.repository.save({
      ...userData,
      passwordHash,
    });
  }
}

// STEP 3: REFACTOR - Improve design
class UserService {
  constructor(
    private repository: UserRepository,
    private hasher: PasswordHasher,
    private validator: UserValidator
  ) {}

  async createUser(userData: UserData): Promise<User> {
    await this.validator.validate(userData);
    const passwordHash = await this.hasher.hash(userData.password);

    const user = new User({
      email: userData.email,
      passwordHash,
      createdAt: new Date(),
    });

    return this.repository.save(user);
  }
}
NIST Mapping:
  • @nist-controls: [si-10, si-11, au-2, au-3]
红-绿-重构循环:
typescript
// 步骤1:红阶段 - 编写失败的测试
describe("UserService", () => {
  describe("createUser", () => {
    it("should hash password before saving", async () => {
      const userData = {
        email: "test@example.com",
        password: "SecurePass123!",
      };

      const service = new UserService(mockRepository, mockHasher);
      await service.createUser(userData);

      expect(mockHasher.hash).toHaveBeenCalledWith("SecurePass123!");
      expect(mockRepository.save).toHaveBeenCalledWith(
        expect.objectContaining({
          email: "test@example.com",
          passwordHash: expect.any(String),
        })
      );
    });
  });
});

// 步骤2:绿阶段 - 最简实现
class UserService {
  constructor(
    private repository: UserRepository,
    private hasher: PasswordHasher
  ) {}

  async createUser(userData: UserData): Promise<User> {
    const passwordHash = await this.hasher.hash(userData.password);
    return this.repository.save({
      ...userData,
      passwordHash,
    });
  }
}

// 步骤3:重构阶段 - 优化设计
class UserService {
  constructor(
    private repository: UserRepository,
    private hasher: PasswordHasher,
    private validator: UserValidator
  ) {}

  async createUser(userData: UserData): Promise<User> {
    await this.validator.validate(userData);
    const passwordHash = await this.hasher.hash(userData.password);

    const user = new User({
      email: userData.email,
      passwordHash,
      createdAt: new Date(),
    });

    return this.repository.save(user);
  }
}
NIST 映射:
  • @nist-controls: [si-10, si-11, au-2, au-3]

2. Property-Based Testing

2. 基于属性的测试

typescript
import { fc } from "fast-check";

// Traditional example-based test
it("should reverse a reversed string back to original", () => {
  expect(reverse(reverse("hello"))).toBe("hello");
  expect(reverse(reverse("world"))).toBe("world");
  // Limited to specific examples
});

// Property-based test - tests thousands of cases
it("reversing twice should return original string", () => {
  fc.assert(
    fc.property(fc.string(), (str) => {
      expect(reverse(reverse(str))).toBe(str);
    })
  );
});

// Complex property testing
describe("calculateTotal", () => {
  it("should always return non-negative totals", () => {
    fc.assert(
      fc.property(
        fc.array(fc.record({ price: fc.nat(), quantity: fc.nat() })),
        (items) => {
          const total = calculateTotal(items);
          expect(total).toBeGreaterThanOrEqual(0);
        }
      )
    );
  });

  it("should be commutative (order doesn't matter)", () => {
    fc.assert(
      fc.property(fc.array(fc.record({ price: fc.nat(), quantity: fc.nat() })), (items) => {
        const total1 = calculateTotal(items);
        const total2 = calculateTotal([...items].reverse());
        expect(total1).toBe(total2);
      })
    );
  });
});
typescript
import { fc } from "fast-check";

// 传统的基于示例的测试
it("should reverse a reversed string back to original", () => {
  expect(reverse(reverse("hello"))).toBe("hello");
  expect(reverse(reverse("world"))).toBe("world");
  // 仅覆盖特定示例
});

// 基于属性的测试 - 测试数千种情况
it("reversing twice should return original string", () => {
  fc.assert(
    fc.property(fc.string(), (str) => {
      expect(reverse(reverse(str))).toBe(str);
    })
  );
});

// 复杂的属性测试
describe("calculateTotal", () => {
  it("should always return non-negative totals", () => {
    fc.assert(
      fc.property(
        fc.array(fc.record({ price: fc.nat(), quantity: fc.nat() })),
        (items) => {
          const total = calculateTotal(items);
          expect(total).toBeGreaterThanOrEqual(0);
        }
      )
    );
  });

  it("should be commutative (order doesn't matter)", () => {
    fc.assert(
      fc.property(fc.array(fc.record({ price: fc.nat(), quantity: fc.nat() })), (items) => {
        const total1 = calculateTotal(items);
        const total2 = calculateTotal([...items].reverse());
        expect(total1).toBe(total2);
      })
    );
  });
});

3. Integration Testing

3. 集成测试

typescript
// API Integration Test
describe("POST /api/users", () => {
  let app: Express;
  let db: Database;

  beforeAll(async () => {
    // Setup test database
    db = await createTestDatabase();
    app = createApp({ database: db });
  });

  afterAll(async () => {
    await db.close();
  });

  beforeEach(async () => {
    // Clean state between tests
    await db.truncate("users");
  });

  it("should create a new user", async () => {
    const response = await request(app)
      .post("/api/users")
      .send({
        email: "test@example.com",
        password: "SecurePass123!",
        name: "Test User",
      })
      .expect(201);

    expect(response.body).toMatchObject({
      id: expect.any(String),
      email: "test@example.com",
      name: "Test User",
    });

    // Verify in database
    const user = await db.query("SELECT * FROM users WHERE email = ?", [
      "test@example.com",
    ]);
    expect(user).toBeDefined();
    expect(user.passwordHash).not.toBe("SecurePass123!"); // Should be hashed
  });

  it("should reject duplicate emails", async () => {
    // Create first user
    await request(app).post("/api/users").send({
      email: "test@example.com",
      password: "SecurePass123!",
    });

    // Attempt duplicate
    await request(app)
      .post("/api/users")
      .send({
        email: "test@example.com",
        password: "AnotherPass456!",
      })
      .expect(409);
  });
});
typescript
// API 集成测试
describe("POST /api/users", () => {
  let app: Express;
  let db: Database;

  beforeAll(async () => {
    // 搭建测试数据库
    db = await createTestDatabase();
    app = createApp({ database: db });
  });

  afterAll(async () => {
    await db.close();
  });

  beforeEach(async () => {
    // 测试间清理状态
    await db.truncate("users");
  });

  it("should create a new user", async () => {
    const response = await request(app)
      .post("/api/users")
      .send({
        email: "test@example.com",
        password: "SecurePass123!",
        name: "测试用户",
      })
      .expect(201);

    expect(response.body).toMatchObject({
      id: expect.any(String),
      email: "test@example.com",
      name: "测试用户",
    });

    // 在数据库中验证
    const user = await db.query("SELECT * FROM users WHERE email = ?", [
      "test@example.com",
    ]);
    expect(user).toBeDefined();
    expect(user.passwordHash).not.toBe("SecurePass123!"); // 应为哈希值
  });

  it("should reject duplicate emails", async () => {
    // 创建第一个用户
    await request(app).post("/api/users").send({
      email: "test@example.com",
      password: "SecurePass123!",
    });

    // 尝试创建重复用户
    await request(app)
      .post("/api/users")
      .send({
        email: "test@example.com",
        password: "AnotherPass456!",
      })
      .expect(409);
  });
});

4. Security Testing

4. 安全测试

typescript
// Input validation tests
describe("Security: Input Validation", () => {
  it("should reject SQL injection attempts", async () => {
    const maliciousInput = "'; DROP TABLE users; --";

    await request(app)
      .get(`/api/users/search?name=${maliciousInput}`)
      .expect(400);
  });

  it("should sanitize XSS attempts", async () => {
    const xssPayload = '<script>alert("XSS")</script>';

    const response = await request(app)
      .post("/api/comments")
      .send({ content: xssPayload })
      .expect(201);

    expect(response.body.content).not.toContain("<script>");
  });

  it("should enforce rate limiting", async () => {
    const requests = Array(101)
      .fill(null)
      .map(() => request(app).get("/api/data"));

    const responses = await Promise.all(requests);
    const rateLimited = responses.filter((r) => r.status === 429);

    expect(rateLimited.length).toBeGreaterThan(0);
  });
});

// Authentication tests
describe("Security: Authentication", () => {
  it("should require authentication for protected routes", async () => {
    await request(app).get("/api/protected").expect(401);
  });

  it("should reject expired tokens", async () => {
    const expiredToken = generateExpiredToken();

    await request(app)
      .get("/api/protected")
      .set("Authorization", `Bearer ${expiredToken}`)
      .expect(401);
  });
});
typescript
// 输入验证测试
describe("Security: Input Validation", () => {
  it("should reject SQL injection attempts", async () => {
    const maliciousInput = "'; DROP TABLE users; --";

    await request(app)
      .get(`/api/users/search?name=${maliciousInput}`)
      .expect(400);
  });

  it("should sanitize XSS attempts", async () => {
    const xssPayload = '<script>alert("XSS")</script>';

    const response = await request(app)
      .post("/api/comments")
      .send({ content: xssPayload })
      .expect(201);

    expect(response.body.content).not.toContain("<script>");
  });

  it("should enforce rate limiting", async () => {
    const requests = Array(101)
      .fill(null)
      .map(() => request(app).get("/api/data"));

    const responses = await Promise.all(requests);
    const rateLimited = responses.filter((r) => r.status === 429);

    expect(rateLimited.length).toBeGreaterThan(0);
  });
});

// 身份验证测试
describe("Security: Authentication", () => {
  it("should require authentication for protected routes", async () => {
    await request(app).get("/api/protected").expect(401);
  });

  it("should reject expired tokens", async () => {
    const expiredToken = generateExpiredToken();

    await request(app)
      .get("/api/protected")
      .set("Authorization", `Bearer ${expiredToken}`)
      .expect(401);
  });
});

5. Performance Testing

5. 性能测试

typescript
// Benchmark testing
describe("Performance: calculateComplexMetric", () => {
  it("should complete within 100ms for 1000 items", async () => {
    const items = generateTestData(1000);

    const start = performance.now();
    await calculateComplexMetric(items);
    const duration = performance.now() - start;

    expect(duration).toBeLessThan(100);
  });

  it("should scale linearly with input size", async () => {
    const sizes = [100, 200, 400, 800];
    const timings: number[] = [];

    for (const size of sizes) {
      const items = generateTestData(size);
      const start = performance.now();
      await calculateComplexMetric(items);
      timings.push(performance.now() - start);
    }

    // Check that doubling input approximately doubles time
    expect(timings[1] / timings[0]).toBeCloseTo(2, 0.5);
    expect(timings[2] / timings[1]).toBeCloseTo(2, 0.5);
  });
});

// Load testing with autocannon
import autocannon from "autocannon";

describe("Load Testing", () => {
  it("should handle 1000 req/s with <200ms p95 latency", async () => {
    const result = await autocannon({
      url: "http://localhost:3000/api/health",
      connections: 100,
      duration: 10,
      pipelining: 10,
    });

    expect(result.requests.average).toBeGreaterThan(1000);
    expect(result.latency.p95).toBeLessThan(200);
  });
});
typescript
// 基准测试
describe("Performance: calculateComplexMetric", () => {
  it("should complete within 100ms for 1000 items", async () => {
    const items = generateTestData(1000);

    const start = performance.now();
    await calculateComplexMetric(items);
    const duration = performance.now() - start;

    expect(duration).toBeLessThan(100);
  });

  it("should scale linearly with input size", async () => {
    const sizes = [100, 200, 400, 800];
    const timings: number[] = [];

    for (const size of sizes) {
      const items = generateTestData(size);
      const start = performance.now();
      await calculateComplexMetric(items);
      timings.push(performance.now() - start);
    }

    // 验证输入量翻倍时,耗时大致翻倍
    expect(timings[1] / timings[0]).toBeCloseTo(2, 0.5);
    expect(timings[2] / timings[1]).toBeCloseTo(2, 0.5);
  });
});

// 使用autocannon进行负载测试
import autocannon from "autocannon";

describe("Load Testing", () => {
  it("should handle 1000 req/s with <200ms p95 latency", async () => {
    const result = await autocannon({
      url: "http://localhost:3000/api/health",
      connections: 100,
      duration: 10,
      pipelining: 10,
    });

    expect(result.requests.average).toBeGreaterThan(1000);
    expect(result.latency.p95).toBeLessThan(200);
  });
});

6. Mutation Testing

6. 突变测试

typescript
// Original code
function isAdult(age: number): boolean {
  return age >= 18;
}

// Mutation 1: Change >= to >
// function isAdult(age: number): boolean {
//   return age > 18;
// }

// This test would catch mutation 1
it("should consider 18 as adult", () => {
  expect(isAdult(18)).toBe(true);
});

// Mutation 2: Change 18 to 17
// function isAdult(age: number): boolean {
//   return age >= 17;
// }

// This test would catch mutation 2
it("should not consider 17 as adult", () => {
  expect(isAdult(17)).toBe(false);
});

// Run mutation testing
// npm install --save-dev stryker
// npx stryker run
typescript
// 原始代码
function isAdult(age: number): boolean {
  return age >= 18;
}

// 突变1:将>=改为>
// function isAdult(age: number): boolean {
//   return age > 18;
// }

// 该测试可以捕获突变1
it("should consider 18 as adult", () => {
  expect(isAdult(18)).toBe(true);
});

// 突变2:将18改为17
// function isAdult(age: number): boolean {
//   return age >= 17;
// }

// 该测试可以捕获突变2
it("should not consider 17 as adult", () => {
  expect(isAdult(17)).toBe(false);
});

// 运行突变测试
// npm install --save-dev stryker
// npx stryker run

Test Organization

测试组织方式

typescript
// Arrange-Act-Assert (AAA) Pattern
describe("OrderService", () => {
  describe("calculateTotal", () => {
    it("should apply discount to eligible orders", () => {
      // ARRANGE - Setup test data
      const order = {
        items: [
          { price: 100, quantity: 2 },
          { price: 50, quantity: 1 },
        ],
        discountCode: "SAVE10",
      };
      const service = new OrderService();

      // ACT - Execute the behavior
      const total = service.calculateTotal(order);

      // ASSERT - Verify the outcome
      expect(total).toBe(225); // (200 + 50) * 0.9
    });
  });
});
typescript
// 安排-执行-断言(AAA)模式
describe("OrderService", () => {
  describe("calculateTotal", () => {
    it("should apply discount to eligible orders", () => {
      // 安排 - 准备测试数据
      const order = {
        items: [
          { price: 100, quantity: 2 },
          { price: 50, quantity: 1 },
        ],
        discountCode: "SAVE10",
      };
      const service = new OrderService();

      // 执行 - 触发业务行为
      const total = service.calculateTotal(order);

      // 断言 - 验证结果
      expect(total).toBe(225); // (200 + 50) * 0.9
    });
  });
});

Integration Points

集成关联

  • Links to Coding Standards for testable code design
  • Links to Security Practices for security testing
  • Links to NIST Compliance for SI-10, SI-11 controls

  • 链接到编码标准以实现可测试的代码设计
  • 链接到安全实践以开展安全测试
  • 链接到NIST合规性以参考SI-10、SI-11控制要求

Level 3: Mastery (Extended Learning)

三级:精通进阶(拓展学习)

Advanced Topics

高级主题

1. Contract Testing

1. 契约测试

typescript
// Provider contract (API server)
import { Pact } from "@pact-foundation/pact";

describe("User API Provider", () => {
  const provider = new Pact({
    consumer: "UserService",
    provider: "UserAPI",
  });

  beforeAll(() => provider.setup());
  afterAll(() => provider.finalize());

  it("should provide user by ID", async () => {
    await provider.addInteraction({
      state: "user 123 exists",
      uponReceiving: "a request for user 123",
      withRequest: {
        method: "GET",
        path: "/users/123",
      },
      willRespondWith: {
        status: 200,
        body: {
          id: "123",
          name: "John Doe",
          email: "john@example.com",
        },
      },
    });

    await provider.verify();
  });
});
typescript
// 提供者契约(API服务器)
import { Pact } from "@pact-foundation/pact";

describe("User API Provider", () => {
  const provider = new Pact({
    consumer: "UserService",
    provider: "UserAPI",
  });

  beforeAll(() => provider.setup());
  afterAll(() => provider.finalize());

  it("should provide user by ID", async () => {
    await provider.addInteraction({
      state: "user 123 exists",
      uponReceiving: "a request for user 123",
      withRequest: {
        method: "GET",
        path: "/users/123",
      },
      willRespondWith: {
        status: 200,
        body: {
          id: "123",
          name: "John Doe",
          email: "john@example.com",
        },
      },
    });

    await provider.verify();
  });
});

2. Chaos Engineering

2. 混沌工程

typescript
// Simulate failures to test resilience
class ChaosMonkey {
  private failureRate: number;

  constructor(failureRate: number = 0.1) {
    this.failureRate = failureRate;
  }

  async injectFailure<T>(operation: () => Promise<T>): Promise<T> {
    if (Math.random() < this.failureRate) {
      throw new Error("Simulated failure");
    }
    return operation();
  }
}

describe("Resilience Testing", () => {
  it("should retry failed operations", async () => {
    const chaos = new ChaosMonkey(0.5); // 50% failure rate
    let attempts = 0;

    const result = await retry(
      async () => {
        attempts++;
        return chaos.injectFailure(() => fetchData());
      },
      { maxAttempts: 3, delay: 100 }
    );

    expect(result).toBeDefined();
    expect(attempts).toBeGreaterThan(1);
  });
});
typescript
// 模拟故障以测试系统韧性
class ChaosMonkey {
  private failureRate: number;

  constructor(failureRate: number = 0.1) {
    this.failureRate = failureRate;
  }

  async injectFailure<T>(operation: () => Promise<T>): Promise<T> {
    if (Math.random() < this.failureRate) {
      throw new Error("Simulated failure");
    }
    return operation();
  }
}

describe("Resilience Testing", () => {
  it("should retry failed operations", async () => {
    const chaos = new ChaosMonkey(0.5); // 50%故障概率
    let attempts = 0;

    const result = await retry(
      async () => {
        attempts++;
        return chaos.injectFailure(() => fetchData());
      },
      { maxAttempts: 3, delay: 100 }
    );

    expect(result).toBeDefined();
    expect(attempts).toBeGreaterThan(1);
  });
});

3. Visual Regression Testing

3. 视觉回归测试

typescript
import { test, expect } from "@playwright/test";

test("homepage should match snapshot", async ({ page }) => {
  await page.goto("https://example.com");

  // Take screenshot and compare with baseline
  await expect(page).toHaveScreenshot("homepage.png", {
    maxDiffPixels: 100,
  });
});

test("button hover state", async ({ page }) => {
  await page.goto("https://example.com");
  await page.hover("button.primary");

  await expect(page.locator("button.primary")).toHaveScreenshot(
    "button-hover.png"
  );
});
typescript
import { test, expect } from "@playwright/test";

test("homepage should match snapshot", async ({ page }) => {
  await page.goto("https://example.com");

  // 截图并与基准图对比
  await expect(page).toHaveScreenshot("homepage.png", {
    maxDiffPixels: 100,
  });
});

test("button hover state", async ({ page }) => {
  await page.goto("https://example.com");
  await page.hover("button.primary");

  await expect(page.locator("button.primary")).toHaveScreenshot(
    "button-hover.png"
  );
});

Resources

参考资源

Essential Reading

必读资料

Testing Frameworks

测试框架

  • Unit Testing: Jest, Vitest, pytest, JUnit
  • Integration Testing: Supertest, TestContainers
  • E2E Testing: Playwright, Cypress, Selenium
  • Property Testing: fast-check, Hypothesis, QuickCheck
  • Mutation Testing: Stryker, PIT, mutmut
  • 单元测试:Jest、Vitest、pytest、JUnit
  • 集成测试:Supertest、TestContainers
  • 端到端测试:Playwright、Cypress、Selenium
  • 属性测试:fast-check、Hypothesis、QuickCheck
  • 突变测试:Stryker、PIT、mutmut

Tools and Services

工具与服务

  • CI/CD: GitHub Actions, GitLab CI, CircleCI
  • Coverage: Istanbul, Coverage.py, JaCoCo
  • Load Testing: k6, Artillery, Gatling
  • Contract Testing: Pact, Spring Cloud Contract
  • CI/CD:GitHub Actions、GitLab CI、CircleCI
  • 覆盖率工具:Istanbul、Coverage.py、JaCoCo
  • 负载测试:k6、Artillery、Gatling
  • 契约测试:Pact、Spring Cloud Contract

Templates

模板

Test Suite Template

测试套件模板

typescript
describe("FeatureName", () => {
  // Setup and teardown
  beforeAll(async () => {
    // One-time setup
  });

  afterAll(async () => {
    // One-time cleanup
  });

  beforeEach(() => {
    // Reset state before each test
  });

  afterEach(() => {
    // Cleanup after each test
  });

  // Happy path tests
  describe("when conditions are normal", () => {
    it("should perform expected behavior", () => {
      // Test implementation
    });
  });

  // Edge cases
  describe("when edge conditions occur", () => {
    it("should handle edge case gracefully", () => {
      // Test implementation
    });
  });

  // Error cases
  describe("when errors occur", () => {
    it("should handle errors appropriately", () => {
      // Test implementation
    });
  });
});
typescript
describe("FeatureName", () => {
  // 前置和后置操作
  beforeAll(async () => {
    // 一次性前置准备
  });

  afterAll(async () => {
    // 一次性清理
  });

  beforeEach(() => {
    // 每个测试前重置状态
  });

  afterEach(() => {
    // 每个测试后清理
  });

  // 正常流程测试
  describe("when conditions are normal", () => {
    it("should perform expected behavior", () => {
      // 测试实现
    });
  });

  // 边界情况测试
  describe("when edge conditions occur", () => {
    it("should handle edge case gracefully", () => {
      // 测试实现
    });
  });

  // 错误情况测试
  describe("when errors occur", () => {
    it("should handle errors appropriately", () => {
      // 测试实现
    });
  });
});

Scripts

脚本

See
./scripts/
for:
  • Test coverage reporters
  • Mutation testing runners
  • Performance benchmark tools
  • Test data generators
查看
./scripts/
目录获取:
  • 测试覆盖率报告工具
  • 突变测试运行器
  • 性能基准测试工具
  • 测试数据生成器

Examples

示例

Basic Usage

基础用法

python
// TODO: Add basic example for testing
// This example demonstrates core functionality
python
// TODO: 添加测试基础示例
// 该示例展示核心功能

Advanced Usage

高级用法

python
// TODO: Add advanced example for testing
// This example shows production-ready patterns
python
// TODO: 添加测试高级示例
// 该示例展示生产就绪模式

Integration Example

集成示例

python
// TODO: Add integration example showing how testing
// works with other systems and services
See
examples/testing/
for complete working examples.
python
// TODO: 添加集成示例,展示测试如何与其他系统和服务协作
查看
examples/testing/
目录获取完整可运行示例。

Integration Points

集成关联

This skill integrates with:
本技能可与以下内容集成:

Upstream Dependencies

上游依赖

  • Tools: Common development tools and frameworks
  • Prerequisites: Basic understanding of general concepts
  • 工具:常见开发工具与框架
  • 前置要求:对通用概念的基本理解

Downstream Consumers

下游应用

  • Applications: Production systems requiring testing functionality
  • CI/CD Pipelines: Automated testing and deployment workflows
  • Monitoring Systems: Observability and logging platforms
  • 应用系统:需要测试功能的生产系统
  • CI/CD流水线:自动化测试与部署工作流
  • 监控系统:可观测性与日志平台

Related Skills

相关技能

  • See other skills in this category
  • 查看本分类下的其他技能

Common Integration Patterns

常见集成模式

  1. Development Workflow: How this skill fits into daily development
  2. Production Deployment: Integration with production systems
  3. Monitoring & Alerting: Observability integration points
  1. 开发工作流:本技能如何融入日常开发
  2. 生产部署:与生产系统的集成方式
  3. 监控与告警:可观测性集成点

Common Pitfalls

常见误区

Pitfall 1: Insufficient Testing

误区1:测试不充分

Problem: Not testing edge cases and error conditions leads to production bugs
Solution: Implement comprehensive test coverage including:
  • Happy path scenarios
  • Error handling and edge cases
  • Integration points with external systems
Prevention: Enforce minimum code coverage (80%+) in CI/CD pipeline
问题:未测试边界情况和错误处理,导致生产环境出现bug
解决方案:实现全面的测试覆盖,包括:
  • 正常流程场景
  • 错误处理与边界情况
  • 与外部系统的集成点
预防措施:在CI/CD流水线中强制要求最低代码覆盖率(80%+)

Pitfall 2: Hardcoded Configuration

误区2:硬编码配置

Problem: Hardcoding values makes applications inflexible and environment-dependent
Solution: Use environment variables and configuration management:
  • Separate config from code
  • Use environment-specific configuration files
  • Never commit secrets to version control
Prevention: Use tools like dotenv, config validators, and secret scanners
问题:硬编码配置值导致应用灵活性差,依赖特定环境
解决方案:使用环境变量和配置管理工具:
  • 将配置与代码分离
  • 使用环境特定的配置文件
  • 绝不将敏感信息提交到版本控制系统
预防措施:使用dotenv、配置验证器和敏感信息扫描工具

Pitfall 3: Ignoring Security Best Practices

误区3:忽视安全最佳实践

Problem: Security vulnerabilities from not following established security patterns
Solution: Follow security guidelines:
  • Input validation and sanitization
  • Proper authentication and authorization
  • Encrypted data transmission (TLS/SSL)
  • Regular security audits and updates
Prevention: Use security linters, SAST tools, and regular dependency updates
Best Practices:
  • Follow established patterns and conventions for testing
  • Keep dependencies up to date and scan for vulnerabilities
  • Write comprehensive documentation and inline comments
  • Use linting and formatting tools consistently
  • Implement proper error handling and logging
  • Regular code reviews and pair programming
  • Monitor production metrics and set up alerts

问题:未遵循既定安全模式,导致安全漏洞
解决方案:遵循安全指南:
  • 输入验证与清理
  • 正确的身份验证与授权
  • 加密数据传输(TLS/SSL)
  • 定期安全审计与更新
预防措施:使用安全代码检查工具、SAST工具,并定期更新依赖
最佳实践
  • 遵循既定的测试模式与规范
  • 保持依赖更新并扫描漏洞
  • 编写全面的文档与内联注释
  • 持续使用代码检查与格式化工具
  • 实现完善的错误处理与日志记录
  • 定期代码评审与结对编程
  • 监控生产指标并设置告警

Bundled Resources

配套资源

  • Full TESTING_STANDARDS.md
  • UNIFIED_STANDARDS.md
  • Test configuration templates in
    ./templates/
  • Testing utility scripts in
    ./scripts/
  • Example test suites in
    ./resources/
  • 完整TESTING_STANDARDS.md
  • UNIFIED_STANDARDS.md
  • ./templates/
    目录下的测试配置模板
  • ./scripts/
    目录下的测试实用脚本
  • ./resources/
    目录下的示例测试套件