fingu-tips KSEL 종합 리포트

4. 통합 테스트 스위트

PR #62 · 브랜치 test/comprehensive-kpi-integration · OPEN · 시험 후 머지

TL;DR

시험 D-1 시점에 운영 코드(src/kpi/*, src/pipelines/*, src/metrics/*)의 end-to-end 흐름과 API 진입점을 결정적 stub 모드 통합 테스트 23 개로 잠갔습니다. baseline 7 JSON 으로 회귀 감지, CI integration step 신설 (실패 시 차단). 운영 alpha 배포 흐름 영향 0.

신규 테스트23 (KPI 7 + API 16) baseline JSON7 3회 회귀100% pass 실행 시간1.3 초 외부 API0 변경+930 / -2 (20 files)

4.1 사전 점검에서 발견된 핵심 위험 3개

#위험영향대응
1기존 CI pytest ... \|\| true실패해도 CI 통과 → 새 테스트 깨져도 머지신규 integration step 추가 (\|\| true 미적용)
2KPI4 stub 10,000 sample × 60s × 5CI 30s timeout 초과통합테스트에서 evaluate(duration_sec=1, repeat=1) 축소 → 0.05 초
3KPI3/6 stub random.Random() 새 인스턴스score baseline 비교 false-positive해당 KPI baseline 은 schema · 메타만 잠금 (KPI4 패턴)

4.2 신설 파일 구조

tests/
├─ integration/
│  ├─ __init__.py
│  ├─ conftest.py            # baseline helper · RESULTS_DIR tmp · deterministic env
│  ├─ test_kpi1_e2e.py       # KPI ① 재무 F1
│  ├─ test_kpi2_e2e.py       # KPI ② 분류
│  ├─ test_kpi3_e2e.py       # KPI ③ BLEU
│  ├─ test_kpi4_e2e.py       # KPI ④ 처리속도 (축소 1s×1)
│  ├─ test_kpi5_e2e.py       # KPI ⑤ 개인화
│  ├─ test_kpi6_e2e.py       # KPI ⑥ NQ
│  ├─ test_kpi7_e2e.py       # KPI ⑦ 상품추천
│  └─ test_api_e2e.py        # TestClient — /api/health · /api/kpi · personas · sample
└─ baselines/
   ├─ kpi1_finance_qa.json                    # 5.7 KB · full result dict
   ├─ kpi2_text_classification.json           # 1.3 KB
   ├─ kpi3_translation.json                   # 0.09 KB (schema only)
   ├─ kpi4_throughput.json                    # 0.12 KB (schema + integrity)
   ├─ kpi5_personalized_recommendation.json   # 1.4 KB
   ├─ kpi6_finance_search.json                # 0.09 KB (schema only)
   └─ kpi7_product_recommendation.json        # 1.5 KB

4.3 통합 테스트 설계 원칙

4.4 baseline 비교 helper (conftest.py)

VOLATILE_KEYS = {
    "timestamp", "results_path",
    "elapsed_sec", "duration_sec", "duration_sec_actual",
}

def _strip_volatile(obj):
    # dict / list 재귀로 비결정 필드 제거 후 baseline 과 비교

def assert_baseline_match(result, baseline_name):
    cleaned = _strip_volatile(result)
    if not path.exists() or os.getenv("UPDATE_BASELINES") == "1":
        path.write_text(json.dumps(cleaned, ensure_ascii=False, indent=2, sort_keys=True))
        pytest.skip(...)
    expected = json.loads(path.read_text())
    assert cleaned == expected

4.5 CI 통합 step (.github/workflows/ci.yml)

- name: install
  run: |
    pip install -r requirements-test.txt
    pip install pytest-timeout
- name: compile check
  run: python -m compileall -q src api
- name: smoke import
  run: python -c "from src.api import app; print('routes:', len(app.routes))"
- name: pytest (unit only, fast)
  run: python -m pytest tests/ --ignore=tests/integration -x --tb=short -q --timeout=30 || true
- name: pytest (integration, blocking — baseline + API E2E)
  run: python -m pytest tests/integration/ -m integration --tb=short -q --timeout=120

기존 unit step 은 --ignore=tests/integration + || true 유지. 신설 integration step 은 실패 차단. detect-changes paths-filter 에 tests/**pytest.ini 추가.

4.6 회귀 검증

실행결과시간
1차 (UPDATE_BASELINES=1)23 skipped (baseline 생성)1.3 초
2차23 passed1.3 초
3차23 passed1.3 초
4차23 passed1.3 초
CI on PR #624 passed · 0 failed~1m

4.7 머지 정책

4.8 KSEL 검토 관점에서의 가치