- Frontend: Next.js 14 with TypeScript - Backend: FastAPI with SQLAlchemy - Agent: Carmodoo sync agent - Deployment: Docker Compose based staging/production setup - Scripts: Automated deployment with rollback support 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
233 lines
8.1 KiB
Python
233 lines
8.1 KiB
Python
"""
|
|
Performance Check Integration Tests
|
|
|
|
통합 테스트 시나리오:
|
|
1. 배너 차량 + 비로그인 → 성능점검표 미리보기만 가능
|
|
2. 배너 차량 + 로그인 (미결제) → 성능점검표 미리보기만 가능
|
|
3. 배너 차량 + 로그인 (0.1 CC 결제) → 성능점검표 전체 접근 가능
|
|
4. 일반 차량 + 비로그인 → 성능점검표 미리보기만 가능
|
|
5. 일반 차량 + 로그인 (1 CC 결제) → 성능점검표 전체 접근 가능
|
|
"""
|
|
|
|
import pytest
|
|
from fastapi.testclient import TestClient
|
|
from unittest.mock import MagicMock, patch
|
|
from sqlalchemy.orm import Session
|
|
|
|
|
|
# 테스트 시나리오 정의
|
|
TEST_SCENARIOS = [
|
|
# (시나리오 이름, 배너여부, 로그인여부, 결제타입, 예상결과)
|
|
("banner_anonymous", True, False, None, {"has_access": False, "can_view_images": True}),
|
|
("banner_logged_in_no_payment", True, True, None, {"has_access": False, "can_view_images": True}),
|
|
("banner_logged_in_perf_payment", True, True, "performance", {"has_access": True, "can_view_images": True}),
|
|
("banner_logged_in_full_payment", True, True, "full", {"has_access": True, "can_view_images": True}),
|
|
("normal_anonymous", False, False, None, {"has_access": False, "can_view_images": False}),
|
|
("normal_logged_in_no_payment", False, True, None, {"has_access": False, "can_view_images": False}),
|
|
("normal_logged_in_perf_payment", False, True, "performance", {"has_access": True, "can_view_images": False}),
|
|
("normal_logged_in_full_payment", False, True, "full", {"has_access": True, "can_view_images": True}),
|
|
]
|
|
|
|
|
|
class TestPerformanceCheckIntegration:
|
|
"""성능점검표 통합 테스트"""
|
|
|
|
@pytest.mark.parametrize(
|
|
"scenario_name,is_banner,is_logged_in,payment_type,expected",
|
|
TEST_SCENARIOS
|
|
)
|
|
def test_performance_check_access_scenarios(
|
|
self,
|
|
scenario_name: str,
|
|
is_banner: bool,
|
|
is_logged_in: bool,
|
|
payment_type: str,
|
|
expected: dict
|
|
):
|
|
"""
|
|
모든 시나리오에 대한 성능점검표 접근 테스트
|
|
|
|
이 테스트는 실제 API를 호출하지 않고 로직만 검증합니다.
|
|
실제 API 테스트는 별도의 e2e 테스트에서 수행합니다.
|
|
"""
|
|
# Given
|
|
user = self._create_user(is_logged_in)
|
|
has_perf_view = payment_type == "performance"
|
|
has_car_view = payment_type == "full"
|
|
|
|
# When
|
|
result = self._simulate_performance_check_access(
|
|
user=user,
|
|
is_banner_car=is_banner,
|
|
has_perf_view=has_perf_view,
|
|
has_car_view=has_car_view
|
|
)
|
|
|
|
# Then
|
|
assert result["has_access"] == expected["has_access"], \
|
|
f"Scenario '{scenario_name}' failed: expected has_access={expected['has_access']}, got {result['has_access']}"
|
|
|
|
def _create_user(self, is_logged_in: bool):
|
|
"""테스트용 사용자 생성"""
|
|
if not is_logged_in:
|
|
return None
|
|
|
|
user = MagicMock()
|
|
user.is_admin = False
|
|
user.id = 1
|
|
return user
|
|
|
|
def _simulate_performance_check_access(
|
|
self,
|
|
user,
|
|
is_banner_car: bool,
|
|
has_perf_view: bool,
|
|
has_car_view: bool
|
|
) -> dict:
|
|
"""
|
|
성능점검표 접근 시뮬레이션
|
|
|
|
실제 로직: backend/app/api/carmodoo.py - get_car_performance_check()
|
|
"""
|
|
has_access = False
|
|
|
|
# 배너 차량 여부는 성능점검표 접근에 영향 없음!
|
|
# (이것이 핵심 비즈니스 로직)
|
|
|
|
if user:
|
|
if hasattr(user, 'is_admin') and user.is_admin:
|
|
has_access = True
|
|
else:
|
|
has_access = has_perf_view or has_car_view
|
|
|
|
return {
|
|
"has_access": has_access,
|
|
"preview": {
|
|
"check_number": "TEST123",
|
|
"check_date": "2024-01-01",
|
|
"mileage": 50000
|
|
} if not has_access else None,
|
|
"data": {"full": "data"} if has_access else None
|
|
}
|
|
|
|
|
|
class TestBannerCarIntegration:
|
|
"""배너 차량 통합 테스트"""
|
|
|
|
def test_banner_car_free_features(self):
|
|
"""배너 차량의 무료 기능 확인"""
|
|
is_banner_car = True
|
|
|
|
# 배너 차량 무료 기능
|
|
free_features = {
|
|
"all_images": True,
|
|
"dealer_contact": True,
|
|
"basic_info": True,
|
|
}
|
|
|
|
# 배너 차량 유료 기능
|
|
paid_features = {
|
|
"performance_check": True, # 0.1 CC 필요
|
|
}
|
|
|
|
# 비로그인 사용자도 무료 기능 접근 가능
|
|
user = None
|
|
|
|
for feature, is_free in free_features.items():
|
|
can_access = is_banner_car and is_free
|
|
assert can_access is True, f"Banner car should have free access to {feature}"
|
|
|
|
# 성능점검표는 결제 필요
|
|
can_access_perf_check = False # 결제하지 않으면 불가
|
|
assert can_access_perf_check is False, "Performance check requires payment even for banner cars"
|
|
|
|
def test_banner_vs_normal_car_comparison(self):
|
|
"""배너 차량 vs 일반 차량 기능 비교"""
|
|
user_logged_in_no_payment = MagicMock()
|
|
user_logged_in_no_payment.is_admin = False
|
|
|
|
# 배너 차량
|
|
banner_car_access = {
|
|
"images": True, # 무료
|
|
"contact": True, # 무료
|
|
"performance_check": False, # 결제 필요
|
|
}
|
|
|
|
# 일반 차량
|
|
normal_car_access = {
|
|
"images": False, # 결제 필요
|
|
"contact": False, # 결제 필요
|
|
"performance_check": False, # 결제 필요
|
|
}
|
|
|
|
# 배너 차량은 이미지/연락처만 무료
|
|
assert banner_car_access["images"] is True
|
|
assert banner_car_access["contact"] is True
|
|
assert banner_car_access["performance_check"] is False
|
|
|
|
# 일반 차량은 모두 유료
|
|
assert normal_car_access["images"] is False
|
|
assert normal_car_access["performance_check"] is False
|
|
|
|
|
|
class TestCCPaymentIntegration:
|
|
"""CC 결제 통합 테스트"""
|
|
|
|
def test_performance_check_costs_01_cc(self):
|
|
"""성능점검표 비용은 0.1 CC"""
|
|
PERFORMANCE_CHECK_COST = 0.1
|
|
|
|
user_balance = 5.0 # 신규 가입 시 지급되는 CC
|
|
|
|
# 결제 후 잔액
|
|
after_payment = user_balance - PERFORMANCE_CHECK_COST
|
|
|
|
assert after_payment == 4.9
|
|
|
|
def test_full_car_view_costs_1_cc(self):
|
|
"""차량 전체 보기 비용은 1 CC"""
|
|
FULL_CAR_VIEW_COST = 1.0
|
|
|
|
user_balance = 5.0
|
|
|
|
# 결제 후 잔액
|
|
after_payment = user_balance - FULL_CAR_VIEW_COST
|
|
|
|
assert after_payment == 4.0
|
|
|
|
def test_full_car_view_includes_performance_check(self):
|
|
"""1 CC 결제 시 성능점검표 포함"""
|
|
has_full_car_view = True
|
|
has_separate_perf_view = False
|
|
|
|
# 1 CC 결제하면 성능점검표 접근 가능
|
|
can_access_perf_check = has_full_car_view or has_separate_perf_view
|
|
|
|
assert can_access_perf_check is True
|
|
|
|
def test_insufficient_balance(self):
|
|
"""잔액 부족 시 결제 실패"""
|
|
user_balance = 0.05
|
|
PERFORMANCE_CHECK_COST = 0.1
|
|
|
|
can_purchase = user_balance >= PERFORMANCE_CHECK_COST
|
|
|
|
assert can_purchase is False
|
|
|
|
|
|
# 테스트 매트릭스 문서화
|
|
ACCESS_MATRIX = """
|
|
+------------------+-------------+--------------------+------------------+
|
|
| 사용자 상태 | 배너 차량 | 일반 차량 | 성능점검표 |
|
|
+------------------+-------------+--------------------+------------------+
|
|
| 비로그인 | 이미지 O | 이미지 X (블러) | X |
|
|
| 로그인 (미결제) | 이미지 O | 이미지 X (블러) | X |
|
|
| 로그인 (0.1CC) | 이미지 O | 이미지 X (블러) | O |
|
|
| 로그인 (1CC) | 이미지 O | 이미지 O | O |
|
|
| 관리자 | 이미지 O | 이미지 O | O |
|
|
+------------------+-------------+--------------------+------------------+
|
|
|
|
* 배너 차량: 이미지와 연락처만 무료, 성능점검표는 0.1 CC 필요
|
|
* 1 CC 결제 시 성능점검표 포함
|
|
"""
|