-
Notifications
You must be signed in to change notification settings - Fork 0
test: 식단 기능 테스트 코드 작성 #523
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
oeunji
wants to merge
11
commits into
develop
Choose a base branch
from
test/dining
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
cc27c5f
delete: koinUITest 타겟 삭제 및 파일 정리
oeunji 4c1fa31
delete: 기존에 만들어진 koinUnitTest 삭제
oeunji 849539a
add: 새로운 Unit Testing 타겟 추가
oeunji 6569d18
add: Combine Publisher를 async로 브리징하는 테스트 헬퍼 추가
oeunji 750b398
add: 식단 테스트용 Fixture 추가
oeunji 6a2e0ed
add: DiningRepository Spy 추가
oeunji bb87523
add: DateProvider 시간대 판단 경계값 테스트 추가
oeunji 7f45dcd
add: FetchDiningListUseCase 필터링/정렬 테스트 추가
oeunji 4d126a0
add: ShareMenuListUseCase 식단 공유 테스트 추가
oeunji 7316605
chore: 식단 테스트 파일을 koinUnitTests 타겟에 등록
oeunji 4643366
delete: 빈 example() 테스트 삭제
oeunji File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| // | ||
| // DateProviderTests.swift | ||
| // koinUnitTests | ||
| // | ||
| // Created by 이은지 on 8/8/26. | ||
| // | ||
|
|
||
| import Foundation | ||
| import Testing | ||
| @testable import koin | ||
|
|
||
| @Suite("DateProvider - 시간대 판단 로직 경계값") | ||
| struct DateProviderTests { | ||
|
|
||
| private let sut = DefaultDateProvider() | ||
| private let calendar = Calendar.current | ||
|
|
||
| private func date(hour: Int, minute: Int) throws -> Date { | ||
| try #require(DiningFixture.date(hour: hour, minute: minute, calendar: calendar)) | ||
| } | ||
|
|
||
| @Test("09:00 이전이면 breakfast를 반환한다") | ||
| func 아홉시_이전이면_breakfast를_반환한다() throws { | ||
| let input = try date(hour: 8, minute: 59) | ||
|
|
||
| let result = sut.execute(date: input) | ||
|
|
||
| #expect(result.diningType == .breakfast) | ||
| #expect(calendar.isDate(result.date, inSameDayAs: input)) | ||
| } | ||
|
|
||
| @Test("09:00이면 lunch를 반환한다") | ||
| func 아홉시면_lunch를_반환한다() throws { | ||
| let input = try date(hour: 9, minute: 0) | ||
|
|
||
| let result = sut.execute(date: input) | ||
|
|
||
| #expect(result.diningType == .lunch) | ||
| #expect(calendar.isDate(result.date, inSameDayAs: input)) | ||
| } | ||
|
|
||
| @Test("13:30이면 lunch를 반환한다") | ||
| func 열세시_삼십분이면_lunch를_반환한다() throws { | ||
| let input = try date(hour: 13, minute: 30) | ||
|
|
||
| let result = sut.execute(date: input) | ||
|
|
||
| #expect(result.diningType == .lunch) | ||
| } | ||
|
|
||
| @Test("13:31이면 dinner를 반환한다") | ||
| func 열세시_삼십일분이면_dinner를_반환한다() throws { | ||
| let input = try date(hour: 13, minute: 31) | ||
|
|
||
| let result = sut.execute(date: input) | ||
|
|
||
| #expect(result.diningType == .dinner) | ||
| #expect(calendar.isDate(result.date, inSameDayAs: input)) | ||
| } | ||
|
|
||
| @Test("18:30이면 dinner를 반환한다") | ||
| func 열여덟시_삼십분이면_dinner를_반환한다() throws { | ||
| let input = try date(hour: 18, minute: 30) | ||
|
|
||
| let result = sut.execute(date: input) | ||
|
|
||
| #expect(result.diningType == .dinner) | ||
| } | ||
|
|
||
| @Test("18:30 이후면 다음 날 breakfast를 반환한다", arguments: [(18, 31), (23, 59)]) | ||
| func 열여덟시_삼십분_이후면_다음_날_breakfast를_반환한다(hour: Int, minute: Int) throws { | ||
| let input = try date(hour: hour, minute: minute) | ||
| let expectedNextDay = try #require(calendar.date(byAdding: .day, value: 1, to: input)) | ||
|
|
||
| let result = sut.execute(date: input) | ||
|
|
||
| #expect(result.diningType == .breakfast) | ||
| #expect(calendar.isDate(result.date, inSameDayAs: expectedNextDay)) | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| // | ||
| // FetchDiningListUseCaseTests.swift | ||
| // koinUnitTests | ||
| // | ||
| // Created by 이은지 on 8/8/26. | ||
| // | ||
|
|
||
| import Foundation | ||
| import Testing | ||
| @testable import koin | ||
|
|
||
| @Suite("FetchDiningListUseCase - segmentControl에 따른 데이터 필터링") | ||
| struct FetchDiningListUseCaseTests { | ||
|
|
||
| private func makeSUT( | ||
| stubbedDiningList: [DiningDto] | ||
| ) -> (sut: DefaultFetchDiningListUseCase, spy: SpyDiningRepository) { | ||
| let spy = SpyDiningRepository() | ||
| spy.stubbedDiningList = stubbedDiningList | ||
| return (DefaultFetchDiningListUseCase(diningRepository: spy), spy) | ||
| } | ||
|
|
||
| private func diningInfo( | ||
| type: DiningType, | ||
| date: Date = Date() | ||
| ) -> CurrentDiningTime { | ||
| CurrentDiningTime(date: date, diningType: type) | ||
| } | ||
|
|
||
| @Test("요청한 시간대의 식단만 반환한다") | ||
| func 요청한_시간대의_식단만_반환한다() async throws { | ||
| let (sut, _) = makeSUT(stubbedDiningList: [ | ||
| DiningFixture.dto(id: 1, type: .breakfast, place: .cornerA), | ||
| DiningFixture.dto(id: 2, type: .lunch, place: .cornerB), | ||
| DiningFixture.dto(id: 3, type: .dinner, place: .cornerC), | ||
| DiningFixture.dto(id: 4, type: .lunch, place: .special) | ||
| ]) | ||
|
|
||
| let result = try await sut.execute(diningInfo: diningInfo(type: .lunch)).firstValue() | ||
|
|
||
| #expect(result.count == 2) | ||
| #expect(result.allSatisfy { $0.type == .lunch }) | ||
| #expect(result.map(\.id).sorted() == [2, 4]) | ||
| } | ||
|
|
||
| @Test( | ||
| "미운영 메뉴는 제외한다", | ||
| arguments: [DiningType.breakfast, .lunch, .dinner] | ||
| ) | ||
| func 미운영_메뉴는_제외한다(requestedType: DiningType) async throws { | ||
| let (sut, _) = makeSUT(stubbedDiningList: [ | ||
| DiningFixture.dto(id: 1, type: requestedType, place: .cornerA, menu: ["미운영"]), | ||
| DiningFixture.dto(id: 2, type: requestedType, place: .cornerB, menu: ["김치찌개", "밥"]) | ||
| ]) | ||
|
|
||
| let result = try await sut.execute(diningInfo: diningInfo(type: requestedType)).firstValue() | ||
|
|
||
| #expect(result.count == 1) | ||
| #expect(result.first?.id == 2) | ||
| #expect(!result.contains { $0.menu.first == "미운영" }) | ||
| } | ||
|
|
||
| @Test("장소 우선순위대로 정렬한다") | ||
| func 장소_우선순위대로_정렬한다() async throws { | ||
| let (sut, _) = makeSUT(stubbedDiningList: [ | ||
| DiningFixture.dto(id: 1, type: .lunch, place: .secondCampus), | ||
| DiningFixture.dto(id: 2, type: .lunch, place: .special), | ||
| DiningFixture.dto(id: 3, type: .lunch, place: .cornerC), | ||
| DiningFixture.dto(id: 4, type: .lunch, place: .cornerA), | ||
| DiningFixture.dto(id: 5, type: .lunch, place: .cornerB) | ||
| ]) | ||
|
|
||
| let result = try await sut.execute(diningInfo: diningInfo(type: .lunch)).firstValue() | ||
|
|
||
| #expect(result.map(\.place) == [.cornerA, .cornerB, .cornerC, .special, .secondCampus]) | ||
| } | ||
|
|
||
| @Test("요청 날짜를 yyMMdd 형식으로 전달한다") | ||
| func 요청_날짜를_yyMMdd_형식으로_전달한다() async throws { | ||
| let (sut, spy) = makeSUT(stubbedDiningList: []) | ||
| let requestedDate = try #require(DiningFixture.date(year: 2026, month: 8, day: 3)) | ||
|
|
||
| _ = try await sut.execute(diningInfo: diningInfo(type: .lunch, date: requestedDate)).firstValue() | ||
|
|
||
| #expect(spy.fetchDiningListCallCount == 1) | ||
| #expect(spy.receivedFetchRequests.first?.date == "260803") | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| // | ||
| // ShareMenuListUseCaseTests.swift | ||
| // koinUnitTests | ||
| // | ||
| // Created by 이은지 on 8/8/26. | ||
| // | ||
|
|
||
| import Foundation | ||
| import Testing | ||
| @testable import koin | ||
|
|
||
| @Suite("ShareMenuListUseCase - 카카오톡 식단 공유하기") | ||
| struct ShareMenuListUseCaseTests { | ||
|
|
||
| @Test("DiningItem을 ShareDiningMenu로 변환하면 메뉴와 이미지를 유지한다") | ||
| func DiningItem을_ShareDiningMenu로_변환하면_메뉴와_이미지를_유지한다() { | ||
| let item = DiningFixture.item( | ||
| type: .lunch, | ||
| place: .cornerA, | ||
| menu: ["김치찌개", "밥"], | ||
| imageUrl: "url1" | ||
| ) | ||
|
|
||
| let shareModel = item.toShareDiningItem() | ||
|
|
||
| #expect(shareModel.menuList == ["김치찌개", "밥"]) | ||
| #expect(shareModel.imageUrl == "url1") | ||
| #expect(shareModel.type == .lunch) | ||
| #expect(shareModel.place == .cornerA) | ||
| } | ||
|
|
||
| @Test("날짜를 yyMMdd 형식으로 변환한다") | ||
| func 날짜를_yyMMdd_형식으로_변환한다() { | ||
| let item = DiningFixture.item(date: "2026-08-03") | ||
|
|
||
| let shareModel = item.toShareDiningItem() | ||
|
|
||
| #expect(shareModel.date == "260803") | ||
| } | ||
|
|
||
| @Test( | ||
| "날짜 변환에 실패하면 원본 문자열을 사용한다", | ||
| arguments: ["", "날짜없음", "2026-13-45"] | ||
| ) | ||
| func 날짜_변환에_실패하면_원본_문자열을_사용한다(invalidDate: String) { | ||
| let item = DiningFixture.item(date: invalidDate) | ||
|
|
||
| let shareModel = item.toShareDiningItem() | ||
|
|
||
| #expect(shareModel.date == invalidDate) | ||
| } | ||
|
|
||
| @Test("구분자가 달라도 파싱에 성공하면 yyMMdd로 변환된다") | ||
| func 구분자가_달라도_파싱에_성공하면_yyMMdd로_변환된다() { | ||
| let item = DiningFixture.item(date: "2026/08/03") | ||
|
|
||
| let shareModel = item.toShareDiningItem() | ||
|
|
||
| #expect(shareModel.date == "260803") | ||
| } | ||
|
|
||
| @Test("공유 모델을 레포지토리에 전달한다") | ||
| func 공유_모델을_레포지토리에_전달한다() throws { | ||
| let spy = SpyDiningRepository() | ||
| let sut = DefaultShareMenuListUseCase(diningRepository: spy) | ||
| let shareModel = DiningFixture.item( | ||
| date: "2026-08-03", | ||
| place: .cornerB, | ||
| menu: ["돈까스"], | ||
| imageUrl: "url2" | ||
| ).toShareDiningItem() | ||
|
|
||
| sut.execute(shareModel: shareModel) | ||
|
|
||
| #expect(spy.receivedShareModels.count == 1) | ||
| let received = try #require(spy.receivedShareModels.first) | ||
| #expect(received.menuList == shareModel.menuList) | ||
| #expect(received.imageUrl == shareModel.imageUrl) | ||
| #expect(received.date == shareModel.date) | ||
| #expect(received.place == shareModel.place) | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
Repository: BCSDLab/KOIN_iOS
Length of output: 11811
🏁 Script executed:
Repository: BCSDLab/KOIN_iOS
Length of output: 447
🏁 Script executed:
Repository: BCSDLab/KOIN_iOS
Length of output: 486
🏁 Script executed:
Repository: BCSDLab/KOIN_iOS
Length of output: 468
Don’t run
@testabletests from a Release scheme.koinUnitTestsuses@testable import koin, but thekoinRelease configuration does not enable testability. UseDebugforTestAction, or enableENABLE_TESTABILITY = YESforkoinonly in the Release build path used by tests.🤖 Prompt for AI Agents