testing-strategies

GitHub

提供全面的测试策略,涵盖单元、集成、E2E等类型。强调测试行为而非实现,遵循测试金字塔,将测试视为代码并追求高置信度。包含成熟度模型及AAA模式等实践指南。

categories/development/testing-strategies/SKILL.md cosmicstack-labs/mercury-agent-skills

Trigger Scenarios

询问软件测试策略或最佳实践 需要编写单元测试或集成测试的示例 评估项目测试成熟度级别 优化现有测试代码的可维护性

Install

npx skills add cosmicstack-labs/mercury-agent-skills --skill testing-strategies -g -y
More Options

Non-standard path

npx skills add https://github.com/cosmicstack-labs/mercury-agent-skills/tree/main/categories/development/testing-strategies -g -y

Use without installing

npx skills use cosmicstack-labs/mercury-agent-skills@testing-strategies

指定 Agent (Claude Code)

npx skills add cosmicstack-labs/mercury-agent-skills --skill testing-strategies -a claude-code -g -y

安装 repo 全部 skill

npx skills add cosmicstack-labs/mercury-agent-skills --all -g -y

预览 repo 内 skill

npx skills add cosmicstack-labs/mercury-agent-skills --list

SKILL.md

Frontmatter
{
    "name": "testing-strategies",
    "metadata": {
        "tags": [
            "testing",
            "unit-tests",
            "integration-tests",
            "e2e",
            "property-based-testing",
            "mutation-testing"
        ],
        "author": "cosmicstack-labs",
        "version": "1.0.0",
        "category": "development"
    },
    "description": "Comprehensive testing strategy covering unit, integration, e2e, property-based, and mutation testing with practical patterns"
}

Testing Strategies

A comprehensive approach to testing that gives you confidence your code works correctly — from unit tests to mutation testing.

Core Principles

1. Test Behavior, Not Implementation

Your tests should specify what the code does, not how it does it. Tests that pass after a refactor (with the same behavior) are good tests. Tests that break after a refactor (with the same behavior) are brittle tests.

2. The Test Pyramid Is a Guideline, Not a Rule

Write many fast unit tests, some integration tests, and a few end-to-end tests. But adjust ratios based on your context: a data pipeline needs more integration tests; a UI component needs more visual regression tests.

3. Tests Are Code — Treat Them That Way

Tests need the same care as production code: clean naming, DRY helpers, proper abstractions. Test code that's hard to maintain leads to tests that get deleted.

4. Confidence Is the Goal

Coverage numbers are a proxy metric. A codebase with 80% coverage and excellent tests is better than one with 100% coverage and shallow tests. Test the things that scare you.


Testing Maturity Model

Level Unit Tests Integration Tests CI Integration Quality Gates
1: None No tests No tests No CI None
2: Skeleton Some critical paths Happy-path smoke tests Tests run manually None
3: Standard >60% coverage >80% of API endpoints Tests run on every PR Coverage check: >60%
4: Systematic >80% coverage Contract tests + DB tests CI fails on test failure Coverage + mutation score >70%
5: Excellence Property-based + mutation Consumer-driven contracts Test parallelization, flaky test detection Mutation score >85%, flaky tests auto-retry

Target: Level 3+ for production services. Level 4+ for critical systems.


Actionable Guidance

Unit Testing Patterns

The AAA Pattern (Arrange, Act, Assert)

import pytest
from datetime import datetime, timedelta

def test_discount_applies_to_premium_members():
    # Arrange
    user = User(membership="premium", joined_at=datetime.now() - timedelta(days=365))
    cart = Cart(items=[Item(price=100.0)])
    service = DiscountService()

    # Act
    discount = service.calculate_discount(user, cart)

    # Assert
    assert discount == 20.0  # 20% premium member discount

Test Naming Conventions

# Pattern: test_[unit]_[scenario]_[expected_behavior]

# Good names — tell you what's being tested
def test_calculate_discount_premium_member_returns_20_percent():
    ...

def test_calculate_discount_expired_membership_returns_0():
    ...

def test_calculate_discount_empty_cart_returns_0():
    ...

# Bad names — need to read the test body
def test_discount_1():
    ...

def test_discount_negative():
    ...

One Assertion Concept Per Test

