-
Notifications
You must be signed in to change notification settings - Fork 0
Harness
trz-21 edited this page Jun 16, 2026
·
2 revisions
📌 이 페이지는 이 프로젝트의 살아있는 스펙(최종 현황) 이며 canonical 문서입니다. 코드/설계 변경 시 PR 머지 후 이 페이지를 갱신합니다. (작업 흐름: 개발-워크플로우)
컴파일타임 (cargo check / tsc --noEmit)
└─ 타입 에러, 미구현 trait, 없는 함수 → 즉시 검출
단위 테스트 (cargo test --lib / vitest)
└─ application/, adapters/ 각 모듈의 #[cfg(test)] 블록
└─ Mock Port 주입으로 외부 의존성 없이 비즈니스 로직 검증
통합 테스트 (cargo test --tests / vitest)
└─ TestApp + testcontainers PostgreSQL
└─ HTTP 요청 → DB 저장 → 응답 전체 흐름
└─ 크롤러/Gemini API는 Mock Adapter 사용
E2E (Playwright)
└─ 실제 브라우저 + 실제 서버(next dev, baseURL http://localhost:3000)
└─ 핵심 사용자 플로우 / 공개 화면 스모크
- 설정:
playwright.config.ts—testDir: './tests/e2e',webServer로npm run dev자동 기동. - 현행 스펙(
landing.spec.ts): 공개 랜딩 페이지(/) 스모크 3건 — 히어로 카피·가입/로그인 CTA / 주요 섹션 헤딩(핵심 가치·작동 방식·신뢰할 수 있는 분석·요금제) / 가입 CTA →/register라우팅. 인증·백엔드가 필요 없어 dev 서버만으로 검증 가능. ⚠️ CI 게이트 주의: Playwright는 테스트가 0건이면Error: No tests found로 exit 1 → CI red.tests/e2e/에는 항상 최소 1건 이상의 통과 테스트가 있어야 한다. (#30/#31 회귀 방지)
-
cargo test실행 시 자동으로 PostgreSQL 컨테이너 스핀업 - 로컬 PostgreSQL 설치 불필요
- 프로세스당 컨테이너 1개 공유 (
OnceCell) → 성능 최적화 - 각 TestApp은 격리된
test_<uuid>DB → 테스트 간 상태 오염 없음 - TestApp Drop 시 test DB 자동 삭제
#[tokio::test]
async fn test_create_analysis() {
let app = TestApp::spawn().await;
let client = reqwest::Client::new();
// 1. 회원가입
let register_res = client
.post(&format!("{}/api/v1/auth/register", app.address))
.json(&serde_json::json!({
"email": "test@example.com",
"password": "password123"
}))
.send().await.unwrap();
assert_eq!(register_res.status(), 201);
let body: serde_json::Value = register_res.json().await.unwrap();
let token = body["token"].as_str().unwrap();
// 2. 분석 요청
let analysis_res = client
.post(&format!("{}/api/v1/analyses", app.address))
.bearer_auth(token)
.json(&serde_json::json!({
"urls": ["https://www.coupang.com/vp/products/12345"],
"review_limit": 50
}))
.send().await.unwrap();
assert_eq!(analysis_res.status(), 202);
}// 크롤러 Mock
struct MockCrawler;
#[async_trait]
impl CoupangCrawler for MockCrawler {
async fn fetch_reviews(&self, url: &str, limit: u32) -> Result<Vec<Review>> {
Ok(vec![
Review { text: "포장이 너무 허술해요".to_string(), rating: 2 },
Review { text: "가격 대비 품질 좋아요".to_string(), rating: 5 },
])
}
}
// TestApp에 주입
impl TestApp {
pub async fn spawn_with_mock() -> Self {
// MockCrawler, MockAiAnalyzer 주입
}
}# 백엔드 (testcontainers 자동 처리)
cd backend
make test # cargo test
make run # docker-compose DB + migrate + cargo run
# 프론트엔드
cd frontend
npm test -- --run # vitest
npx playwright test # E2E-
컴파일 먼저:
cargo check/tsc --noEmit통과 없이 작업 완료 불가 -
테스트 통과:
cargo test/npm test -- --run전체 통과 필수 - API 계약 유지: 기존 응답 필드 제거/타입 변경 금지 (추가만 허용)
- 테스트 동반: 새 엔드포인트/기능 추가 시 통합 테스트 필수
-
스펙 동기화: 기능/설계 변경 시 GitHub Wiki(canonical) 해당 페이지 갱신 필수 (구
specification/은 이관 전 스냅샷)
push/PR → GitHub Actions
Backend CI (backend/** 변경 시):
├─ cargo check --all-targets
├─ cargo fmt --check
├─ cargo clippy --all-targets -- -D warnings
└─ cargo test --all-targets (services: postgres:16)
Frontend CI (frontend/** 변경 시):
├─ tsc --noEmit
├─ npm run lint
├─ vitest run + vitest run --coverage
└─ playwright test ← tests/e2e/ 에 테스트 0건이면 실패함(위 주의 참고)
두 워크플로우는
paths필터로 분리돼 있다.frontend/**변경은 Frontend CI만,backend/**변경은 Backend CI만 돌린다.
📚 스펙 네비게이션: Home · Service-Overview · Tech-Stack · API · Backend · Frontend · Harness · 개발-워크플로우