How this skill is triggered — by the user, by Claude, or both
Slash command
/solocheck-skills:api-integration-testThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
- [ ] `tests/test_{module}_api.py` 위치
tests/test_{module}_api.py 위치tests/conftest.py - 공통 Fixturefastapi.testclient.TestClient 사용client - TestClientauth_headers - 인증 헤더test_user - 테스트 사용자import pytest
from fastapi.testclient import TestClient
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from src.main import app
from src.database import Base, get_db
from src.users.models import User
from src.common.security import get_password_hash, create_access_token
TEST_DATABASE_URL = "sqlite:///./test.db"
engine = create_engine(TEST_DATABASE_URL, connect_args={"check_same_thread": False})
TestSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
@pytest.fixture(scope="session")
def setup_database():
"""테스트 DB 스키마 생성"""
Base.metadata.create_all(bind=engine)
yield
Base.metadata.drop_all(bind=engine)
@pytest.fixture
def db_session(setup_database):
"""각 테스트별 DB 세션 (롤백)"""
connection = engine.connect()
transaction = connection.begin()
session = TestSessionLocal(bind=connection)
yield session
session.close()
transaction.rollback()
connection.close()
@pytest.fixture
def client(db_session):
"""테스트 클라이언트"""
def override_get_db():
yield db_session
app.dependency_overrides[get_db] = override_get_db
with TestClient(app) as c:
yield c
app.dependency_overrides.clear()
@pytest.fixture
def test_user(db_session):
"""기본 테스트 사용자"""
user = User(
id="test-user-id",
email="[email protected]",
password_hash=get_password_hash("password123"),
nickname="테스트유저",
is_active=True
)
db_session.add(user)
db_session.commit()
return user
@pytest.fixture
def auth_headers(test_user):
"""인증 헤더"""
token = create_access_token({"sub": test_user.id})
return {"Authorization": f"Bearer {token}"}
import pytest
class Test{Resource}API:
"""{Resource} API 통합 테스트"""
# --- POST ---
def test_create_{resource}_success(self, client, auth_headers):
"""생성 성공"""
response = client.post(
"/api/v1/{resources}",
json={
"name": "테스트",
"value": "[email protected]",
"priority": 1
},
headers=auth_headers
)
assert response.status_code == 201
data = response.json()
assert data["name"] == "테스트"
assert "id" in data
def test_create_{resource}_unauthorized(self, client):
"""인증 없이 생성 시도"""
response = client.post(
"/api/v1/{resources}",
json={"name": "테스트", "value": "[email protected]", "priority": 1}
)
assert response.status_code == 403
def test_create_{resource}_validation_error(self, client, auth_headers):
"""검증 실패"""
response = client.post(
"/api/v1/{resources}",
json={"name": "", "priority": 10}, # 잘못된 값
headers=auth_headers
)
assert response.status_code == 422
# --- GET ---
def test_get_{resources}_empty(self, client, auth_headers):
"""빈 목록 조회"""
response = client.get("/api/v1/{resources}", headers=auth_headers)
assert response.status_code == 200
data = response.json()
assert data["data"] == []
# --- DELETE ---
def test_delete_{resource}_success(self, client, auth_headers, existing_{resource}):
"""삭제 성공"""
response = client.delete(
f"/api/v1/{resources}/{existing_{resource}.id}",
headers=auth_headers
)
assert response.status_code == 204
def test_delete_{resource}_not_found(self, client, auth_headers):
"""없는 리소스 삭제"""
response = client.delete(
"/api/v1/{resources}/nonexistent-id",
headers=auth_headers
)
assert response.status_code == 404
Provides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub roo2323/ce-part-repo