# BAD: Testing multiple behaviors in one test
def test_order_total():
    order = create_order_with_items([Item(price=10.0), Item(price=20.0)])
    assert order.subtotal == 30.0
    assert order.tax == 3.0  # 10% tax
    assert order.total == 33.0
    # If tax calculation breaks, all three assertions fail
    # and you don't know which behavior broke

# GOOD: One assertion concept per test
def test_order_subtotal_is_sum_of_item_prices():
    order = create_order_with_items([Item(price=10.0), Item(price=20.0)])
    assert order.subtotal == 30.0

def test_order_tax_is_10_percent_of_subtotal():
    order = create_order_with_items([Item(price=30.0)])
    assert order.tax == 3.0

def test_order_total_is_subtotal_plus_tax():
    order = create_order_with_items([Item(price=30.0)])
    assert order.total == 33.0

Fixtures and Factories

import pytest
from datetime import datetime

# Use fixtures for shared setup
@pytest.fixture
def premium_user():
    return User(
        id=42,
        membership="premium",
        joined_at=datetime(2023, 1, 15)
    )

@pytest.fixture
def basic_user():
    return User(
        id=7,
        membership="basic",
        joined_at=datetime(2023, 6, 1)
    )

@pytest.fixture
def cart_with_items():
    return Cart(items=[
        Item(sku="ABC", price=50.0, quantity=2),
        Item(sku="XYZ", price=25.0, quantity=1)
    ])

# Use factory functions for complex setup
def create_order_with_items(items, user=None):
    if user is None:
        user = User(id=1, membership="basic")
    cart = Cart(items=items)
    return Order(user=user, cart=cart, payment_method="credit_card")

# Clean tests with fixtures
def test_premium_member_gets_free_shipping(premium_user, cart_with_items):
    shipping = ShippingService()
    cost = shipping.calculate_cost(premium_user, cart_with_items)
    assert cost == 0.0

def test_basic_member_pays_shipping(basic_user, cart_with_items):
    shipping = ShippingService()
    cost = shipping.calculate_cost(basic_user, cart_with_items)
    assert cost > 0.0

Mocking and Fakes

When to Mock vs. When to Fake

from unittest.mock import Mock, patch
import pytest

# Mock: Use for external services (HTTP, email, payments)
def test_order_creates_payment_charge():
    payment_gateway = Mock()
    payment_gateway.charge.return_value = Transaction(id="txn_123", status="success")
    
    service = OrderService(payment_gateway=payment_gateway)
    order = service.create_order(user_id=42, total=29.99)
    
    payment_gateway.charge.assert_called_once_with(
        amount=29.99,
        currency="USD",
        description="Order - User 42"
    )
    assert order.payment_status == "completed"

# Fake: Use for in-memory implementations of repositories
class InMemoryUserRepository:
    def __init__(self):
        self.users = {}
    
    def save(self, user):
        self.users[user.id] = user
    
    def find_by_id(self, user_id):
        return self.users.get(user_id)
    
    def find_by_email(self, email):
        for user in self.users.values():
            if user.email == email:
                return user
        return None

def test_user_registration():
    repo = InMemoryUserRepository()
    service = UserService(repo)
    
    user = service.register("alice@example.com", "secure_password")
    assert repo.find_by_email("alice@example.com") is not None
    assert user.email == "alice@example.com"

Mocking External HTTP Calls

import responses
import requests

@responses.activate
def test_external_api_integration():
    # Mock the external API
    responses.add(
        responses.GET,
        "https://api.github.com/repos/user/repo",
        json={"stargazers_count": 42, "description": "A great repo"},
        status=200
    )
    
    # Your code that calls the API
    result = fetch_repo_stats("user", "repo")
    
    assert result["stars"] == 42
    assert result["description"] == "A great repo"
    assert len(responses.calls) == 1

Integration Testing

Database Integration Tests

import pytest
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

@pytest.fixture
def db_session():
    # Use in-memory SQLite for fast test setup
    engine = create_engine("sqlite:///:memory:")
    Base.metadata.create_all(engine)
    Session = sessionmaker(bind=engine)
    session = Session()
    yield session
    session.close()

