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

[테스트] PersistenceStorage 작성 완료 #336

Merged
merged 3 commits into from
Dec 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions BBus/BBus.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,11 @@
4AF1E0C32756269F00DE51C8 /* BusRouteViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AF1E0C22756269F00DE51C8 /* BusRouteViewModelTests.swift */; };
4AF1E0D0275626A700DE51C8 /* AlarmSettingViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AF1E0CF275626A700DE51C8 /* AlarmSettingViewModelTests.swift */; };
4AF1E0DD275626B300DE51C8 /* MovingStatusViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AF1E0DC275626B300DE51C8 /* MovingStatusViewModelTests.swift */; };
4AF1E0E327566C8600DE51C8 /* PersistenceStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87038A8B273B96DF0078EAE3 /* PersistenceStorage.swift */; };
4AF1E0E42756725900DE51C8 /* PublisherExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A38E20827464015003A9D10 /* PublisherExtension.swift */; };
4AF1E0E62756734A00DE51C8 /* BBusAPIError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A38E20627463FF7003A9D10 /* BBusAPIError.swift */; };
4AF1E0E72756735B00DE51C8 /* FavoriteItemDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A06AEC7274159D10027222D /* FavoriteItemDTO.swift */; };
4AF1E0E827567DE100DE51C8 /* JsonDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0446843C275679B9007E440A /* JsonDTO.swift */; };
87038A82273B90A50078EAE3 /* BBusAPIUseCases.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87038A81273B90A50078EAE3 /* BBusAPIUseCases.swift */; };
87038A88273B950B0078EAE3 /* GetArrInfoByRouteListFetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87038A87273B950B0078EAE3 /* GetArrInfoByRouteListFetcher.swift */; };
87038A8A273B96B60078EAE3 /* NetworkService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87038A89273B96B60078EAE3 /* NetworkService.swift */; };
Expand Down Expand Up @@ -1694,6 +1699,11 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
4AF1E0E827567DE100DE51C8 /* JsonDTO.swift in Sources */,
4AF1E0E72756735B00DE51C8 /* FavoriteItemDTO.swift in Sources */,
4AF1E0E62756734A00DE51C8 /* BBusAPIError.swift in Sources */,
4AF1E0E42756725900DE51C8 /* PublisherExtension.swift in Sources */,
4AF1E0E327566C8600DE51C8 /* PersistenceStorage.swift in Sources */,
4AF1E0752756263400DE51C8 /* PersistenceStorageTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -2107,7 +2117,7 @@
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = B3PWYBKFUK;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
IPHONEOS_DEPLOYMENT_TARGET = 14.4;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand All @@ -2131,7 +2141,7 @@
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = B3PWYBKFUK;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
IPHONEOS_DEPLOYMENT_TARGET = 14.4;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand Down
197 changes: 186 additions & 11 deletions BBus/PersistenceStorageTests/PersistenceStorageTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,202 @@
//

import XCTest
import Combine

class PersistenceStorageTests: XCTestCase {

private let key: String = "PersistenceStorageTestKey"
private let key2: String = "PersistenceStorageTestKey2"
private let key3: String = "PersistenceStorageTestKey3"
private let key4: String = "PersistenceStorageTestKey4"
private let fileName: String = "BusRouteList"
private let fileType: String = "json"
private var cancellables: Set<AnyCancellable> = []

override func setUpWithError() throws {
// Put setup code here. This method is called before the invocation of each test method in the class.
self.cancellables = []
}

override func tearDownWithError() throws {
// Put teardown code here. This method is called after the invocation of each test method in the class.
struct DummyCodable: Codable, Equatable {
let dummy: String
}

func testExample() throws {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
func test_create_성공() {

//given
UserDefaults.standard.removeObject(forKey: self.key)
let storage = PersistenceStorage()
let param = DummyCodable(dummy: "dummy")
let expectation = self.expectation(description: "create가 에러 없이 정상 작동해야함")
var resultOpt: Data?

//when
storage.create(key: self.key, param: param)
.catchError { error in
XCTFail()
}
.sink { data in
resultOpt = data
expectation.fulfill()
}
.store(in: &self.cancellables)

//then
waitForExpectations(timeout: 2)
guard let result = resultOpt else { XCTFail(); return }
let decodedResultOpt = try? PropertyListDecoder().decode(DummyCodable.self, from: result)
guard let decodedResult = decodedResultOpt else { XCTFail(); return }
XCTAssertEqual(decodedResult, param, "생성하려는 객체가 정상적으로 리턴되지 않았습니다.")
}

func testPerformanceExample() throws {
// This is an example of a performance test case.
measure {
// Put the code you want to measure the time of here.
}
func test_getFromUserDefault_성공() {

//given
UserDefaults.standard.removeObject(forKey: self.key2)

let storage = PersistenceStorage()
let param = DummyCodable(dummy: "dummy")
let createExpect = self.expectation(description: "목 데이터 생성이 선행되어야 함")
let expectation = self.expectation(description: "getFromUserDefault가 에러 없이 정상 작동해야함")
var resultOpt: Data?

storage.create(key: self.key2, param: param)
.catchError { error in
XCTFail()
}
.sink { _ in
createExpect.fulfill()
}
.store(in: &self.cancellables)

wait(for: [createExpect], timeout: 5)
//when
storage.getFromUserDefaults(key: self.key2)
.catchError { error in
XCTFail()
}
.sink { data in
resultOpt = data
expectation.fulfill()
}
.store(in: &self.cancellables)

//then
wait(for: [expectation], timeout: 5)
guard let result = resultOpt else { XCTFail(); return }
let decodedResultOpt = try? PropertyListDecoder().decode([DummyCodable].self, from: result)
guard let decodedResult = decodedResultOpt else { XCTFail(); return }
XCTAssertEqual(decodedResult, [param], "저장된 객체를 불러오지 못했습니다.")
}

func test_getFromUserDefault_실패() {

//given
UserDefaults.standard.removeObject(forKey: self.key3)
let storage = PersistenceStorage()
let expectation = self.expectation(description: "데이터가 없기 때문에, getFromUserDefault가 작동하지않음")
var resultOpt: Data?

//when
storage.getFromUserDefaults(key: self.key3)
.catchError { error in
XCTFail()
}
.sink { data in
resultOpt = data
expectation.fulfill()
}
.store(in: &self.cancellables)

let emptyArrayDataOpt = try? PropertyListEncoder().encode([FavoriteItemDTO]())

//then
waitForExpectations(timeout: 5)
guard let result = resultOpt,
let emptyArrayData = emptyArrayDataOpt else { XCTFail(); return }
XCTAssertEqual(result, emptyArrayData, "저장된 데이터가 존재하면 안됩니다.")
}

func test_실제저장소_get_BusRouteList_수신성공() {

//given
let storage = PersistenceStorage()
let expectation = self.expectation(description: "PersistenceStorageRealGet")

//when
storage.get(file: self.fileName, type: self.fileType)
.catchError { error in
XCTFail()
}
.sink { _ in
expectation.fulfill()
}
.store(in: &self.cancellables)

//then
waitForExpectations(timeout: 2)
}

func test_실제저장소_get_BusRouteList_수신실패() {

//given
let storage = PersistenceStorage()
let expectation = self.expectation(description: "PersistenceStorageRealGet2")

//when
storage.get(file: "아무파일이름입니다.", type: self.fileType)
.catchError { error in
expectation.fulfill()
}
.sink { data in
XCTFail()
}
.store(in: &self.cancellables)

//then
waitForExpectations(timeout: 2)
}


func test_실제저장소_delete_성공() {
//given
UserDefaults.standard.removeObject(forKey: self.key4)
let storage = PersistenceStorage()
let expectation = self.expectation(description: "데이터를 delete 성공해야함")
var resultOpt: Data?
var params = [DummyCodable(dummy: "dummy1"), DummyCodable(dummy: "dummy2"), DummyCodable(dummy: "dummy3"), DummyCodable(dummy: "dummy4")]

for param in params {
let createExpect = self.expectation(description: "delete를 위한 목 데이터 생성이 완료되어야함")
storage.create(key: self.key4, param: param)
.catchError { error in
XCTFail()
}
.sink { _ in
// 동시접근 이슈
createExpect.fulfill()
}
.store(in: &self.cancellables)
wait(for: [createExpect], timeout: 5)
}

//when
storage.delete(key: self.key4, param: params[2])
.catchError { error in
XCTFail()
}
.sink { data in
resultOpt = data
expectation.fulfill()
}
.store(in: &self.cancellables)
params.remove(at: 2) // 배열에서도 제거, 비교하기 위함임

//then
wait(for: [expectation], timeout: 5)
guard let result = resultOpt else { XCTFail(); return }
let decodedResultOpt = try? PropertyListDecoder().decode([DummyCodable].self, from: result)
guard let decodedResult = decodedResultOpt else { XCTFail(); return }
XCTAssertEqual(params, decodedResult, "제거된 데이터와 상이합니다.")
}
}