claude/skills/test-expert/SKILL.md
Testing methodologies, test-driven development (TDD), unit and integration testing, and testing best practices across multiple frameworks. Use when the user needs to write tests, implement TDD, or improve test coverage and quality.
npx skillsauth add einverne/dotfiles test-expertInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
You are a testing expert. Your role is to help users write effective tests, follow TDD practices, and ensure code quality through comprehensive test coverage.
/\
/ \ E2E Tests (Few)
/____\
/ \ Integration Tests (Some)
/________\
/ \ Unit Tests (Many)
/__________\
def test_add_numbers():
assert add(2, 3) == 5 # Function doesn't exist yet
def add(a, b):
return a + b
def add(a: int, b: int) -> int:
"""Add two numbers and return the result."""
return a + b
# Good: Clear, focused, independent
def test_user_can_be_created_with_email():
# Arrange
email = "[email protected]"
# Act
user = User(email=email)
# Assert
assert user.email == email
assert user.is_active == True
# Good names describe what's being tested
def test_user_creation_with_valid_email_succeeds():
pass
def test_user_creation_with_invalid_email_raises_error():
pass
def test_empty_cart_has_zero_total():
pass
import pytest
from myapp import Calculator
class TestCalculator:
@pytest.fixture
def calc(self):
return Calculator()
def test_add(self, calc):
assert calc.add(2, 3) == 5
def test_divide_by_zero_raises_error(self, calc):
with pytest.raises(ZeroDivisionError):
calc.divide(10, 0)
@pytest.mark.parametrize("a,b,expected", [
(2, 3, 5),
(0, 0, 0),
(-1, 1, 0),
])
def test_add_multiple_cases(self, calc, a, b, expected):
assert calc.add(a, b) == expected
describe('Calculator', () => {
let calc;
beforeEach(() => {
calc = new Calculator();
});
test('adds two numbers', () => {
expect(calc.add(2, 3)).toBe(5);
});
test('throws error on division by zero', () => {
expect(() => calc.divide(10, 0)).toThrow();
});
test.each([
[2, 3, 5],
[0, 0, 0],
[-1, 1, 0],
])('add(%i, %i) returns %i', (a, b, expected) => {
expect(calc.add(a, b)).toBe(expected);
});
});
#!/usr/bin/env bats
@test "script exits with status 0 on success" {
run ./myscript.sh input.txt
[ "$status" -eq 0 ]
}
@test "script produces expected output" {
run ./myscript.sh input.txt
[ "${lines[0]}" = "Expected output" ]
}
@test "script fails with invalid input" {
run ./myscript.sh nonexistent.txt
[ "$status" -ne 0 ]
[[ "$output" =~ "Error" ]]
}
from unittest.mock import Mock, patch, MagicMock
# Mock an object
mock_db = Mock()
mock_db.get_user.return_value = {"id": 1, "name": "Test"}
# Patch a function
@patch('myapp.external_api_call')
def test_function(mock_api):
mock_api.return_value = {"status": "success"}
result = my_function()
assert result == expected
mock_api.assert_called_once_with(expected_arg)
// Jest mocking
jest.mock('./api');
import { fetchUser } from './api';
test('loads user data', async () => {
fetchUser.mockResolvedValue({ id: 1, name: 'Test' });
const user = await loadUser(1);
expect(user.name).toBe('Test');
expect(fetchUser).toHaveBeenCalledWith(1);
});
import pytest
from myapp import create_app, db
@pytest.fixture
def app():
app = create_app('testing')
with app.app_context():
db.create_all()
yield app
db.session.remove()
db.drop_all()
def test_user_can_be_saved_to_database(app):
user = User(email='[email protected]')
db.session.add(user)
db.session.commit()
retrieved = User.query.filter_by(email='[email protected]').first()
assert retrieved is not None
assert retrieved.email == '[email protected]'
def test_api_returns_user_list(client):
response = client.get('/api/users')
assert response.status_code == 200
assert len(response.json) > 0
assert 'email' in response.json[0]
// Playwright example
test('user can login', async ({ page }) => {
await page.goto('https://example.com');
await page.fill('[name="email"]', '[email protected]');
await page.fill('[name="password"]', 'password123');
await page.click('button[type="submit"]');
await expect(page.locator('.welcome')).toContainText('Welcome back');
});
@pytest.fixture
def sample_user():
return User(
email='[email protected]',
name='Test User'
)
@pytest.fixture
def authenticated_client(client, sample_user):
client.login(sample_user)
return client
import factory
class UserFactory(factory.Factory):
class Meta:
model = User
email = factory.Sequence(lambda n: f'user{n}@example.com')
name = factory.Faker('name')
is_active = True
# Usage
user = UserFactory()
admin = UserFactory(is_admin=True)
users = UserFactory.create_batch(10)
project/
├── src/
│ └── myapp/
│ ├── __init__.py
│ └── calculator.py
└── tests/
├── __init__.py
├── conftest.py # Shared fixtures
├── unit/
│ └── test_calculator.py
├── integration/
│ └── test_database.py
└── e2e/
└── test_user_flow.py
# Python
pytest --cov=myapp --cov-report=html
# JavaScript
jest --coverage
# View coverage
open htmlcov/index.html
def test_raises_error():
with pytest.raises(ValueError, match="Invalid input"):
function_that_raises("bad")
@pytest.mark.asyncio
async def test_async_function():
result = await async_function()
assert result == expected
@patch('myapp.datetime')
def test_time_dependent(mock_datetime):
mock_datetime.now.return_value = datetime(2024, 1, 1)
result = function_using_time()
assert result == expected
# .github/workflows/test.yml
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run tests
run: |
pip install -r requirements-dev.txt
pytest --cov --cov-report=xml
- name: Upload coverage
uses: codecov/codecov-action@v2
Remember: Good tests are your safety net. They give you confidence to refactor and add features. Invest time in writing quality tests!
development
生成符合项目规范的 React 组件。当用户要求创建组件、新建 React 组件或生成组件文件时使用
development
生成符合 Conventional Commits 规范的 Git 提交信息。当用户要求生成提交、创建 commit 或写提交信息时使用
devops
将当前分支部署到测试环境。当用户要求部署、发布到测试或在 staging 环境测试时使用
development
进行系统化的代码审查,检查代码质量、安全性和性能。当用户要求审查代码、review 或检查代码时使用