Skip to content
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

[TEST] Today Unit test 작성 (#197) #201

Merged
merged 9 commits into from
Dec 3, 2023
52 changes: 49 additions & 3 deletions LionHeart-iOS/LionHeart-iOS.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,17 @@
B59BFD3F2ADBBF2B005D2D81 /* CurriculumFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = B59BFD3E2ADBBF2B005D2D81 /* CurriculumFactory.swift */; };
B59BFD412ADBBFB2005D2D81 /* MyPageFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = B59BFD402ADBBFB2005D2D81 /* MyPageFactory.swift */; };
B59BFD432ADBBFF5005D2D81 /* ArticleFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = B59BFD422ADBBFF5005D2D81 /* ArticleFactory.swift */; };
B59FC6A52B1893E9000996CA /* TodayServiceTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B59FC6A42B1893E9000996CA /* TodayServiceTest.swift */; };
B59FC6A72B18A3EE000996CA /* TodayArticleSuccess.json in Resources */ = {isa = PBXBuildFile; fileRef = B59FC6A62B18A3EE000996CA /* TodayArticleSuccess.json */; };
B59FC6A92B18C48F000996CA /* TodayViewModelSpy.swift in Sources */ = {isa = PBXBuildFile; fileRef = B59FC6A82B18C48F000996CA /* TodayViewModelSpy.swift */; };
B59FC6B02B19AAF2000996CA /* TodayViewModelSetUp.swift in Sources */ = {isa = PBXBuildFile; fileRef = B59FC6AF2B19AAF2000996CA /* TodayViewModelSetUp.swift */; };
B59FC6B22B19AB5C000996CA /* TodayNavigationSpy.swift in Sources */ = {isa = PBXBuildFile; fileRef = B59FC6B12B19AB5C000996CA /* TodayNavigationSpy.swift */; };
B59FC6B42B19AC7B000996CA /* TodayManagerStub.swift in Sources */ = {isa = PBXBuildFile; fileRef = B59FC6B32B19AC7B000996CA /* TodayManagerStub.swift */; };
B59FC6B62B19AD7D000996CA /* TodayViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B59FC6B52B19AD7D000996CA /* TodayViewModelTests.swift */; };
B59FC6B82B19B525000996CA /* TodayClientError.json in Resources */ = {isa = PBXBuildFile; fileRef = B59FC6B72B19B525000996CA /* TodayClientError.json */; };
B59FC6BF2B19FA2F000996CA /* TodayServerError.json in Resources */ = {isa = PBXBuildFile; fileRef = B59FC6BE2B19FA2F000996CA /* TodayServerError.json */; };
B59FC6C12B1A0A04000996CA /* TodayArticleEmptyData.json in Resources */ = {isa = PBXBuildFile; fileRef = B59FC6C02B1A0A04000996CA /* TodayArticleEmptyData.json */; };
B59FC6C52B1B8D21000996CA /* TodayViewControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B59FC6C42B1B8D21000996CA /* TodayViewControllerTests.swift */; };
B5BE51C12B15B8F100042EF3 /* ServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BE51C02B15B8F100042EF3 /* ServiceTests.swift */; };
B5BE51C72B15C75F00042EF3 /* URLSessionStub.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BE51C62B15C75F00042EF3 /* URLSessionStub.swift */; };
B5BE51C92B15CB9600042EF3 /* JSONLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BE51C82B15CB9600042EF3 /* JSONLoader.swift */; };
Expand Down Expand Up @@ -479,6 +490,18 @@
B59BFD3E2ADBBF2B005D2D81 /* CurriculumFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurriculumFactory.swift; sourceTree = "<group>"; };
B59BFD402ADBBFB2005D2D81 /* MyPageFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyPageFactory.swift; sourceTree = "<group>"; };
B59BFD422ADBBFF5005D2D81 /* ArticleFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleFactory.swift; sourceTree = "<group>"; };
B59FC6A42B1893E9000996CA /* TodayServiceTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayServiceTest.swift; sourceTree = "<group>"; };
B59FC6A62B18A3EE000996CA /* TodayArticleSuccess.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = TodayArticleSuccess.json; sourceTree = "<group>"; };
B59FC6A82B18C48F000996CA /* TodayViewModelSpy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayViewModelSpy.swift; sourceTree = "<group>"; };
B59FC6AE2B1981EB000996CA /* LionHeart-iOS.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = "LionHeart-iOS.xctestplan"; sourceTree = "<group>"; };
B59FC6AF2B19AAF2000996CA /* TodayViewModelSetUp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayViewModelSetUp.swift; sourceTree = "<group>"; };
B59FC6B12B19AB5C000996CA /* TodayNavigationSpy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayNavigationSpy.swift; sourceTree = "<group>"; };
B59FC6B32B19AC7B000996CA /* TodayManagerStub.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayManagerStub.swift; sourceTree = "<group>"; };
B59FC6B52B19AD7D000996CA /* TodayViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayViewModelTests.swift; sourceTree = "<group>"; };
B59FC6B72B19B525000996CA /* TodayClientError.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = TodayClientError.json; sourceTree = "<group>"; };
B59FC6BE2B19FA2F000996CA /* TodayServerError.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = TodayServerError.json; sourceTree = "<group>"; };
B59FC6C02B1A0A04000996CA /* TodayArticleEmptyData.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = TodayArticleEmptyData.json; sourceTree = "<group>"; };
B59FC6C42B1B8D21000996CA /* TodayViewControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayViewControllerTests.swift; sourceTree = "<group>"; };
B5BE51C02B15B8F100042EF3 /* ServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServiceTests.swift; sourceTree = "<group>"; };
B5BE51C62B15C75F00042EF3 /* URLSessionStub.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLSessionStub.swift; sourceTree = "<group>"; };
B5BE51C82B15CB9600042EF3 /* JSONLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSONLoader.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -890,6 +913,7 @@
B532E8252A5525C600F0DB19 = {
isa = PBXGroup;
children = (
B59FC6AE2B1981EB000996CA /* LionHeart-iOS.xctestplan */,
B532E8302A5525C600F0DB19 /* LionHeart-iOS */,
B532E8472A5525C800F0DB19 /* LionHeart-iOSTests */,
B532E8512A5525C800F0DB19 /* LionHeart-iOSUITests */,
Expand Down Expand Up @@ -1453,7 +1477,7 @@
children = (
B5BE51CD2B15CC5300042EF3 /* JSON */,
B5BE51CF2B15CC5B00042EF3 /* ServiceTests */,
B5BE51CE2B15CC5700042EF3 /* ViewModelStub */,
B5BE51CE2B15CC5700042EF3 /* ViewModelTests */,
B5BE51D02B15CC5F00042EF3 /* ViewControllerTests */,
);
path = Today;
Expand Down Expand Up @@ -1500,27 +1524,38 @@
B5BE51CD2B15CC5300042EF3 /* JSON */ = {
isa = PBXGroup;
children = (
B59FC6A62B18A3EE000996CA /* TodayArticleSuccess.json */,
B59FC6B72B19B525000996CA /* TodayClientError.json */,
B59FC6BE2B19FA2F000996CA /* TodayServerError.json */,
B59FC6C02B1A0A04000996CA /* TodayArticleEmptyData.json */,
);
path = JSON;
sourceTree = "<group>";
};
B5BE51CE2B15CC5700042EF3 /* ViewModelStub */ = {
B5BE51CE2B15CC5700042EF3 /* ViewModelTests */ = {
isa = PBXGroup;
children = (
B59FC6B32B19AC7B000996CA /* TodayManagerStub.swift */,
B59FC6B12B19AB5C000996CA /* TodayNavigationSpy.swift */,
B59FC6AF2B19AAF2000996CA /* TodayViewModelSetUp.swift */,
B59FC6B52B19AD7D000996CA /* TodayViewModelTests.swift */,
);
path = ViewModelStub;
path = ViewModelTests;
sourceTree = "<group>";
};
B5BE51CF2B15CC5B00042EF3 /* ServiceTests */ = {
isa = PBXGroup;
children = (
B59FC6A42B1893E9000996CA /* TodayServiceTest.swift */,
);
path = ServiceTests;
sourceTree = "<group>";
};
B5BE51D02B15CC5F00042EF3 /* ViewControllerTests */ = {
isa = PBXGroup;
children = (
B59FC6A82B18C48F000996CA /* TodayViewModelSpy.swift */,
B59FC6C42B1B8D21000996CA /* TodayViewControllerTests.swift */,
);
path = ViewControllerTests;
sourceTree = "<group>";
Expand Down Expand Up @@ -2270,6 +2305,10 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B59FC6BF2B19FA2F000996CA /* TodayServerError.json in Resources */,
B59FC6B82B19B525000996CA /* TodayClientError.json in Resources */,
B59FC6A72B18A3EE000996CA /* TodayArticleSuccess.json in Resources */,
B59FC6C12B1A0A04000996CA /* TodayArticleEmptyData.json in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -2588,9 +2627,16 @@
buildActionMask = 2147483647;
files = (
B5BE51C92B15CB9600042EF3 /* JSONLoader.swift in Sources */,
B59FC6B02B19AAF2000996CA /* TodayViewModelSetUp.swift in Sources */,
B59FC6B42B19AC7B000996CA /* TodayManagerStub.swift in Sources */,
C034EDE02ADE3A4A00AD6FF3 /* LionHeart_iOSTests.swift in Sources */,
B59FC6B62B19AD7D000996CA /* TodayViewModelTests.swift in Sources */,
B5BE51C12B15B8F100042EF3 /* ServiceTests.swift in Sources */,
B59FC6C52B1B8D21000996CA /* TodayViewControllerTests.swift in Sources */,
B59FC6A92B18C48F000996CA /* TodayViewModelSpy.swift in Sources */,
B5BE51C72B15C75F00042EF3 /* URLSessionStub.swift in Sources */,
B59FC6A52B1893E9000996CA /* TodayServiceTest.swift in Sources */,
B59FC6B22B19AB5C000996CA /* TodayNavigationSpy.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,13 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
shouldUseLaunchSchemeArgsEnv = "YES">
<TestPlans>
<TestPlanReference
reference = "container:LionHeart-iOS.xctestplan"
default = "YES">
</TestPlanReference>
</TestPlans>
<Testables>
<TestableReference
skipped = "NO"
Expand All @@ -41,7 +46,7 @@
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO"
skipped = "YES"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
Expand Down
37 changes: 37 additions & 0 deletions LionHeart-iOS/LionHeart-iOS.xctestplan
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"configurations" : [
{
"id" : "ECF67E50-99EF-455F-8688-CA85B659EE79",
"name" : "Test Scheme Action",
"options" : {

}
}
],
"defaultOptions" : {
"targetForVariableExpansion" : {
"containerPath" : "container:LionHeart-iOS.xcodeproj",
"identifier" : "B532E82D2A5525C600F0DB19",
"name" : "LionHeart-iOS"
}
},
"testTargets" : [
{
"target" : {
"containerPath" : "container:LionHeart-iOS.xcodeproj",
"identifier" : "B532E8432A5525C800F0DB19",
"name" : "LionHeart-iOSTests"
}
},
{
"enabled" : false,
"parallelizable" : true,
"target" : {
"containerPath" : "container:LionHeart-iOS.xcodeproj",
"identifier" : "B532E84D2A5525C800F0DB19",
"name" : "LionHeart-iOSUITests"
}
}
],
"version" : 1
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import Foundation

@frozen
enum NetworkError: Error, CustomStringConvertible {
enum NetworkError: Error, CustomStringConvertible, Equatable {
case urlEncodingError
case jsonDecodingError
case badCasting
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import UIKit

struct TodayArticle: AppData {
struct TodayArticle: Equatable, AppData {
var fetalNickname: String
var articleTitle: String
var articleDescription: String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,17 @@ protocol TodayViewControllerable where Self: UIViewController {}

final class TodayViewController: UIViewController, TodayViewControllerable {

private lazy var todayNavigationBar = LHNavigationBarView(type: .today, viewController: self)
private var titleLabel = LHTodayArticleTitle()
lazy var todayNavigationBar = LHNavigationBarView(type: .today, viewController: self)
var titleLabel = LHTodayArticleTitle()
private var subTitleLable = LHTodayArticleTitle(initalizeString: "오늘의 아티클이에요")
private var mainArticleView = TodayArticleView()
var mainArticleView = TodayArticleView()
private var pointImage = LHImageView(in: UIImage(named: "TodayArticle_PointImage"), contentMode: .scaleAspectFit)

private let viewModel: any TodayViewModel
private let viewWillAppearSubject = PassthroughSubject<Void, Never>()
private let navigationLeftButtonTapped = PassthroughSubject<Void, Never>()
private let navigationRightButtonTapped = PassthroughSubject<Void, Never>()
private let todayArticleTapped = PassthroughSubject<Void, Never>()
let viewWillAppearSubject = PassthroughSubject<Void, Never>()
let navigationLeftButtonTapped = PassthroughSubject<Void, Never>()
let navigationRightButtonTapped = PassthroughSubject<Void, Never>()
let todayArticleTapped = PassthroughSubject<Void, Never>()
private var cancelBag = Set<AnyCancellable>()

init(viewModel: some TodayViewModel) {
Expand Down Expand Up @@ -54,15 +54,21 @@ final class TodayViewController: UIViewController, TodayViewControllerable {

func bindInput() {
self.todayNavigationBar.rightFirstBarItem.tapPublisher
.sink { [weak self] in self?.navigationLeftButtonTapped.send(()) }
.sink { [weak self] in
self?.navigationLeftButtonTapped.send(())
}
.store(in: &cancelBag)

self.todayNavigationBar.rightSecondBarItem.tapPublisher
.sink { [weak self] in self?.navigationRightButtonTapped.send(()) }
.sink { [weak self] in
self?.navigationRightButtonTapped.send(())
}
.store(in: &cancelBag)

self.mainArticleView.tabPublisher
.sink { [weak self] in self?.todayArticleTapped.send(()) }
.sink { [weak self] in
self?.todayArticleTapped.send(())
}
.store(in: &cancelBag)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,20 @@ import Combine

final class TodayViewModelImpl: TodayViewModel, TodayViewModelPresentable {

private enum FlowType { case bookmarkButtonTapped, myPageButtonTapped }
enum FlowType: Equatable {
case bookmarkButtonTapped
case myPageButtonTapped
case articleTapped(articleId: Int)
}

private let navigator: TodayNavigation
private let manager: TodayManager

private let navigationSubject = PassthroughSubject<FlowType, Never>()
let navigationSubject = PassthroughSubject<FlowType, Never>()
let errorSubject = PassthroughSubject<NetworkError, Never>()

private var cancelBag = Set<AnyCancellable>()
private var articleID: Int?
var articleID: Int?

init(navigator: TodayNavigation, manager: TodayManager) {
self.navigator = navigator
Expand All @@ -26,14 +32,23 @@ final class TodayViewModelImpl: TodayViewModel, TodayViewModelPresentable {

func transform(input: TodayViewModelInput) -> TodayViewModelOutput {

self.errorSubject
.sink {
print($0)
}
.store(in: &cancelBag)

self.navigationSubject
.receive(on: RunLoop.main)
.sink { [weak self] in
guard let self else { return }
switch $0 {
case .bookmarkButtonTapped:
self?.navigator.navigationLeftButtonTapped()
self.navigator.navigationLeftButtonTapped()
case .myPageButtonTapped:
self?.navigator.navigationRightButtonTapped()
self.navigator.navigationRightButtonTapped()
case .articleTapped(let articleId):
self.navigator.todayArticleTapped(articleID: articleId)
}
}
.store(in: &cancelBag)
Expand All @@ -48,8 +63,10 @@ final class TodayViewModelImpl: TodayViewModel, TodayViewModelPresentable {

input.todayArticleTapped
.sink { [weak self] in
guard let articleID = self?.articleID else { return }
self?.navigator.todayArticleTapped(articleID: articleID)
guard let articleID = self?.articleID else {
return
}
self?.navigationSubject.send(.articleTapped(articleId: articleID))
}
.store(in: &cancelBag)

Expand All @@ -68,7 +85,8 @@ final class TodayViewModelImpl: TodayViewModel, TodayViewModelPresentable {
}
}
.catch { error in
Just(TodayArticle.emptyArticle)
self.errorSubject.send(error)
return Just(TodayArticle.emptyArticle)
}
.eraseToAnyPublisher()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ import SnapKit
final class TodayArticleView: UIView {

private let backgroundView = LHView(color: .designSystem(.black)?.withAlphaComponent(0.7)).makeRound(4)
private var weekInfomationLabel = LHLabel(type: .body2R, color: .componentLionRed)
private var articleTitleLabel = LHLabel(type: .head2, color: .white, lines: 0)
private var descriptionLabel = LHLabel(type: .body2R, color: .gray400, lines: 3)
var weekInfomationLabel = LHLabel(type: .body2R, color: .componentLionRed)
var articleTitleLabel = LHLabel(type: .head2, color: .white, lines: 0)
var descriptionLabel = LHLabel(type: .body2R, color: .gray400, lines: 3)
private var weekInfomationView = LHImageView(in: UIImage(named: "today_test_label"), contentMode: .scaleAspectFill)
private var mainArticlImageView = LHImageView(contentMode: .scaleAspectFill).makeRound(4)
var mainArticlImageView = LHImageView(contentMode: .scaleAspectFill).makeRound(4)
private var seperateLine = LHImageView(in: UIImage(named: "MainArticleSeperateLine"), contentMode: .scaleAspectFill)

override init(frame: CGRect) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"code": "N003",
"message": "아티클의 컨텐츠가 존재하지 않습니다."
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"code": "string",
"message": "string",
"data": {
"articleId": 0,
"babyNickname": "minjae",
"title": "TITLE",
"mainImageUrl": "string",
"editorNoteContent": "editornote",
"week": 0,
"day": 0
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"code": "N003",
"message": "클라이언트 에러입니다."
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"code": "I001",
"message": "서버 에러가 발생했습니다."
}

Loading