def test_create_and_retrieve_order(db_session):
    # Arrange
    repo = OrderRepository(db_session)
    user = User(id=42, name="Alice")
    db_session.add(user)
    db_session.commit()
    
    order = Order(user_id=user.id, total=29.99, status="pending")
    
    # Act
    saved_order = repo.save(order)
    retrieved_order = repo.find_by_id(saved_order.id)
    
    # Assert
    assert retrieved_order is not None
    assert retrieved_order.user_id == 42
    assert retrieved_order.total == 29.99
    assert retrieved_order.status == "pending"

API Integration Tests

import pytest
from fastapi.testclient import TestClient

@pytest.fixture
def client():
    app = create_app()  # Your FastAPI/Flask app
    return TestClient(app)

def test_create_order_endpoint(client):
    # Arrange
    request_data = {
        "user_id": 42,
        "items": [
            {"sku": "ABC-123", "quantity": 2}
        ],
        "payment_method": "credit_card"
    }
    
    # Act
    response = client.post("/api/orders", json=request_data)
    
    # Assert
    assert response.status_code == 201
    data = response.json()
    assert "order_id" in data
    assert data["status"] == "pending"
    assert data["total"] > 0

def test_get_order_not_found(client):
    response = client.get("/api/orders/99999")
    assert response.status_code == 404
    assert response.json()["detail"] == "Order not found"

End-to-End Testing

Playwright Example

import pytest
from playwright.sync_api import Page, expect

def test_user_checkout_flow(page: Page):
    # Navigate to the app
    page.goto("https://example.com")
    
    # Login
    page.click("text=Sign In")
    page.fill("[data-testid=email-input]", "alice@example.com")
    page.fill("[data-testid=password-input]", "password123")
    page.click("[data-testid=login-button]")
    
    # Wait for dashboard
    expect(page.locator("text=Welcome, Alice")).to_be_visible()
    
    # Add item to cart
    page.click("[data-testid=add-to-cart-ABC123]")
    expect(page.locator("[data-testid=cart-count]")).to_have_text("1")
    
    # Checkout
    page.click("[data-testid=checkout-button]")
    page.fill("[data-testid=card-number]", "4111111111111111")
    page.fill("[data-testid=expiry]", "12/28")
    page.fill("[data-testid=cvc]", "123")
    page.click("[data-testid=pay-button]")
    
    # Verify success
    expect(page.locator("[data-testid=order-confirmation]")).to_be_visible()
    expect(page.locator("[data-testid=order-status]")).to_have_text("confirmed")

Cypress Example

// cypress/e2e/user-registration.cy.js
describe('User Registration', () => {
  beforeEach(() => {
    cy.visit('/register')
  })

  it('should register a new user successfully', () => {
    cy.get('[data-cy=name-input]').type('Alice Johnson')
    cy.get('[data-cy=email-input]').type('alice@example.com')
    cy.get('[data-cy=password-input]').type('SecurePass123!')
    cy.get('[data-cy=tos-checkbox]').check()
    cy.get('[data-cy=register-button]').click()
    
    cy.url().should('include', '/welcome')
    cy.contains('Welcome, Alice Johnson').should('be.visible')
  })

  it('should show validation errors for invalid email', () => {
    cy.get('[data-cy=email-input]').type('not-an-email')
    cy.get('[data-cy=password-input]').type('short')
    cy.get('[data-cy=register-button]').click()
    
    cy.contains('Invalid email address').should('be.visible')
    cy.contains('Password must be at least 8 characters').should('be.visible')
  })
})

Property-Based Testing

Test properties that should always be true, rather than specific examples.

from hypothesis import given, strategies as st
from hypothesis.strategies import integers, text, lists

# Example: Testing a sorting function
@given(lists(integers()))
def test_sort_always_returns_sorted_list(items):
    result = sorted(items)
    for i in range(len(result) - 1):
        assert result[i] <= result[i + 1]

@given(lists(integers()))
def test_sort_preserves_elements(items):
    result = sorted(items)
    assert sorted(result) == sorted(items)

@given(lists(integers()))
def test_sort_is_idempotent(items):
    first_sort = sorted(items)
    second_sort = sorted(first_sort)
    assert first_sort == second_sort

# Example: Testing URL validation
@given(text())
def test_valid_urls_have_expected_structure(url):
    is_valid = is_valid_url(url)
    if is_valid:
        assert url.startswith("http://") or url.startswith("https://")
        assert "." in url

