Claude
Skills
Sign in
Back

testing-code

Included with Lifetime
$97 forever

Generates and improves tests following TDD principles. Activates when new features are implemented, test coverage is low, or user requests tests. Ensures comprehensive test coverage with unit, integration, and edge case tests.

Code Review

What this skill does


# Testing Code

You are activating test generation and improvement capabilities. Your role is to ensure code has comprehensive, maintainable test coverage.

## When to Activate

This skill activates when:

- New features or functions are implemented
- User requests tests ("add tests", "test this")
- Test coverage is low or missing
- Bugs are found (need regression tests)
- Refactoring code (need confidence tests pass)
- Before creating pull requests

## Testing Philosophy

### Why Test?

- **Confidence**: Know code works as expected
- **Regression Prevention**: Catch bugs from changes
- **Documentation**: Tests show how code should be used
- **Design Feedback**: Hard to test = bad design
- **Refactoring Safety**: Change with confidence

### Test Pyramid

```
        /\
       /  \    E2E Tests (Few)
      /    \   - Test full workflows
     /------\
    /        \ Integration Tests (Some)
   /          \- Test module interactions
  /------------\
 /              \ Unit Tests (Many)
/______________/ - Test individual functions
```

## Testing Process

### 1. Analyze Code

Understand what to test:

- What is the purpose?
- What are the inputs and outputs?
- What are the edge cases?
- What are the error conditions?
- What are the side effects?

### 2. Identify Test Cases

#### Happy Path

- Normal, expected usage
- Valid inputs producing valid outputs

#### Edge Cases

- Boundary values (0, -1, max, empty)
- Unusual but valid inputs
- Minimum and maximum values

#### Error Cases

- Invalid inputs
- Null/undefined/None
- Wrong types
- Violations of constraints

#### Integration Points

- External API calls
- Database interactions
- File system operations
- Other modules/classes

### 3. Write Tests

Follow this structure:

```python
def test_function_name_condition_expected():
    """
    Test that function_name handles condition and returns expected result.
    """
    # Arrange: Set up test data and conditions
    input_data = ...
    expected_output = ...

    # Act: Execute the code under test
    result = function_name(input_data)

    # Assert: Verify the result
    assert result == expected_output
```

### 4. Check Coverage

Ensure comprehensive coverage:

- All code paths executed
- All branches tested
- All error conditions tested
- Edge cases covered

## Test Patterns

### Unit Tests

Test individual functions in isolation.

**Python Example**:

```python
import pytest
from mymodule import calculate_total

def test_calculate_total_with_valid_items():
    """Calculate total for valid items."""
    items = [
        {"price": 10.00, "quantity": 2},
        {"price": 5.00, "quantity": 3},
    ]
    assert calculate_total(items) == 35.00

def test_calculate_total_with_empty_list():
    """Calculate total returns 0 for empty list."""
    assert calculate_total([]) == 0.00

def test_calculate_total_with_zero_quantity():
    """Calculate total handles zero quantity."""
    items = [{"price": 10.00, "quantity": 0}]
    assert calculate_total(items) == 0.00

def test_calculate_total_raises_on_negative_price():
    """Calculate total raises ValueError for negative price."""
    items = [{"price": -10.00, "quantity": 1}]
    with pytest.raises(ValueError, match="Price cannot be negative"):
        calculate_total(items)
```

**JavaScript Example**:

```javascript
import { describe, it, expect } from "vitest";
import { calculateTotal } from "./cart";

describe("calculateTotal", () => {
  it("calculates total for valid items", () => {
    const items = [
      { price: 10.0, quantity: 2 },
      { price: 5.0, quantity: 3 },
    ];
    expect(calculateTotal(items)).toBe(35.0);
  });

  it("returns 0 for empty list", () => {
    expect(calculateTotal([])).toBe(0);
  });

  it("handles zero quantity", () => {
    const items = [{ price: 10.0, quantity: 0 }];
    expect(calculateTotal(items)).toBe(0);
  });

  it("throws error for negative price", () => {
    const items = [{ price: -10.0, quantity: 1 }];
    expect(() => calculateTotal(items)).toThrow("Price cannot be negative");
  });
});
```

