G-1: 메신저 Webhook Relay + _send_to_room 실제 httpx 호출 구현 G-2: POST /api/tasks/bulk SR 대량작업 엔드포인트 (최대 100건) G-3: 라이선스 만료 알림 스케줄러 (매일 09:00 KST) G-4: 체험판 upgrade_banner 필드 + license.py 배너 로직 G-5: core/auto_rca.py + incidents/problem auto-rca 엔드포인트 G-6: core/deploy_impact.py + vibe impact-analysis 엔드포인트 G-7: core/ticket_classifier.py + SR 생성 시 AI 분류 + ai-suggestion API G-8: VulnPatchRecord 모델 + vuln_scan 패치추적 4개 엔드포인트 G-9: core/jira_sync.py + gateway Jira/Confluence 연동 엔드포인트 G-10: core/push_notify.py + routers/push.py + PushSubscription 모델 G-11: approvals 다중승인 (위임/서명/기한초과/마감연장) G-12: alembic.ini + migrations/ + cicd/migrate_to_postgres.sh 하네스: guardia-orchestrator 확장기능 Phase 반영 봇명령어: /sr /status /license /bulk 슬래시 명령어 추가 설치스크립트: setup/ (Ubuntu, CentOS, RHEL, Windows) --test 옵션 포함 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
594 lines
20 KiB
Markdown
594 lines
20 KiB
Markdown
# GUARDiA ITSM + Messenger — 단위·통합 테스트 계획서
|
|
|
|
**문서 버전**: 1.0
|
|
**작성일**: 2026-05-25
|
|
**대상 시스템**: GUARDiA ITSM v1.0, GUARDiA Messenger v1.0
|
|
|
|
---
|
|
|
|
## 목차
|
|
|
|
1. [개요](#1-개요)
|
|
2. [테스트 범위 및 전략](#2-테스트-범위-및-전략)
|
|
3. [테스트 환경](#3-테스트-환경)
|
|
4. [단위 테스트 계획](#4-단위-테스트-계획)
|
|
5. [통합 테스트 계획](#5-통합-테스트-계획)
|
|
6. [비기능 테스트 계획](#6-비기능-테스트-계획)
|
|
7. [테스트 케이스 목록](#7-테스트-케이스-목록)
|
|
8. [결함 관리](#8-결함-관리)
|
|
9. [완료 기준](#9-완료-기준)
|
|
|
|
---
|
|
|
|
## 1. 개요
|
|
|
|
### 1.1 목적
|
|
|
|
본 문서는 GUARDiA ITSM 및 GUARDiA Messenger 시스템의 품질 보증을 위한 단위 테스트 및 통합 테스트 계획을 정의한다. 개별 컴포넌트의 정확성 검증(단위)과 컴포넌트 간 상호작용 검증(통합)을 통해 출시 전 결함을 조기에 발견하고 수정한다.
|
|
|
|
### 1.2 테스트 대상
|
|
|
|
| 구분 | 대상 모듈 |
|
|
|------|-----------|
|
|
| ITSM 코어 | auth, dashboard, tasks, approvals, audit, cmdb |
|
|
| ITSM 운영 | ssl_manager, pm, incidents, oncall, batch |
|
|
| ITSM 지원 | kb, shell_scripts, ssh, attachments, notifications |
|
|
| ITSM 고객 | rating, institutions, timetable, work |
|
|
| Messenger | bot dispatcher, GUARDiA_ITSM bot, command handlers |
|
|
| 공통 | scheduler, seed, database, JWT auth |
|
|
|
|
### 1.3 테스트 유형 정의
|
|
|
|
- **단위 테스트(Unit Test)**: 함수/클래스 단위의 독립 검증. 외부 의존성은 mock 처리.
|
|
- **통합 테스트(Integration Test)**: DB·Redis·SSH·Messenger 등 실제 의존성과의 연동 검증.
|
|
- **E2E 시나리오 테스트**: 사용자 시나리오 전 구간 검증 (API 호출 → DB 저장 → 알림 발송).
|
|
|
|
---
|
|
|
|
## 2. 테스트 범위 및 전략
|
|
|
|
### 2.1 단위 테스트 범위
|
|
|
|
```
|
|
범위 내 (In Scope)
|
|
├── 모든 라우터 엔드포인트 (130개 API)
|
|
├── core/scheduler.py — 스케줄 함수
|
|
├── core/seed.py — 시드 데이터 생성
|
|
├── utils/crypto.py — AES-256-GCM 암/복호화
|
|
├── utils/ssh_runner.py — SSH 명령 검증
|
|
└── schemas/*.py — Pydantic 직렬화/역직렬화
|
|
|
|
범위 외 (Out of Scope)
|
|
├── 3rd party 라이브러리 내부 (FastAPI, SQLAlchemy)
|
|
└── OS 수준 시스템 콜
|
|
```
|
|
|
|
### 2.2 통합 테스트 범위
|
|
|
|
```
|
|
범위 내
|
|
├── ITSM API ↔ SQLite DB 연동
|
|
├── ITSM API ↔ GUARDiA Messenger 알림
|
|
├── SSH 실행 → 원격 서버 응답 처리
|
|
├── SSL 점검 스크립트 → JSON 파싱
|
|
├── 스케줄러 → DB 변경 → 알림 체인
|
|
└── PM 스케줄 → WorkTimetable 자동 생성
|
|
|
|
범위 외
|
|
├── 외부 LLM API (완전 금지)
|
|
├── 실제 고객 운영 서버 대상 SSH
|
|
└── 이메일/SMS 외부 발송
|
|
```
|
|
|
|
### 2.3 테스트 전략
|
|
|
|
- **TDD 기반**: 핵심 비즈니스 로직은 테스트 먼저 작성
|
|
- **AAA 패턴**: Arrange → Act → Assert
|
|
- **픽스처 격리**: 각 테스트는 독립 SQLite in-memory DB 사용
|
|
- **커버리지 목표**: 단위 80% 이상, 통합 70% 이상
|
|
|
|
---
|
|
|
|
## 3. 테스트 환경
|
|
|
|
### 3.1 단위 테스트 환경
|
|
|
|
```
|
|
OS: 동일 (Linux/Windows 무관)
|
|
Python: 3.11+
|
|
프레임워크: pytest 8.x + pytest-asyncio
|
|
Mock: unittest.mock, respx (httpx mock)
|
|
DB: SQLite in-memory (aiosqlite)
|
|
의존성: requirements-dev.txt 참조
|
|
```
|
|
|
|
**requirements-dev.txt**:
|
|
```
|
|
pytest>=8.0
|
|
pytest-asyncio>=0.23
|
|
pytest-cov>=5.0
|
|
httpx>=0.27 # TestClient
|
|
respx>=0.21 # httpx mock
|
|
faker>=25.0 # 테스트 데이터
|
|
freezegun>=1.4 # 시간 고정
|
|
```
|
|
|
|
### 3.2 통합 테스트 환경
|
|
|
|
```
|
|
OS: Ubuntu 22.04 LTS (권장) 또는 Windows Server 2022
|
|
Python: 3.11+
|
|
DB: SQLite 파일 기반 (테스트 전용)
|
|
Messenger: 테스트 채널 (별도 구성)
|
|
SSH 대상: localhost SSH 서버 (테스트 전용)
|
|
```
|
|
|
|
### 3.3 디렉토리 구조
|
|
|
|
```
|
|
C:\GUARDiA\itsm\
|
|
└── tests\
|
|
├── conftest.py # 공통 픽스처
|
|
├── unit\
|
|
│ ├── test_auth.py
|
|
│ ├── test_tasks.py
|
|
│ ├── test_ssl_manager.py
|
|
│ ├── test_pm.py
|
|
│ ├── test_incidents.py
|
|
│ ├── test_oncall.py
|
|
│ ├── test_batch.py
|
|
│ ├── test_scheduler.py
|
|
│ └── test_crypto.py
|
|
└── integration\
|
|
├── test_sr_workflow.py
|
|
├── test_approval_chain.py
|
|
├── test_pm_workflow.py
|
|
├── test_incident_workflow.py
|
|
└── test_notification_chain.py
|
|
```
|
|
|
|
---
|
|
|
|
## 4. 단위 테스트 계획
|
|
|
|
### 4.1 conftest.py 공통 픽스처
|
|
|
|
```python
|
|
# tests/conftest.py
|
|
import pytest
|
|
import pytest_asyncio
|
|
from httpx import AsyncClient, ASGITransport
|
|
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
|
|
from sqlalchemy.orm import sessionmaker
|
|
from database import Base, get_db
|
|
from main import app
|
|
|
|
TEST_DB = "sqlite+aiosqlite:///:memory:"
|
|
|
|
@pytest_asyncio.fixture
|
|
async def db_session():
|
|
engine = create_async_engine(TEST_DB)
|
|
async with engine.begin() as conn:
|
|
await conn.run_sync(Base.metadata.create_all)
|
|
SessionLocal = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
|
|
async with SessionLocal() as session:
|
|
yield session
|
|
async with engine.begin() as conn:
|
|
await conn.run_sync(Base.metadata.drop_all)
|
|
|
|
@pytest_asyncio.fixture
|
|
async def client(db_session):
|
|
app.dependency_overrides[get_db] = lambda: db_session
|
|
async with AsyncClient(
|
|
transport=ASGITransport(app=app), base_url="http://test"
|
|
) as ac:
|
|
yield ac
|
|
app.dependency_overrides.clear()
|
|
|
|
@pytest_asyncio.fixture
|
|
async def auth_headers(client):
|
|
r = await client.post("/auth/login", json={"username":"admin","password":"admin1234!"})
|
|
token = r.json()["access_token"]
|
|
return {"Authorization": f"Bearer {token}"}
|
|
```
|
|
|
|
### 4.2 인증 모듈 (auth) 단위 테스트
|
|
|
|
**파일**: `tests/unit/test_auth.py`
|
|
|
|
| 테스트 ID | 테스트명 | 설명 | 기대 결과 |
|
|
|-----------|----------|------|-----------|
|
|
| UT-AUTH-001 | 정상 로그인 | 올바른 계정으로 로그인 | 200 + access_token 반환 |
|
|
| UT-AUTH-002 | 잘못된 비밀번호 | 틀린 비밀번호 시도 | 401 Unauthorized |
|
|
| UT-AUTH-003 | 존재하지 않는 계정 | 없는 사용자명 | 401 Unauthorized |
|
|
| UT-AUTH-004 | 비밀번호 변경 | 현재 PW 확인 후 변경 | 200 + message |
|
|
| UT-AUTH-005 | JWT 토큰 만료 | 만료된 토큰으로 API 호출 | 401 Unauthorized |
|
|
| UT-AUTH-006 | RBAC — CUSTOMER 권한 제한 | CUSTOMER가 admin API 호출 | 403 Forbidden |
|
|
| UT-AUTH-007 | RBAC — ENGINEER 권한 | ENGINEER가 SR 처리 | 200 OK |
|
|
| UT-AUTH-008 | 빈 토큰 | Authorization 헤더 없음 | 401 Unauthorized |
|
|
|
|
```python
|
|
# 예시 테스트 코드
|
|
@pytest.mark.asyncio
|
|
async def test_login_success(client, db_session):
|
|
# Arrange: seed admin user
|
|
from core.seed import seed_all
|
|
await seed_all(db_session)
|
|
# Act
|
|
r = await client.post("/auth/login", json={"username":"admin","password":"admin1234!"})
|
|
# Assert
|
|
assert r.status_code == 200
|
|
data = r.json()
|
|
assert "access_token" in data
|
|
assert data["token_type"] == "bearer"
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_login_wrong_password(client, db_session):
|
|
from core.seed import seed_all
|
|
await seed_all(db_session)
|
|
r = await client.post("/auth/login", json={"username":"admin","password":"wrong!"})
|
|
assert r.status_code == 401
|
|
```
|
|
|
|
### 4.3 SR 처리 (tasks) 단위 테스트
|
|
|
|
| 테스트 ID | 테스트명 | 기대 결과 |
|
|
|-----------|----------|-----------|
|
|
| UT-TASK-001 | SR 생성 (INCIDENT 유형) | 201 + sr_id 반환 |
|
|
| UT-TASK-002 | SR 생성 (CHANGE 유형) | 201 + sr_id 반환 |
|
|
| UT-TASK-003 | SR 목록 페이징 | 200 + items/total 구조 |
|
|
| UT-TASK-004 | SR 상태 변경 OPEN→IN_PROGRESS | 200 + 상태 업데이트 |
|
|
| UT-TASK-005 | SR 상태 — 잘못된 전환 | 400 Bad Request |
|
|
| UT-TASK-006 | SR 첨부파일 업로드 | 201 + file_id |
|
|
| UT-TASK-007 | SR 첨부파일 경로 순회 방지 | 400 Bad Request |
|
|
| UT-TASK-008 | 고객(CUSTOMER) SR 자기 것만 조회 | 200 + 본인 SR만 |
|
|
| UT-TASK-009 | SR 검색 (제목 키워드) | 200 + 필터 결과 |
|
|
| UT-TASK-010 | SR 만족도 평가 | 200 + rating 저장 |
|
|
|
|
### 4.4 SSL 관리 (ssl_manager) 단위 테스트
|
|
|
|
| 테스트 ID | 테스트명 | 기대 결과 |
|
|
|-----------|----------|-----------|
|
|
| UT-SSL-001 | SSL 도메인 등록 | 201 + ssl_id |
|
|
| UT-SSL-002 | 중복 도메인 등록 | 409 Conflict |
|
|
| UT-SSL-003 | SSL 즉시 점검 — 정상 응답 파싱 | 200 + days_left 계산 |
|
|
| UT-SSL-004 | SSL 즉시 점검 — SSH 실패 시 | 200 + error_msg 기록 |
|
|
| UT-SSL-005 | 만료 임박 알림 등급 (EXPIRED ≤0) | level=EXPIRED |
|
|
| UT-SSL-006 | 만료 임박 알림 등급 (URGENT ≤7) | level=URGENT |
|
|
| UT-SSL-007 | 만료 임박 알림 등급 (WARN ≤30) | level=WARN |
|
|
| UT-SSL-008 | 정상 인증서 (>30일) | level=OK |
|
|
| UT-SSL-009 | SSL 수동 갱신 완료 기록 | 200 + renewed_at 업데이트 |
|
|
| UT-SSL-010 | SSL 도메인 삭제 | 204 No Content |
|
|
|
|
### 4.5 PM 정기점검 (pm) 단위 테스트
|
|
|
|
| 테스트 ID | 테스트명 | 기대 결과 |
|
|
|-----------|----------|-----------|
|
|
| UT-PM-001 | PM 템플릿 생성 | 201 + template_id |
|
|
| UT-PM-002 | PM 템플릿 목록 조회 | 200 + 카테고리별 목록 |
|
|
| UT-PM-003 | PM 스케줄 생성 (MONTHLY) | 201 + next_scheduled 계산 |
|
|
| UT-PM-004 | PM 스케줄 생성 (WEEKLY) | 201 + 7일 후 next_scheduled |
|
|
| UT-PM-005 | PM 스케줄 생성 (QUARTERLY) | 201 + 90일 후 next_scheduled |
|
|
| UT-PM-006 | PM 작업 생성 (WorkTimetable 연동) | 201 + timetable_id |
|
|
| UT-PM-007 | PM 결과 저장 — PASS | 200 + result=PASS |
|
|
| UT-PM-008 | PM 결과 저장 — FAIL (비고 필수) | 400 if note 없음 |
|
|
| UT-PM-009 | PM 완료 처리 | 200 + completed_at 기록 |
|
|
| UT-PM-010 | PM Excel 보고서 다운로드 | 200 + Content-Type: xlsx |
|
|
| UT-PM-011 | next_scheduled 계산 — MONTHLY 말일 | 말일 처리 정확성 |
|
|
| UT-PM-012 | PM 템플릿 소프트 삭제 | 200 + is_active=False |
|
|
|
|
### 4.6 장애 관리 (incidents) 단위 테스트
|
|
|
|
| 테스트 ID | 테스트명 | 기대 결과 |
|
|
|-----------|----------|-----------|
|
|
| UT-INC-001 | 장애 생성 (P1) | 201 + INC-YYYYMMDD-XXXXXX 형식 |
|
|
| UT-INC-002 | 장애 생성 (P4) | 201 + 알림 없음 |
|
|
| UT-INC-003 | P1/P2 생성 → Messenger 알림 | 알림 함수 호출 확인 (mock) |
|
|
| UT-INC-004 | 상태 전환 OPEN→INVESTIGATING | 200 + 타임라인 기록 |
|
|
| UT-INC-005 | 잘못된 상태 전환 CLOSED→OPEN | 400 Bad Request |
|
|
| UT-INC-006 | 장애 타임라인 조회 | 200 + events 목록 |
|
|
| UT-INC-007 | 장애 종결 (RCA 필수) | 400 if rca 없음 |
|
|
| UT-INC-008 | 장애 목록 — P1 필터 | 200 + P1 only |
|
|
| UT-INC-009 | 장애 통계 (기간별) | 200 + count by priority |
|
|
| UT-INC-010 | 장애 SR 연동 | 200 + related_sr_ids 업데이트 |
|
|
|
|
### 4.7 온콜/당직 (oncall) 단위 테스트
|
|
|
|
| 테스트 ID | 테스트명 | 기대 결과 |
|
|
|-----------|----------|-----------|
|
|
| UT-OC-001 | 당직 단건 등록 | 201 + duty_id |
|
|
| UT-OC-002 | 중복 당직 등록 (같은 날+교대) | 409 Conflict |
|
|
| UT-OC-003 | 당직 일괄 등록 (최대 62건) | 201 + count |
|
|
| UT-OC-004 | 당직 일괄 — 초과 (63건) | 422 Validation Error |
|
|
| UT-OC-005 | 오늘 당직 조회 | 200 + 교대별 그룹 |
|
|
| UT-OC-006 | 월별 당직 조회 | 200 + 해당 월 목록 |
|
|
| UT-OC-007 | 당직 삭제 | 204 No Content |
|
|
|
|
### 4.8 배치 작업 (batch) 단위 테스트
|
|
|
|
| 테스트 ID | 테스트명 | 기대 결과 |
|
|
|-----------|----------|-----------|
|
|
| UT-BAT-001 | 배치 작업 생성 | 201 + batch_id |
|
|
| UT-BAT-002 | 위험 명령 차단 (rm -rf /) | 400 Bad Request |
|
|
| UT-BAT-003 | 위험 명령 차단 (shutdown) | 400 Bad Request |
|
|
| UT-BAT-004 | 위험 명령 차단 (fork bomb) | 400 Bad Request |
|
|
| UT-BAT-005 | 배치 수동 실행 요청 | 202 Accepted |
|
|
| UT-BAT-006 | 배치 실행 이력 조회 | 200 + runs 목록 |
|
|
| UT-BAT-007 | 배치 실패 시 SR 자동 생성 | SR 생성 확인 (mock) |
|
|
| UT-BAT-008 | 비활성 배치 스케줄 — 실행 안 함 | is_active=False 체크 |
|
|
| UT-BAT-009 | 배치 작업 삭제 | 204 No Content |
|
|
| UT-BAT-010 | TIMEOUT 처리 (asyncio timeout) | 실행 상태=TIMEOUT |
|
|
|
|
### 4.9 암호화 유틸 단위 테스트
|
|
|
|
| 테스트 ID | 테스트명 | 기대 결과 |
|
|
|-----------|----------|-----------|
|
|
| UT-CRYPTO-001 | AES-256-GCM 암호화/복호화 왕복 | 원문 복원 성공 |
|
|
| UT-CRYPTO-002 | 서로 다른 평문 → 다른 암호문 | 결정론적 아님 확인 |
|
|
| UT-CRYPTO-003 | 잘못된 키로 복호화 | 예외 발생 |
|
|
| UT-CRYPTO-004 | 빈 문자열 암호화 | 정상 처리 |
|
|
| UT-CRYPTO-005 | 한국어 포함 문자열 암호화 | UTF-8 왕복 성공 |
|
|
|
|
### 4.10 스케줄러 단위 테스트
|
|
|
|
```python
|
|
# tests/unit/test_scheduler.py
|
|
import pytest
|
|
from datetime import datetime
|
|
from freezegun import freeze_time
|
|
from core.scheduler import _calc_next
|
|
from models import PmSchedule, PmFrequency
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_calc_next_weekly():
|
|
with freeze_time("2026-01-01"):
|
|
sched = PmSchedule(frequency=PmFrequency.WEEKLY)
|
|
result = _calc_next(sched, datetime(2026, 1, 1))
|
|
assert result == datetime(2026, 1, 8)
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_calc_next_monthly_end_of_month():
|
|
# 1월 31일에서 +1달 → 2월 28일 (말일 처리)
|
|
sched = PmSchedule(frequency=PmFrequency.MONTHLY, day_of_month=31)
|
|
result = _calc_next(sched, datetime(2026, 1, 31))
|
|
assert result.day == 28 # 2026년 2월 말일
|
|
```
|
|
|
|
---
|
|
|
|
## 5. 통합 테스트 계획
|
|
|
|
### 5.1 SR 처리 전체 워크플로우
|
|
|
|
**시나리오**: 고객 SR 접수 → 담당자 배정 → 처리 → 완료 → 만족도 평가
|
|
|
|
```
|
|
TC-INT-SR-001: SR 접수부터 완료까지 전체 흐름
|
|
1. POST /tasks/ — SR 생성 (CUSTOMER 역할)
|
|
2. GET /tasks/{id} — 생성 확인
|
|
3. PATCH /assign/{sr_id} — 담당자 배정 (PM 역할)
|
|
4. PATCH /tasks/{id}/status — IN_PROGRESS 전환
|
|
5. POST /work/ — 처리 내역 등록
|
|
6. PATCH /tasks/{id}/status — RESOLVED 전환
|
|
7. POST /rating/ — 만족도 5점 등록
|
|
8. GET /dashboard/summary — 통계 반영 확인
|
|
|
|
기대 결과: 전 단계 성공, 최종 SR 상태=RESOLVED, rating=5
|
|
```
|
|
|
|
### 5.2 결재 워크플로우
|
|
|
|
**시나리오**: CHANGE 유형 SR → 결재 요청 → 승인 → 실행
|
|
|
|
```
|
|
TC-INT-APV-001: 결재 승인 워크플로우
|
|
1. POST /tasks/ — CHANGE SR 생성
|
|
2. POST /approvals/ — 결재 요청 (결재자 2단계 설정)
|
|
3. PATCH /approvals/{id}/approve — 1단계 승인
|
|
4. PATCH /approvals/{id}/approve — 2단계 승인
|
|
5. GET /tasks/{sr_id} — SR 상태 = APPROVED 확인
|
|
6. PATCH /tasks/{id}/status — IMPLEMENTING 전환
|
|
|
|
TC-INT-APV-002: 결재 거부 워크플로우
|
|
1. POST /tasks/ + POST /approvals/
|
|
2. PATCH /approvals/{id}/reject — 거부 (사유 필수)
|
|
3. GET /tasks/{sr_id} — SR 상태 = REJECTED 확인
|
|
```
|
|
|
|
### 5.3 PM 정기점검 워크플로우
|
|
|
|
```
|
|
TC-INT-PM-001: PM 스케줄 → 자동 작업 생성
|
|
1. POST /pm/templates/ — 체크리스트 템플릿 생성
|
|
2. POST /pm/schedules/ — MONTHLY 스케줄 등록
|
|
3. (스케줄러 _auto_generate_pm 함수 직접 호출)
|
|
4. GET /timetable/ — WorkTimetable 생성 확인
|
|
5. GET /pm/works/{id} — PM 작업 목록 확인
|
|
|
|
TC-INT-PM-002: PM 결과 저장 및 Excel 보고서
|
|
1. (PM 작업 생성 선행)
|
|
2. POST /pm/works/{id}/results — 각 항목 PASS/FAIL 저장
|
|
3. PATCH /pm/works/{id}/complete — 완료 처리
|
|
4. GET /pm/works/{id}/report — Excel 다운로드
|
|
5. openpyxl로 파일 열기 → PASS/FAIL 색상 확인
|
|
```
|
|
|
|
### 5.4 장애 처리 워크플로우
|
|
|
|
```
|
|
TC-INT-INC-001: P1 장애 발생 → 처리 → 종결
|
|
1. POST /incidents/ — P1 장애 등록
|
|
→ Messenger 알림 mock 확인
|
|
2. POST /incidents/{id}/timeline — "장애 감지 완료" 기록
|
|
3. PATCH /incidents/{id}/status — INVESTIGATING
|
|
4. PATCH /incidents/{id}/status — MITIGATED (조치 내역 포함)
|
|
5. PATCH /incidents/{id}/status — RESOLVED (임시 해결)
|
|
6. POST /incidents/{id}/close — RCA 문서 포함 종결
|
|
7. GET /incidents/{id} — 전체 타임라인 확인
|
|
```
|
|
|
|
### 5.5 배치 실행 및 실패 알림
|
|
|
|
```
|
|
TC-INT-BAT-001: 배치 실행 실패 → SR 자동 생성
|
|
1. POST /batch/jobs — 의도적 실패 명령으로 배치 등록
|
|
(예: "exit 1" 명령)
|
|
2. POST /batch/jobs/{id}/run — 수동 실행
|
|
3. (BackgroundTask 완료 대기)
|
|
4. GET /batch/jobs/{id}/runs — 상태 = FAILED 확인
|
|
5. GET /tasks/ — 자동 생성된 SR 확인 (sr_type=LOG, priority=HIGH)
|
|
```
|
|
|
|
### 5.6 Messenger 알림 통합 테스트
|
|
|
|
```
|
|
TC-INT-MSG-001: ITSM 이벤트 → Messenger 채널 발송
|
|
1. mock Messenger API (respx)
|
|
2. P1 장애 생성 → /incidents/ POST
|
|
3. respx 캡처된 요청에서 채널 ID, 메시지 내용 검증
|
|
4. 메시지에 incident_id, priority, title 포함 확인
|
|
5. 서버 IP/비밀번호 미포함 확인 (보안)
|
|
|
|
TC-INT-MSG-002: Bot 명령 처리
|
|
1. POST /messenger/webhook — "/itsm sr list" 명령
|
|
2. 응답 메시지에 SR 목록 포함 확인
|
|
3. POST /messenger/webhook — "/itsm help"
|
|
4. 응답 메시지에 명령어 목록 확인
|
|
```
|
|
|
|
---
|
|
|
|
## 6. 비기능 테스트 계획
|
|
|
|
### 6.1 성능 테스트
|
|
|
|
| 항목 | 목표 | 측정 방법 |
|
|
|------|------|-----------|
|
|
| API 응답 시간 (평균) | ≤ 500ms | locust or k6 |
|
|
| API 응답 시간 (P99) | ≤ 2000ms | locust or k6 |
|
|
| 동시 사용자 | 50명 이상 정상 처리 | locust 동시 접속 |
|
|
| DB 트랜잭션 | 100 TPS 이상 | pytest-benchmark |
|
|
| 파일 업로드 | 10MB 이하 ≤ 3초 | httpx 직접 테스트 |
|
|
|
|
### 6.2 보안 테스트
|
|
|
|
| 항목 | 테스트 방법 | 기대 결과 |
|
|
|------|------------|-----------|
|
|
| SQL 인젝션 | 검색 파라미터에 SQL 구문 주입 | 에러 없이 빈 결과 |
|
|
| XSS | SR 제목에 `<script>alert(1)</script>` | HTML 이스케이프 |
|
|
| JWT 위조 | 임의 서명 토큰 사용 | 401 |
|
|
| 경로 순회 | `../../../etc/passwd` 첨부파일 | 400 |
|
|
| SSH 명령 인젝션 | `; rm -rf /` 포함 명령 | 400 |
|
|
| 서버 정보 노출 | API 응답에 IP/PW 포함 여부 | 미포함 확인 |
|
|
| 스택트레이스 노출 | 의도적 오류 발생 | SR ID + 요약만 반환 |
|
|
|
|
### 6.3 감사 로그 무결성 테스트
|
|
|
|
```
|
|
TC-AUDIT-001: 해시 체인 무결성
|
|
1. 여러 감사 로그 생성 (API 호출 10회)
|
|
2. GET /audit/logs — 전체 조회
|
|
3. 각 로그의 prev_hash → 이전 로그 hash 일치 확인
|
|
4. DB에서 중간 로그 직접 수정
|
|
5. GET /audit/verify — 무결성 깨짐 감지 확인
|
|
```
|
|
|
|
---
|
|
|
|
## 7. 테스트 케이스 목록 요약
|
|
|
|
| 모듈 | 단위 TC | 통합 TC | 합계 |
|
|
|------|---------|---------|------|
|
|
| auth | 8 | 2 | 10 |
|
|
| tasks/SR | 10 | 4 | 14 |
|
|
| approvals | 6 | 3 | 9 |
|
|
| ssl_manager | 10 | 2 | 12 |
|
|
| pm | 12 | 3 | 15 |
|
|
| incidents | 10 | 2 | 12 |
|
|
| oncall | 7 | 1 | 8 |
|
|
| batch | 10 | 2 | 12 |
|
|
| scheduler | 6 | 2 | 8 |
|
|
| crypto/security | 5 | 3 | 8 |
|
|
| messenger | 4 | 3 | 7 |
|
|
| audit | 4 | 2 | 6 |
|
|
| **합계** | **92** | **29** | **121** |
|
|
|
|
---
|
|
|
|
## 8. 결함 관리
|
|
|
|
### 8.1 결함 등급
|
|
|
|
| 등급 | 정의 | 처리 기한 |
|
|
|------|------|-----------|
|
|
| Critical | 시스템 중단, 데이터 손실, 보안 취약점 | 즉시 (24시간 내) |
|
|
| Major | 핵심 기능 비정상, 결과 오류 | 3일 내 |
|
|
| Minor | 비핵심 기능 문제, UI 오류 | 7일 내 |
|
|
| Trivial | 오타, 경미한 표시 오류 | 다음 버전 |
|
|
|
|
### 8.2 결함 생명주기
|
|
|
|
```
|
|
NEW → ASSIGNED → IN_PROGRESS → FIXED → VERIFIED → CLOSED
|
|
↓
|
|
REOPENED (재현 시)
|
|
```
|
|
|
|
### 8.3 결함 보고서 양식
|
|
|
|
```
|
|
결함 ID: BUG-YYYY-NNN
|
|
제목: [모듈] 결함 요약
|
|
심각도: Critical/Major/Minor/Trivial
|
|
재현 단계:
|
|
1. ...
|
|
2. ...
|
|
실제 결과: ...
|
|
기대 결과: ...
|
|
스크린샷/로그: (첨부)
|
|
발견일: YYYY-MM-DD
|
|
발견자: ...
|
|
```
|
|
|
|
---
|
|
|
|
## 9. 완료 기준
|
|
|
|
### 9.1 단계별 완료 기준
|
|
|
|
**단위 테스트 완료**:
|
|
- [ ] 모든 단위 TC 실행 완료
|
|
- [ ] 코드 커버리지 80% 이상
|
|
- [ ] Critical/Major 결함 0건
|
|
|
|
**통합 테스트 완료**:
|
|
- [ ] 모든 통합 시나리오 TC 실행 완료
|
|
- [ ] 주요 워크플로우 E2E 검증 완료
|
|
- [ ] Critical/Major 결함 0건
|
|
|
|
**보안 테스트 완료**:
|
|
- [ ] 보안 TC 전 항목 통과
|
|
- [ ] API 응답에 민감 정보 미포함 확인
|
|
- [ ] 감사 로그 무결성 확인
|
|
|
|
### 9.2 테스트 실행 명령
|
|
|
|
```bash
|
|
# 전체 단위 테스트
|
|
cd C:\GUARDiA\itsm
|
|
pytest tests/unit/ -v --cov=. --cov-report=html
|
|
|
|
# 통합 테스트
|
|
pytest tests/integration/ -v --timeout=30
|
|
|
|
# 특정 모듈
|
|
pytest tests/unit/test_incidents.py -v
|
|
|
|
# 커버리지 HTML 보고서 확인
|
|
open htmlcov/index.html
|
|
```
|
|
|
|
---
|
|
|
|
*본 테스트 계획서는 GUARDiA ITSM v1.0 기준으로 작성되었으며, 버전 업그레이드 시 갱신이 필요합니다.*
|