import 'package:flutter_test/flutter_test.dart'; import 'package:lunchpick/domain/usecases/recommendation_engine.dart'; import 'package:lunchpick/domain/entities/restaurant.dart'; import 'package:lunchpick/domain/entities/visit_record.dart'; import 'package:lunchpick/domain/entities/user_settings.dart'; import 'package:uuid/uuid.dart'; void main() { late RecommendationEngine engine; late List testRestaurants; late List testVisitRecords; setUp(() { engine = RecommendationEngine(); // 테스트용 맛집 데이터 생성 testRestaurants = [ Restaurant( id: '1', name: '가까운 한식당', category: '한식', subCategory: '백반', roadAddress: '서울 중구 세종대로 110', jibunAddress: '서울 중구 태평로1가 31', latitude: 37.5666, longitude: 126.9784, source: DataSource.USER_INPUT, createdAt: DateTime.now(), updatedAt: DateTime.now(), visitCount: 0, ), Restaurant( id: '2', name: '먼 중식당', category: '중식', subCategory: '짜장면', roadAddress: '서울 강남구 테헤란로 123', jibunAddress: '서울 강남구 역삼동 123', latitude: 37.5012, longitude: 127.0396, source: DataSource.USER_INPUT, createdAt: DateTime.now(), updatedAt: DateTime.now(), visitCount: 0, ), Restaurant( id: '3', name: '최근 방문한 일식당', category: '일식', subCategory: '스시', roadAddress: '서울 종로구 종로 123', jibunAddress: '서울 종로구 종로1가 123', latitude: 37.5702, longitude: 126.9842, source: DataSource.USER_INPUT, createdAt: DateTime.now(), updatedAt: DateTime.now(), visitCount: 1, ), ]; // 테스트용 방문 기록 생성 testVisitRecords = [ VisitRecord( id: const Uuid().v4(), restaurantId: '3', visitDate: DateTime.now().subtract(const Duration(days: 2)), isConfirmed: true, createdAt: DateTime.now(), ), ]; }); group('RecommendationEngine', () { test('거리 필터링이 정상 작동해야 함', () async { final config = RecommendationConfig( userLatitude: 37.5665, userLongitude: 126.9780, maxDistance: 1.0, // 1km selectedCategories: [], userSettings: UserSettings(), ); final result = await engine.generateRecommendation( allRestaurants: testRestaurants, recentVisits: [], config: config, ); // 1km 이내의 맛집만 추천되어야 함 expect(result, isNotNull); expect(result!.id, isIn(['1', '3'])); // 가까운 한식당과 일식당만 expect(result.id, isNot('2')); // 먼 중식당은 제외 }); test('재방문 방지가 정상 작동해야 함', () async { final settings = UserSettings(); final updatedSettings = settings.copyWith(revisitPreventionDays: 7); final config = RecommendationConfig( userLatitude: 37.5665, userLongitude: 126.9780, maxDistance: 10.0, // 10km selectedCategories: [], userSettings: updatedSettings, ); final result = await engine.generateRecommendation( allRestaurants: testRestaurants, recentVisits: testVisitRecords, config: config, ); // 최근 방문한 일식당은 제외되어야 함 expect(result, isNotNull); expect(result!.id, isNot('3')); }); test('카테고리 필터링이 정상 작동해야 함', () async { final config = RecommendationConfig( userLatitude: 37.5665, userLongitude: 126.9780, maxDistance: 100.0, // 100km selectedCategories: ['한식'], userSettings: UserSettings(), ); final result = await engine.generateRecommendation( allRestaurants: testRestaurants, recentVisits: [], config: config, ); // 한식만 추천되어야 함 expect(result, isNotNull); expect(result!.category, '한식'); }); test('모든 조건을 만족하는 맛집이 없으면 null을 반환해야 함', () async { final config = RecommendationConfig( userLatitude: 37.5665, userLongitude: 126.9780, maxDistance: 0.1, // 100m - 너무 가까움 selectedCategories: [], userSettings: UserSettings(), ); final result = await engine.generateRecommendation( allRestaurants: testRestaurants, recentVisits: [], config: config, ); expect(result, isNull); }); test('가중치 시스템이 정상 작동해야 함', () async { // 한식에 높은 가중치 부여 final settings = UserSettings(); final updatedSettings = settings.copyWith( categoryWeights: { '한식': 2.0, '중식': 0.5, '일식': 1.0, }, ); final config = RecommendationConfig( userLatitude: 37.5665, userLongitude: 126.9780, maxDistance: 100.0, selectedCategories: [], userSettings: updatedSettings, ); // 여러 번 실행하여 한식이 더 자주 추천되는지 확인 final results = {}; for (int i = 0; i < 100; i++) { final result = await engine.generateRecommendation( allRestaurants: testRestaurants, recentVisits: [], config: config, ); if (result != null) { results[result.category] = (results[result.category] ?? 0) + 1; } } // 한식이 다른 카테고리보다 더 많이 추천되어야 함 expect(results['한식'] ?? 0, greaterThan(results['중식'] ?? 0)); }); }); }