### Integration Tests

Test multiple components working together.

**Example**:

```python
def test_user_registration_flow():
    """Test complete user registration workflow."""
    # Arrange: Set up test database
    db = setup_test_database()
    api = UserAPI(db)

    # Act: Register user
    response = api.register({
        "email": "[email protected]",
        "password": "SecurePass123!",
    })

    # Assert: User created and email sent
    assert response.status == 201
    assert db.users.find_by_email("[email protected]") is not None
    assert email_was_sent("[email protected]", "Welcome")
```

### Mocking & Stubbing

Isolate code from external dependencies.

**Python Example**:

```python
from unittest.mock import Mock, patch

def test_send_notification_calls_email_service():
    """Test that send_notification calls email service correctly."""
    # Arrange: Mock email service
    mock_email = Mock()

    # Act: Send notification
    with patch('mymodule.email_service', mock_email):
        send_notification("[email protected]", "Hello")

    # Assert: Email service called with correct args
    mock_email.send.assert_called_once_with(
        to="[email protected]",
        subject="Notification",
        body="Hello"
    )
```

### Parameterized Tests

Test multiple inputs efficiently.

**Python Example**:

```python
@pytest.mark.parametrize("input,expected", [
    (0, "zero"),
    (1, "one"),
    (2, "two"),
    (10, "many"),
    (-5, "negative"),
])
def test_number_to_word(input, expected):
    """Test number_to_word for various inputs."""
    assert number_to_word(input) == expected
```

### Property-Based Tests

Generate test cases automatically.

**Python Example**:

```python
from hypothesis import given
from hypothesis.strategies import integers

@given(integers())
def test_double_is_reversible(x):
    """Test that doubling and halving returns original value."""
    assert half(double(x)) == x
```

## Test Organization

### Directory Structure

```
project/
├── src/
│   └── mymodule/
│       ├── __init__.py
│       ├── calculator.py
│       └── user.py
└── tests/
    ├── __init__.py
    ├── unit/
    │   ├── test_calculator.py
    │   └── test_user.py
    ├── integration/
    │   └── test_user_flow.py
    └── conftest.py  # Shared fixtures
```

### Naming Conventions

- Test files: `test_*.py` or `*_test.py`
- Test functions: `test_<function>_<condition>_<expected>`
- Test classes: `Test<ClassName>`

**Good Names**:

- `test_calculate_total_with_empty_list_returns_zero`
- `test_user_login_with_invalid_password_raises_error`
- `test_api_returns_404_for_nonexistent_resource`

**Bad Names**:

- `test_calc` (too vague)
- `test_1` (no meaning)
- `test_it_works` (what works?)

## Testing Checklist

For each function/class, ensure tests for:

### Functionality

- [ ] Happy path (normal usage)
- [ ] Return values correct
- [ ] Side effects occur as expected

### Edge Cases

- [ ] Empty inputs ([], "", 0, None)
- [ ] Boundary values (min, max, -1)
- [ ] Large inputs
- [ ] Special characters/values

### Error Handling

- [ ] Invalid inputs
- [ ] Null/undefined/None
- [ ] Wrong types
- [ ] Constraint violations
- [ ] External failures (API down, etc.)

### Integration

- [ ] Calls to other functions/modules
- [ ] Database interactions
- [ ] File operations
- [ ] Network requests

## Test Quality Standards

### Good Tests Are:

**Fast**:

- Run in milliseconds
- No unnecessary I/O
- Use mocks for external dependencies

**Independent**:

- No shared state between tests
- Can run in any order
- Don't depend on other tests

**Repeatable**:

- Same result every time
- No flaky tests
- No dependency on external state

**Self-Validating**:

- Pass or fail clearly
- No manual inspection
- Descriptive failure messages

**Timely**:

- Written before or with code (TDD)
- Not as an afterthought
- Updated when code changes

### Anti-Patterns to Avoid

**Testing Implementation 

Related in Code Review