# 08. 테스트 Lane 구성

> **상태**: 2026-04-22 W3-1에서 도입. Wave 3 Gate G3의 필수 전제.
> **기준**: `backend/pytest.ini` + `backend/tests/conftest.py` `pytest_collection_modifyitems`.

## 왜 분리했는가

W0 감사에서 저장소 전체 `pytest`가 **637 passed / 56 failed / 2 errors / 1 skipped**로 측정됐는데, 이 중 `architecture-refactor-final/README.md`가 말하는 "256 passed"는 실제로는 core lane subset이었다. 전체 결과를 한 개 숫자로 보면 다음 두 상황을 구분할 수 없다:

1. 공개 계약(startup/auth/api) 회귀
2. 레거시 v2/v3 drift (이미 알고 있는 F19 cluster)

lane을 분리하면:
- core lane은 "지금 바로 깨지면 안 되는 계약". CI 기본 실행.
- startup lane은 앱 부팅/auth/users/api. 배포 직전 필수.
- image lane은 시간이 오래 걸리는 모킹 + I/O heavy 영역. 별도 lane으로 유지.
- full lane은 W3~W5 기간 동안 drift 정리 대상. 녹색이 된 cluster부터 core/startup으로 이동.

## Marker 정의

| marker | 파일 대상 | 집계 (2026-04-24 실측) | 기준선 |
|--------|-----------|-------------------|--------|
| `core` | `tests/core/**`, `tests/services/**`, `tests/pipeline/**` | 538 tests | **533 pass / 5 skip / 0 fail** |
| `startup` | `test_auth_api`, `test_users_api`, `test_pipeline_e2e`, `test_*_api`, `test_models`, `test_security`, `test_moderation*`, `test_i18n`, `test_provenance`, `test_visual_world_rules`, `test_*_summary`, `test_project_export_import`, `test_applicability`, `test_step_catalog`, `test_manifest_fields`, `test_settings_registry`, `test_api_endpoint_decorator`, `test_progress`, `test_activity_logger`, `test_checkpoint_io` | 223 tests | 159 pass / 6 fail / 1 skip / 57 errors (DB fixture 의존, 환경별 편차) |
| `image` | `test_images_api`, `test_image_validator`, `test_fal_angle_edit`, `test_gemini_i2i_angle`, `test_variation_pipeline`, `test_entity_dependency`, `test_gpt_scene10_analysis` | 86 tests | 43 pass / 5 fail / 3 skip / 35 errors (DB fixture 의존) |
| `full` | 위에 포함되지 않은 나머지 루트 파일 (legacy v2/v3 drift — `test_*_v2`, `test_*_v3`, `test_entity_*`, `test_outlook_v2` 등) | 152 tests | 123 pass / 1 fail / 24 skip / 4 errors |
| `pg` | PostgreSQL 통합 (기본 실행에서 제외) | 별도 | n/a |

**합계**: 999 tests / 858 pass / 12 fail / 33 skip / 96 errors.

> ⚠️ 2026-04-24 실측의 startup/image/full errors(57/35/4)는 PostgreSQL 테스트 fixture 초기화 실패가 다수 — 환경에 따라 변동. `core`는 환경 독립적이므로 baseline 신뢰도 최고.

## 사용법

> **주의**: `backend/pytest.ini`의 `addopts = -m "not pg"` 때문에 `pytest tests/ -k <name>`으로 필터해도 pg 테스트는 기본 제외된다. pg lane을 쓰려면 반드시 `-m pg`로 override.

```bash
cd backend

# 기본: core 만 (~1s, 가장 빠름)
.venv/bin/python -m pytest tests/ -m core

# startup lane (TestClient 필요, ~2분)
.venv/bin/python -m pytest tests/ -m startup

# image lane (I/O heavy, ~1~2분)
.venv/bin/python -m pytest tests/ -m image

# full lane (legacy drift — 현재 36 failing, W3~W5에서 정리)
.venv/bin/python -m pytest tests/ -m full

# 복수 선택 (W3 Exit 조건인 core+startup green)
.venv/bin/python -m pytest tests/ -m "core or startup"

# 전체 (pg 제외). pytest.ini의 addopts로 -m "not pg" 기본 적용.
.venv/bin/python -m pytest tests/

# PostgreSQL lane (별도 conftest_pg.py)
.venv/bin/python -m pytest tests/ -m pg
```

## Auto-marking 규칙

`backend/tests/conftest.py`의 `pytest_collection_modifyitems`에서 적용한다. 우선순위:

1. 테스트 함수/모듈에 이미 `@pytest.mark.<lane>`이 있으면 그 값을 유지. (명시 우선)
2. `tests/core/**`, `tests/services/**`, `tests/pipeline/**` 경로면 `core`.
3. 파일 stem이 `_STARTUP_STEMS` frozenset에 있으면 `startup`.
4. 파일 stem이 `_IMAGE_STEMS` frozenset에 있으면 `image`.
5. 그 외 루트 테스트는 `full`.

새 테스트 파일을 추가할 때는 `conftest.py` 상단의 frozenset에 등록하거나, 새 lane이면 `pytest.ini`와 함께 확장하자.

## Frontend 테스트 lane (W3-5 F32)

2026-04-22에 Vitest + React Testing Library harness를 도입했다. `frontend/vitest.config.ts`가 `vite.config.ts`를 재활용하고 jsdom 환경에서 실행.

```bash
cd frontend

# watch 모드
npm run test

# 단일 실행 (CI용)
npm run test:run
```

현재 smoke/hook 범위:

| 파일 | 종류 | 내용 |
|------|------|------|
| `src/pages/Dashboard.test.tsx` | smoke | useProjectList mock → 목록 렌더링 + 빈 목록 state |
| `src/hooks/api/mutations/useRunAllSteps.test.ts` | hook | /steps/run-all POST URL + category/mode 파라미터 + 에러 전파 |
| `src/hooks/api/mutations/useStillMutations.test.ts` | hook | recommend-variations / edit-angle / edit-color body+URL |

공용 유틸: `src/test-utils.tsx` — `createTestQueryClient`, `renderWithProviders`, `renderHookWithProviders`.

### 이월 (후속 세션)

- smoke 확장: `Episodes.tsx`, `EpisodeDetail.tsx`, `EpisodeStills.tsx` (Router context가 필요해 배선 추가 필요)
- hook 확장: 나머지 mutation/query 훅 — `useEpisodesProgress`, `useGenStatus`, `useProgress`, 등

## Gate 연결

- **G3 (Wave 3 Exit)**: `-m "core or startup"` 전체 green + F1-smoke/F2-hooks(frontend) smoke green.
- **G5 (Wave 5 Exit)**: `-m image` full green + `full` cluster D (image drift) 소화.
- **G6**: `-m full`도 green. pg lane은 CI 선택 적용.

## 연관 문서

- `docs/review-codex-1/11-fix-plan.md` §8 Wave 3 (F19 cluster + F32)
- `docs/architecture-refactor-final/test-plan.md` (초기 기준선)
- `docs/architecture/_step_manifest.generated.md` (manifest 기준선)
