Skip to content
Back to skills

Testing Strategy

ASecurity

Testing strategy — unit/integration/e2e pyramid, TDD workflow, mocking best practices, test isolation, coverage targets

  • 10 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 9, 2026
ai-agentstypescriptpythonbashsqlfastapitestingapi

Works with

  • cli
  • api

Security analysis

A100/100

Scanned September 9, 2026

npx -y skills add yanacuti1121/Yana-AI --skill testing-strategy --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Testing Strategy?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Testing Strategy
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/yanacuti1121-testing-strategy/badge)](https://www.skillsdirectory.com/skills/yanacuti1121-testing-strategy)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: testing-strategy
description: Testing strategy — unit/integration/e2e pyramid, TDD workflow, mocking best practices, test isolation, coverage targets
triggers:
  - testing strategy
  - test pyramid
  - tdd workflow
  - unit test best practice
  - mock best practice
  - test isolation
  - integration test
  - test coverage target
  - pytest best practice
  - vitest jest best practice
do_not_use_for:
  - LLM evaluation — use ragas/deepeval
  - e2e browser testing — use playwright patterns
  - writing tests for specific code — use tdd-guide
see_also:
  - ai-code-maintainability
  - error-handling-patterns
  - type-safety-patterns
---

# Testing Strategy

## Test Pyramid

```
         [E2E]           ← few, slow, expensive, test real flows
       [Integration]     ← some, medium speed, real DB/API
     [Unit]              ← many, fast, isolated, mock externals
```

Target ratios: 70% unit, 20% integration, 10% e2e
Coverage targets: new code ≥ 80%, overall project ≥ 60%

## Python: pytest Best Practices

```python
# conftest.py — shared fixtures
import pytest
from sqlalchemy import create_engine
from sqlalchemy.orm import Session

@pytest.fixture(scope="session")
def engine():
    return create_engine("sqlite:///:memory:")   # test DB

@pytest.fixture
def db(engine) -> Session:
    Base.metadata.create_all(engine)
    with Session(engine) as session:
        yield session
        session.rollback()   # clean up after each test

@pytest.fixture
def user(db: Session) -> User:
    u = User(name="Test User", email="test@example.com")
    db.add(u)
    db.flush()
    return u
```

```python
# test_user_service.py — unit test with mock
import pytest
from unittest.mock import AsyncMock, patch, MagicMock
from my_app.user_service import UserService, EmailSender

class TestUserService:
    def test_create_user_sends_welcome_email(self):
        # Arrange
        mock_sender = MagicMock(spec=EmailSender)
        mock_repo = MagicMock()
        mock_repo.save.return_value = User(id="u-1", name="Alice", email="a@b.com")
        service = UserService(repo=mock_repo, sender=mock_sender)

        # Act
        result = service.create_user("Alice", "a@b.com")

        # Assert
        assert result.name == "Alice"
        mock_sender.send.assert_called_once_with(
            to="a@b.com",
            subject="Welcome!",
        )

    @pytest.mark.asyncio
    async def test_async_method(self):
        mock_api = AsyncMock()
        mock_api.fetch.return_value = {"status": "ok"}
        service = MyService(api=mock_api)
        result = await service.do_thing()
        assert result == "ok"
```

## TypeScript: Vitest Best Practices

```typescript
// user.service.test.ts
import { describe, it, expect, vi, beforeEach } from "vitest";
import { UserService } from "./user.service";

// Mock at module level
vi.mock("./email.service", () => ({
  EmailService: vi.fn().mockImplementation(() => ({
    send: vi.fn().mockResolvedValue(undefined),
  })),
}));

describe("UserService", () => {
  let service: UserService;
  let mockEmailService: { send: ReturnType<typeof vi.fn> };

  beforeEach(() => {
    mockEmailService = { send: vi.fn().mockResolvedValue(undefined) };
    service = new UserService({ emailService: mockEmailService });
  });

  it("sends welcome email on user creation", async () => {
    const user = await service.createUser({ name: "Alice", email: "a@b.com" });

    expect(user.name).toBe("Alice");
    expect(mockEmailService.send).toHaveBeenCalledOnce();
    expect(mockEmailService.send).toHaveBeenCalledWith(
      expect.objectContaining({ to: "a@b.com" })
    );
  });

  it("throws on duplicate email", async () => {
    await service.createUser({ name: "Alice", email: "dup@b.com" });
    await expect(
      service.createUser({ name: "Bob", email: "dup@b.com" })
    ).rejects.toThrow("email already exists");
  });
});
```

## Integration Test Pattern

```python
# test_order_api.py — integration: real DB, real HTTP
import pytest
import httpx
from fastapi.testclient import TestClient

@pytest.fixture(scope="module")
def client() -> TestClient:
    from my_app.main import app
    return TestClient(app)

def test_create_order_full_flow(client: TestClient, db: Session):
    # Create user
    user_resp = client.post("/users", json={"name": "Alice", "email": "a@b.com"})
    assert user_resp.status_code == 201
    user_id = user_resp.json()["id"]

    # Create order
    order_resp = client.post("/orders", json={"user_id": user_id, "items": [{"sku": "A", "qty": 2}]})
    assert order_resp.status_code == 201
    order = order_resp.json()
    assert order["status"] == "pending"
    assert order["user_id"] == user_id
```

## TDD Workflow

```bash
# RED: write failing test first
pytest tests/test_feature.py::test_new_behavior -v
# → FAILED (expected)

# GREEN: minimal implementation to pass
# Write only enough code to make the test pass

pytest tests/test_feature.py::test_new_behavior -v
# → PASSED

# REFACTOR: clean up without breaking tests
pytest tests/test_feature.py -v
# → All PASSED
```

## What NOT to Mock

```python
# ✅ Mock external I/O (network, DB, file system, time)
# ✅ Mock slow operations (sleep, large computations)
# ✅ Mock non-deterministic values (random, uuid, datetime.now)

# ❌ Don't mock your own domain logic
# ❌ Don't mock data transformations — test them directly
# ❌ Don't mock to avoid test complexity — fix the design instead

# ❌ Over-mocking — this test proves nothing
def test_user_service_create():
    service = MagicMock(spec=UserService)
    service.create.return_value = User(id="1")
    result = service.create(...)
    assert result.id == "1"  # testing the mock
```

## Anti-Fake-Pass Checks

- Test that fails before implementation = TDD red phase — skip this = untested code
- `assert_called_once_with()` is strict — `assert_called_with()` only checks the last call
- `scope="session"` fixtures are shared across tests — don't mutate them in individual tests
- `asyncio` tests need `@pytest.mark.asyncio` or `asyncio_mode = "auto"` in `pytest.ini`
- Integration tests hitting real DB need cleanup — use `session.rollback()` or transaction per test
- Coverage ≥ 80% on new code — measure with `pytest --cov=src --cov-fail-under=80`

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.