# Example: Testing arithmetic
@given(integers(), integers())
def test_addition_is_commutative(a, b):
    assert a + b == b + a

@given(integers(), integers(), integers())
def test_addition_is_associative(a, b, c):
    assert (a + b) + c == a + (b + c)

Mutation Testing

Mutation testing checks your test quality by introducing bugs and seeing if your tests catch them.

# Install: pip install mutmut

# Original code
def calculate_discount(price: float, is_member: bool) -> float:
    if is_member:
        return price * 0.2  # 20% discount for members
    return 0.0

# Mutmut creates mutants:
# Mutant 1: price * 0.1  (changed constant)
# Mutant 2: price * 0.3  (changed constant)
# Mutant 3: if not is_member  (negated condition)
# Mutant 4: return price * 0.0  (changed value)
# Mutant 5: return price * 0.2 + 1  (added statement)

# Your tests should kill ALL mutants
def test_member_gets_discount():
    assert calculate_discount(100.0, True) == 20.0

def test_non_member_gets_no_discount():
    assert calculate_discount(100.0, False) == 0.0

# These two tests kill all 5 mutants above
# If any mutant survives, your tests are incomplete

Mutation testing workflow:

# Run mutation testing
mutmut run --paths-to-mutate src/

# Review surviving mutants
mutmut results

# Show a surviving mutant
mutmut show 1  # Shows mutant #1 diff

What survivors tell you:

Survival Pattern What's Missing
Constant changed (100 → 0) Tests don't verify specific values
Condition negated (if → if not) Tests don't cover the false branch
Removed function call Tests don't verify side effects
Changed boundary (>= → >) Off-by-one edge case not tested

Test Coverage That Matters

# Not all code is equal. Prioritize testing by risk.

HIGH_PRIORITY = [
    "Payment processing",
    "Authentication/Authorization",
    "Data validation",
    "ID generation / unique constraint logic",
    "State machines / status transitions",
    "Concurrent access / race conditions",
]

MEDIUM_PRIORITY = [
    "Business logic / calculations",
    "API request handling",
    "Data transformation / mapping",
    "Caching logic",
]

LOW_PRIORITY = [
    "Simple getters/setters",
    "Configuration loading",
    "Logging/tracing",
    "Generated code",
    "Trivial delegation methods",
]

def test_priority_guidance():
    """Target 100% coverage for HIGH_PRIORITY, >80% for MEDIUM,
    and don't sweat LOW_PRIORITY under 50%."""
    pass

Contract Tests (Consumer-Driven)

# Consumer (microservice A) defines expectations
# Provider (microservice B) must satisfy them

from pact import Consumer, Provider

@pytest.fixture(scope='module')
def pact():
    pact = Consumer('OrderService').has_pact_with(
        Provider('UserService')
    )
    pact.start_service()
    yield pact
    pact.stop_service()

def test_user_service_returns_user_details(pact):
    # Define the expected interaction
    pact.given('user 42 exists') \
        .upon_receiving('a request for user details') \
        .with_request('GET', '/api/users/42') \
        .will_respond_with(200, body={
            'id': 42,
            'name': 'Alice',
            'email': 'alice@example.com'
        })
    
    # Exercise the consumer code
    with pact:
        client = UserServiceClient(base_url=pact.uri)
        user = client.get_user(42)
        
    # Verify
    assert user.id == 42
    assert user.name == 'Alice'

Test Organization

# Organize tests to mirror source structure
"""
src/
  services/
    order_service.py
    user_service.py

tests/
  unit/
    services/
      test_order_service.py
      test_user_service.py
  integration/
    test_database.py
    test_api_endpoints.py
  e2e/
    test_user_flow.py
    test_admin_flow.py
  conftest.py  # Shared fixtures
"""

# Use markers to categorize tests
import pytest

@pytest.mark.slow
def test_heavy_computation():
    ...

@pytest.mark.integration
def test_database_interaction():
    ...

@pytest.mark.smoke
def test_critical_health_check():
    ...

# Run specific categories
# pytest -m "not slow"        # Skip slow tests
# pytest -m "integration"      # Only integration tests
# pytest -m "smoke"            # Quick sanity checks

