o2o-negosium-original/negodata/docs/imk-test-coverage.md

69 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# IMK 요구사항 테스트 커버리지 (2026-07-24 실행)
IMK 요청 표(14~23) 항목별 **자동 테스트가 실제로 걸려 있는지**와, 이번에 돌린 실행 플로우를 정리한다.
결론부터: **자동 테스트가 있는 IMK 항목은 #15(공급사 재협상) 하나뿐**. 나머지는 UI·라벨·엑셀·스크립트 변경이라 전 스위트(회귀 안전망)만 통과할 뿐 항목 전용 테스트는 없다.
## 1. 실행한 테스트 스위트
| 스위트 | 실행 커맨드 | DB | 결과 |
|---|---|---|---|
| negodata 전체 | `APP_ENV=test .venv/bin/python -m pytest tests/` | 격리 test DB(negosium_test_db, 세션마다 재생성) | **83 passed / 1 failed** |
| 포털(negosium) 전체 | 컨테이너 `APP_ENV=local pytest tests/` | dev DB(negosium_db), 테스트가 자기 행만 시드/정리(비파괴) | **71 passed** |
| negodata #15 심사 | `pytest tests/test_renegotiation.py` | 격리 test DB | **9 passed** |
| 포털 #15 요청/철회 | 컨테이너 `pytest tests/test_renegotiation.py` | dev DB(자기정리, 잔여 0 확인) | **6 passed** |
- negodata 1 실패 = `test_scheduler::test_scheduler_registers_both_jobs` — 스케줄러에 `sync_lps_results` 잡이 새로 추가됐는데 단언을 안 고친 **stale 테스트**. IMK 항목과 무관.
- 포털은 로컬 venv가 없어 컨테이너에 pytest 임시 설치 후 실행. dev DB지만 `PYTESTRENEGO-`/`PYTESTNEGO-` 프리픽스로 자기 행만 지운다.
## 2. IMK 표(14~23) 항목별 커버리지
| # | 요구사항 | 자동 테스트 | 근거/플로우 |
|---|---|---|---|
| 14 | 발주배수 필드 추가 | ❌ 없음 | companies.settings 커스텀 필드. 전용 테스트 없음 |
| **15** | **공급사 재협상 요청 + 승인 화면** | ✅ **있음(15건)** | 포털 요청/철회 6 + negodata 심사 9. 아래 3절 |
| 16 | 통계 인상 억제율 지표 | ❌ 없음 | 통계 파생집계, 전용 테스트 없음 |
| 17 | 협력사 분류카테고리 추가 | ❌ 없음(간접만) | `test_quotation_create/anchoring`이 category 값을 쓰지만 분류 기능 자체 검증 아님 |
| 18 | 배송리드타임 → 표준납기일 | ❌ 없음 | 라벨 문자열 변경, 테스트 대상 아님 |
| 19 | 협력사 화면 구분 영역 삭제 | ❌ 없음 | 프론트 UI 제거, 테스트 대상 아님 |
| 20 | 실적(계약) 공급사 컬럼 추가 | ❌ 없음 | 상품 컬럼 추가, 전용 테스트 없음 |
| 21 | 스크립트 변수명 노출(internet_lowest_price) | ❌ 없음 | agent 스크립트 렌더 수정, 전용 테스트 없음 |
| 22 | 협상카드 일괄 선택 | ❌ 없음 | 프론트 UI, 테스트 대상 아님 |
| 23 | 상품 업로드 양식 수정 | ❌ 없음 | 엑셀 양식/컬럼, 전용 테스트 없음 |
정리: **10개 중 자동 테스트 보유는 1개(#15)**. 나머지 9개는 성격상(UI/라벨/엑셀/스크립트) 단위테스트 대상이 아니거나 아직 미작성 → 사람이 화면에서 확인해야 함.
## 3. #15 재협상 — 테스트별 검증 플로우
### 포털(negosium) — 요청/철회 (`backend/tests/test_renegotiation.py`, e2e HTTP)
개찰(OPEN_*) 마감 + 본인 마지막 라운드 세션을 시드하고 실제 로그인 → 엔드포인트 호출로 검증.
| 테스트 | 플로우 | 기대 |
|---|---|---|
| request_records_pending | 개찰건에 `POST .../renegotiation` | success + custom.renegotiation=PENDING(사유·희망가) + 담당자 알림 1건 |
| request_twice_blocked | 같은 세션에 요청 2회 | 2번째 거부, PENDING 1건 유지 |
| request_blocked_on_awarded | 낙찰(AWARDED)건에 요청 | 거부 + 미기록 |
| request_forbidden_other_supplier | 남의 공급사 세션에 요청 | 거부 + 미기록 |
| cancel_sets_canceled_and_allows_rerequest | 요청 후 `DELETE` 철회 → 재요청 | CANCELED → 재요청 시 PENDING |
| cancel_requires_pending | 대기 요청 없는데 철회 | 거부 |
### negodata — 심사(승인/반려) (`negodata/backend/tests/test_renegotiation.py`, 서비스 단위)
승인이 호출하는 `regenerate_quotation`(견적 풀체인)은 스텁으로 격리하고 #15 고유 계약만 검증.
| 테스트 | 플로우 | 기대 |
|---|---|---|
| list_scoped_to_company | 내 회사·남의 회사 요청 각 1건 → 목록 | 내 회사 건만(total=1) |
| list_filters_by_status | 대기·반려 각 1건 → status=1 필터 | 대기 건만 |
| approve_transitions_and_persists | 대기건 승인(재생성 성공 스텁) | APPROVED + next_quotation_id + memo 박제, 요청 공급사 포함 호출 |
| approve_includes_extra_suppliers | 승인 시 추가 공급사 지정 | 재생성 공급사 = 요청자 ∪ 추가(중복 제거) |
| approve_blocks_when_not_pending | 이미 승인된 건 재승인 | 거부(INVALID) + 재생성 미호출 |
| approve_keeps_pending_when_regenerate_fails | 재생성 실패 스텁 | 실패 반환 + 상태 PENDING 유지 |
| approve_other_company_not_found | 남의 회사 세션 승인(IDOR) | NOT_FOUND + 재생성 미호출 |
| reject_transitions_and_saves_memo | 대기건 반려(사유) | REJECTED + 반려사유 저장 |
| reject_blocks_when_not_pending | 이미 반려된 건 재반려 | 거부(INVALID) |
## 4. 미커버 항목에 대한 권고
- #14/#16/#17/#20/#23(데이터·집계·엑셀)은 서비스 단위 테스트를 붙일 수 있음 — 필요 시 작성.
- #18/#19/#22(라벨·UI)와 #21(스크립트 렌더)은 화면·실협상으로 확인하는 게 맞음.
- #15는 "승인 → 실제 다음 라운드 견적이 올바른 상품/카드로 생성되는지"는 스텁으로 끊었으므로, 실 데이터 승인 1회로 최종 확인 필요.