forked from baron/baron-sso
test corverage 관련 작업 문서화
This commit is contained in:
147
docs/backend_hydra_test_guide.md
Normal file
147
docs/backend_hydra_test_guide.md
Normal file
@@ -0,0 +1,147 @@
|
||||
# Backend Hydra Test Guide
|
||||
|
||||
이 문서는 Baron SSO 백엔드 내에서 **Ory Hydra Admin API**와 연동되는 기능(`HydraAdminService`)을 테스트하는 방법과 커버리지 측정 방법을 설명합니다.
|
||||
|
||||
## 1. 테스트 개요
|
||||
|
||||
백엔드는 OAuth2 클라이언트 관리, 인증/동의(Consent) 요청 승인 등을 위해 Ory Hydra의 Admin API를 호출합니다.
|
||||
본 테스트 가이드는 `httptest` 패키지와 Mocking을 활용하여 실제 Hydra 서버 없이 백엔드의 연동 로직을 빠르고 독립적으로 검증하는 방법을 다룹니다.
|
||||
(주의: 본 가이드는 관리자용 UI인 `adminfront` 테스트가 아닌, 백엔드 내부의 API 연동 코드 테스트를 다룹니다.)
|
||||
|
||||
## 2. 테스트 환경 준비
|
||||
|
||||
테스트는 Go 언어의 표준 테스팅 프레임워크를 사용하므로 별도의 설치가 필요 없으나, 커버리지 확인을 위해 `backend/` 디렉토리에서 작업을 수행해야 합니다.
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
```
|
||||
|
||||
## 3. 테스트 파일 목록 및 실행 방법
|
||||
|
||||
작성된 Hydra 관련 테스트 코드는 크게 3가지 파일로 나뉩니다.
|
||||
|
||||
### 3.1. HydraAdminService (백엔드 내부 서비스) 테스트
|
||||
백엔드 내부에서 Ory Hydra Admin API와 통신하는 최하단 로직(클라이언트 관리, OIDC 흐름, 세션 관리)을 검증합니다.
|
||||
|
||||
* **위치:** `backend/internal/service/hydra_admin_service_test.go`
|
||||
* **실행:**
|
||||
```bash
|
||||
go test -v ./internal/service -run TestHydraAdminService
|
||||
```
|
||||
|
||||
### 3.2. Relying Party Service 테스트
|
||||
`HydraAdminService`와 로컬 DB(RelyingParty) 간의 통합 및 롤백 로직을 검증합니다.
|
||||
|
||||
* **위치:** `backend/internal/service/relying_party_service_test.go`
|
||||
* **실행:**
|
||||
```bash
|
||||
go test -v ./internal/service -run TestRelyingPartyService
|
||||
```
|
||||
|
||||
### 3.3. Auth Handler 로그인 테스트
|
||||
로그인 요청 시 백엔드 핸들러 레벨에서 발생하는 OIDC/Hydra 흐름(Login Challenge 처리 등)을 검증합니다.
|
||||
|
||||
* **위치:** `backend/internal/handler/auth_handler_login_test.go`
|
||||
* **실행:**
|
||||
```bash
|
||||
go test -v ./internal/handler -run TestPasswordLogin
|
||||
```
|
||||
|
||||
### 3.4. 전체 테스트 실행 (권장)
|
||||
모든 Hydra 관련 연동 테스트를 한 번에 실행하려면 다음 명령어를 사용합니다.
|
||||
|
||||
```bash
|
||||
go test -v ./internal/service ./internal/handler -run "TestHydraAdminService|TestRelyingPartyService|TestPasswordLogin"
|
||||
```
|
||||
|
||||
## 4. 테스트 커버리지 측정
|
||||
|
||||
테스트가 코드의 어느 부분을 검증했는지 수치로 확인합니다.
|
||||
|
||||
### 4.1. 수치로 확인 (CLI)
|
||||
|
||||
```bash
|
||||
# 1. HydraAdminService (백엔드 서비스) 커버리지
|
||||
go test -v ./internal/service -run TestHydraAdminService -coverprofile=coverage_hydra.out
|
||||
go tool cover -func=coverage_hydra.out | grep hydra_admin_service.go
|
||||
|
||||
# 2. RelyingPartyService (통합 서비스) 커버리지
|
||||
go test -v ./internal/service -run TestRelyingPartyService -coverprofile=coverage_rp.out
|
||||
go tool cover -func=coverage_rp.out | grep relying_party_service.go
|
||||
```
|
||||
|
||||
**예시 출력:**
|
||||
```text
|
||||
baron-sso-backend/internal/service/hydra_admin_service.go:35: ListClients 100.0%
|
||||
baron-sso-backend/internal/service/hydra_admin_service.go:70: GetClient 85.7%
|
||||
...
|
||||
total: (statements) 78.5%
|
||||
```
|
||||
|
||||
### 4.2. 시각적으로 확인 (HTML)
|
||||
|
||||
어떤 코드가 테스트되지 않았는지(Missing Branch) 브라우저에서 색상으로 확인합니다.
|
||||
|
||||
```bash
|
||||
go tool cover -html=coverage_hydra.out
|
||||
```
|
||||
|
||||
* **초록색**: 테스트에 의해 실행된 코드
|
||||
* **빨간색**: 테스트되지 않은 코드 (추가 테스트 케이스 필요)
|
||||
* **회색**: 테스트 대상이 아닌 코드 (선언부 등)
|
||||
|
||||
## 5. 주요 테스트 항목 (Checklist)
|
||||
|
||||
| 분류 | 메서드 | 테스트 내용 | 파일 위치 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| **클라이언트 관리** | `ListClients` | 클라이언트 목록 페이징 조회 | `hydra_admin_service_test.go` |
|
||||
| | `GetClient` | 특정 클라이언트 상세 조회 (성공/실패) | `hydra_admin_service_test.go` |
|
||||
| | `CreateClient` | 신규 클라이언트 생성 및 메타데이터 검증 | `hydra_admin_service_test.go` |
|
||||
| | `UpdateClient` | 클라이언트 정보 수정 (PUT) | `hydra_admin_service_test.go` |
|
||||
| | `PatchClientStatus` | 클라이언트 상태 변경 (JSON Patch) | `hydra_admin_service_test.go` |
|
||||
| | `DeleteClient` | 클라이언트 삭제 | `hydra_admin_service_test.go` |
|
||||
| **인증/동의** | `GetConsentRequest` | Consent Challenge 검증 및 요청 정보 조회 | `hydra_admin_service_test.go` |
|
||||
| | `AcceptConsentRequest` | 동의 승인 및 리다이렉트 URL 반환 | `hydra_admin_service_test.go` |
|
||||
| | `RejectConsentRequest` | 동의 거부 처리 | `hydra_admin_service_test.go` |
|
||||
| | `GetLoginRequest` | Login Challenge 검증 | `hydra_admin_service_test.go` |
|
||||
| | `AcceptLoginRequest` | 로그인 승인 및 리다이렉트 URL 반환 | `hydra_admin_service_test.go` |
|
||||
| | `RejectLoginRequest` | 로그인 거부 처리 | `hydra_admin_service_test.go` |
|
||||
| **세션 관리** | `ListConsentSessions` | 특정 사용자의 활성 세션 목록 조회 | `hydra_admin_service_test.go` |
|
||||
| | `RevokeConsentSessions` | 특정 사용자/클라이언트의 세션 만료 처리 | `hydra_admin_service_test.go` |
|
||||
| **서비스 통합** | `Create` (RP) | Hydra 생성 -> DB 생성 -> Keto 권한 부여 | `relying_party_service_test.go` |
|
||||
| | `Create` (Rollback) | DB 실패 시 Hydra 롤백(삭제) 검증 | `relying_party_service_test.go` |
|
||||
| **핸들러 연동** | `PasswordLogin` | OIDC 로그인 성공 및 Challenge 승인 | `auth_handler_login_test.go` |
|
||||
| | `PasswordLogin` | 비활성(Inactive) 클라이언트 로그인 차단 | `auth_handler_login_test.go` |
|
||||
|
||||
## 6. 테스트 코드 작성 가이드
|
||||
|
||||
새로운 기능을 추가하거나 커버리지를 높일 때 다음 패턴을 참고하세요.
|
||||
|
||||
```go
|
||||
func TestHydraAdminService_NewFeature(t *testing.T) {
|
||||
// 1. Mock 핸들러 정의 (예상되는 요청 검증 및 가짜 응답 반환)
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Assert: 요청 메서드, URL, 바디 검증
|
||||
if r.Method != http.MethodPost {
|
||||
t.Errorf("expected POST, got %s", r.Method)
|
||||
}
|
||||
|
||||
// Response: 가짜 응답 작성
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(expectedResponse)
|
||||
})
|
||||
|
||||
// 2. 서비스 초기화 (Mock Client 주입)
|
||||
svc := &HydraAdminService{
|
||||
AdminURL: "http://hydra:4445",
|
||||
HTTPClient: mockHydraClient(handler), // ory_service_test.go의 헬퍼 사용
|
||||
}
|
||||
|
||||
// 3. 테스트 실행 및 검증
|
||||
result, err := svc.NewFeature(context.Background(), args)
|
||||
if err != nil {
|
||||
t.Fatalf("failed: %v", err)
|
||||
}
|
||||
// Assert: 결과값 검증
|
||||
}
|
||||
```
|
||||
62
docs/test_concepts_guide.md
Normal file
62
docs/test_concepts_guide.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# 테스트 커버리지 및 모킹 가이드
|
||||
|
||||
이 문서는 백엔드 테스트 코드 작성 시 필수적인 개념인 **테스트 커버리지**와 **모킹(Mocking)**에 대해 설명합니다.
|
||||
|
||||
---
|
||||
|
||||
## 1. 테스트 커버리지 (Test Coverage)
|
||||
|
||||
**정의:** 테스트 코드가 전체 소스 코드 중 얼마나 많은 부분을 실행(검증)했는지를 나타내는 백분율(%) 지표입니다.
|
||||
|
||||
### 왜 중요한가요?
|
||||
* **안정성 지표:** 커버리지가 높을수록 코드의 많은 부분이 자동화된 검증을 거쳤음을 의미합니다.
|
||||
* **사각지대 발견:** 테스트되지 않은 '죽은 코드(Dead Code)'나 누락된 예외 처리 분기(if-else)를 찾아낼 수 있습니다.
|
||||
* **리팩토링 자신감:** 커버리지가 높으면 기존 기능을 깨뜨리지 않고 코드를 수정하기가 훨씬 수월합니다.
|
||||
|
||||
### 어떻게 확인하나요? (Go 기준)
|
||||
```bash
|
||||
# 1. 테스트 실행 및 기록 저장
|
||||
go test -coverprofile=coverage.out ./...
|
||||
|
||||
# 2. 브라우저에서 시각적으로 확인 (어느 줄이 안 됐는지 색상으로 표시됨)
|
||||
go tool cover -html=coverage.out
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 모킹 (Mocking)
|
||||
|
||||
**정의:** 테스트하려는 대상이 의존하는 외부 요소(데이터베이스, 외부 API, 다른 서비스 등)를 **동작만 흉내 내는 가짜 객체(Mock)**로 대체하는 기술입니다.
|
||||
|
||||
### 왜 필요한가요?
|
||||
* **독립적 환경:** 실제 Ory Hydra 서버가 꺼져 있어도 백엔드 로직만 따로 테스트할 수 있습니다.
|
||||
* **결정적 테스트:** 네트워크 상태에 상관없이 항상 동일한 결과를 얻을 수 있습니다.
|
||||
* **예외 상황 시뮬레이션:** "서버 점검 중(503 에러)"과 같은 특수한 상황을 강제로 만들어 내 코드가 잘 대응하는지 확인할 수 있습니다.
|
||||
|
||||
### `MockRelyingPartyRepository`는 무엇인가요?
|
||||
사용자께서 보신 `MockRelyingPartyRepository`는 라이브러리가 제공하는 함수가 아니라, **테스트를 위해 직접 만든 구조체**입니다.
|
||||
|
||||
1. **구조체 정의:** `RelyingPartyRepository`라는 인터페이스를 똑같이 흉내 내도록 우리가 직접 코드를 짭니다.
|
||||
2. **라이브러리 활용:** 이때 `github.com/stretchr/testify/mock` 라이브러리를 사용하여 "이 함수가 호출되면 어떤 값을 반환하라"는 지시를 쉽게 내릴 수 있게 만듭니다.
|
||||
|
||||
**예시 코드:**
|
||||
```go
|
||||
// 1. 우리가 직접 만든 가짜 객체 (이름은 마음대로 정할 수 있음)
|
||||
type MockRelyingPartyRepository struct {
|
||||
mock.Mock // testify 라이브러리의 기능을 빌려옴
|
||||
}
|
||||
|
||||
// 2. 실제 DB 저장소인 척 함수를 구현
|
||||
func (m *MockRelyingPartyRepository) Create(ctx context.Context, rp *domain.RelyingParty) error {
|
||||
args := m.Called(ctx, rp) // 호출 기록
|
||||
return args.Error(0) // 설정된 에러 반환
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 요약 및 원칙
|
||||
|
||||
1. **모킹을 통해 커버리지를 높이세요:** 실제 환경에서 만들기 힘든 에러 상황을 모킹으로 구현하여 코드의 예외 처리 로직(Red line)을 검증하세요.
|
||||
2. **핵심 비즈니스 로직 우선:** 단순한 설정값 조회보다는 **로그인, 권한 체크, 데이터 통합** 등 서비스의 핵심 기능 커버리지를 **80% 이상**으로 유지하는 것을 권장합니다.
|
||||
3. **수치에 집착하지 마세요:** 커버리지 100%가 "버그 없음"을 보장하지는 않습니다. 의미 있는 테스트 케이스를 작성하는 것이 더 중요합니다.
|
||||
Reference in New Issue
Block a user