Common Mistakes

  1. Testing implementation instead of behavior: Your tests break when you refactor even though behavior is identical. Test the public interface and observable results.
  2. Over-mocking: Mocking every dependency creates brittle tests that know too much. Use real objects or fakes when practical.
  3. Flaky tests: Tests that pass sometimes and fail other times erode trust. Fix flaky tests immediately or disable them.
  4. Chasing 100% coverage without quality: Coverage is a proxy. A 100% covered codebase can still have buggy behavior. Focus on testing logic, not lines.
  5. Testing only happy paths: Every test for the success case should have a sibling test for the failure case. Edge cases catch production bugs.
  6. Test code duplication: Extract test helpers and fixtures. Duplicated test setup leads to tests that don't get updated when things change.
  7. Not running tests in CI: Tests that only pass locally aren't tests — they're documentation at best.
  8. Ignoring test failures: A failing test suite is a broken promise. Fix failures before adding new code.
  9. Writing tests after the fact (or not at all): Test-driven development (TDD) isn't required, but tests written after the code often reflect what the code does, not what it should do.

Version History

  • 38e2523 Current 2026-07-05 19:38

Same Skill Collection

categories/ai-ml/agent-audit-logging/SKILL.md
categories/ai-ml/agent-handoff-protocols/SKILL.md
categories/ai-ml/agent-health-monitoring/SKILL.md
categories/ai-ml/agent-task-delegation/SKILL.md
categories/ai-ml/ai-agent-design/SKILL.md
categories/ai-ml/error-recovery-retry/SKILL.md
categories/ai-ml/memory-management/SKILL.md
categories/ai-ml/prompt-engineering/SKILL.md
categories/ai-ml/prompt-version-management/SKILL.md
categories/ai-ml/token-budget-tracking/SKILL.md
categories/automation/daily-briefing/SKILL.md
categories/automation/screenshot/SKILL.md
categories/automation/shell-scripting/SKILL.md
categories/automation/twitter-account-manager/SKILL.md
categories/automation/workflow-automation/SKILL.md
categories/automation/x-twitter-automation/SKILL.md
categories/backend/api-design/SKILL.md
categories/backend/authentication-authorization/SKILL.md
categories/backend/caching-strategies/SKILL.md
categories/backend/database-design/SKILL.md
categories/backend/message-queues/SKILL.md
categories/backend/microservices/SKILL.md
categories/backend/nodejs-patterns/SKILL.md
categories/backend/python-patterns/SKILL.md
categories/backend/serverless-patterns/SKILL.md
categories/business/event-staffing-compliance/SKILL.md
categories/business/event-staffing-ordering/SKILL.md
categories/business/negotiation/SKILL.md
categories/business/startup-strategy/SKILL.md
categories/career/career-planning/SKILL.md
categories/career/interview-prep/SKILL.md
categories/career/linkedin-optimization/SKILL.md
categories/career/resume-writing/SKILL.md
categories/career/salary-negotiation/SKILL.md
categories/creative-personal-development/content-repurposer/SKILL.md
categories/creative-personal-development/daily-standup-journal/SKILL.md
categories/creative-personal-development/decision-matrix/SKILL.md
categories/creative-personal-development/idea-validator/SKILL.md
categories/creative-personal-development/meeting-note-summarizer/SKILL.md
categories/creative-personal-development/personal-branding-statement/SKILL.md
categories/creative-personal-development/storytelling-advisor/SKILL.md
categories/creative-personal-development/time-blocking-scheduler/SKILL.md
categories/data/data-pipeline/SKILL.md
categories/design/accessibility/SKILL.md
categories/design/ui-design-system/SKILL.md
categories/development/api-documentation/SKILL.md
categories/development/architecture-decision-records/SKILL.md
categories/development/clean-code/SKILL.md
categories/development/code-review/SKILL.md
categories/development/debugging-mastery/SKILL.md
categories/development/dependency-management/SKILL.md
categories/development/documentation-generation/SKILL.md
categories/development/git-workflow/SKILL.md
categories/development/hyperframes-cli/SKILL.md
categories/development/hyperframes-media/SKILL.md
categories/development/knowledge-base/SKILL.md
categories/development/markdown-mastery/SKILL.md
categories/development/refactoring-patterns/SKILL.md
categories/development/technical-writing/SKILL.md
categories/devops/ci-cd-pipeline/SKILL.md
categories/devops/cloud-architecture/SKILL.md
categories/devops/docker-patterns/SKILL.md
categories/devops/kubernetes-patterns/SKILL.md
categories/devops/monitoring-observability/SKILL.md
categories/devops/sre-practices/SKILL.md
categories/devops/terraform-iac/SKILL.md
categories/education-learning/assessment-design/SKILL.md
categories/education-learning/learning-science/SKILL.md
categories/education-learning/micro-learning/SKILL.md
categories/education-learning/teaching-methods/SKILL.md
categories/finance-legal/budgeting-forecasting/SKILL.md
categories/finance-legal/contract-review/SKILL.md
categories/finance-legal/financial-analysis/SKILL.md
categories/finance-legal/privacy-compliance/SKILL.md
categories/finance-legal/risk-management/SKILL.md
categories/frontend/component-design-systems/SKILL.md
categories/frontend/frontend-testing/SKILL.md
categories/frontend/nextjs-patterns/SKILL.md
categories/frontend/react-patterns/SKILL.md
categories/frontend/responsive-design/SKILL.md
categories/frontend/state-management/SKILL.md
categories/frontend/tailwind-css/SKILL.md
categories/frontend/web-performance/SKILL.md
categories/health-wellness/fitness-planning/SKILL.md
categories/health-wellness/habit-formation/SKILL.md
categories/health-wellness/mental-health/SKILL.md
categories/health-wellness/nutrition-planning/SKILL.md
categories/health-wellness/sleep-optimization/SKILL.md
categories/marketing/content-creation/SKILL.md
categories/marketing/local-business-growth/SKILL.md
categories/marketing/seo-strategy/SKILL.md
categories/media-download/audio-extraction/SKILL.md
categories/media-download/github-repo-promo/SKILL.md
categories/media-download/github-repo-tour/SKILL.md
categories/media-download/legal-downloading/SKILL.md
categories/media-download/playlist-archiver/SKILL.md
categories/media-download/video-downloader/SKILL.md
categories/mobile/android-kotlin-patterns/SKILL.md
categories/mobile/app-store-optimization/SKILL.md
categories/mobile/ios-swift-patterns/SKILL.md
categories/mobile/mobile-performance/SKILL.md
categories/mobile/react-native-patterns/SKILL.md
categories/pdf-generation/invoice-document-pdf/SKILL.md
categories/pdf-generation/markdown-to-pdf/SKILL.md
categories/pdf-generation/report-generation/SKILL.md
categories/pdf-generation/typesetting-latex/SKILL.md
categories/presentation/data-storytelling/SKILL.md
categories/presentation/pitch-deck-creation/SKILL.md
categories/presentation/presentation-automation/SKILL.md
categories/presentation/presentation-design/SKILL.md
categories/product/product-strategy/SKILL.md
categories/product/user-research/SKILL.md
categories/security/security-audit/SKILL.md
categories/shop-restaurant/amazon-assistant/SKILL.md
categories/shop-restaurant/daily-pulse/SKILL.md
categories/shop-restaurant/inventory-optimizer/SKILL.md
categories/shop-restaurant/menu-engineer/SKILL.md
categories/shop-restaurant/price-scout/SKILL.md
categories/shop-restaurant/review-responder/SKILL.md
categories/shop-restaurant/social-post/SKILL.md
categories/shop-restaurant/staff-scheduler/SKILL.md
categories/shop-restaurant/table-manager/SKILL.md
categories/shop-restaurant/zomato-order/SKILL.md
categories/testing-qa/accessibility-testing/SKILL.md
categories/testing-qa/api-testing/SKILL.md
categories/testing-qa/e2e-testing/SKILL.md
categories/testing-qa/performance-testing/SKILL.md
categories/testing-qa/test-strategy/SKILL.md
categories/ai-ml/gbrain-lite/SKILL.md
categories/development/hyperframes/SKILL.md
categories/pdf-generation/any2pdf/SKILL.md

Metadata

Files
0
Version
38e2523
Hash
2f18778f
Indexed
2026-07-05 19:38

trang chủ - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-07-09 01:06
浙ICP备14020137号-1 $bản đồ khách truy cập$