Skip to content

Commit

Permalink
test: FruitStore use 테스트 코드 작성 #1
Browse files Browse the repository at this point in the history
- FruitStore checkInventory 오류 수정
- FruitStore calculateUsableInventory 함수 분리
  • Loading branch information
김정상 committed Feb 15, 2022
1 parent 40c67e5 commit 2d6f417
Show file tree
Hide file tree
Showing 3 changed files with 227 additions and 14 deletions.
127 changes: 126 additions & 1 deletion JuiceMaker/JuiceMaker.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

/* Begin PBXBuildFile section */
73B6685227BBE7CE005CF6E3 /* FruitType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73B6685127BBE7CE005CF6E3 /* FruitType.swift */; };
73B6686127BC026A005CF6E3 /* FruitStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73B6685927BBFEE3005CF6E3 /* FruitStoreTests.swift */; };
C71CD66B266C7ACB0038B9CB /* FruitStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = C71CD66A266C7ACB0038B9CB /* FruitStore.swift */; };
C73DAF37255D0CDD00020D38 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C73DAF36255D0CDD00020D38 /* AppDelegate.swift */; };
C73DAF39255D0CDD00020D38 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C73DAF38255D0CDD00020D38 /* SceneDelegate.swift */; };
Expand All @@ -18,8 +19,20 @@
C73DAF4C255D0D0400020D38 /* JuiceMaker.swift in Sources */ = {isa = PBXBuildFile; fileRef = C73DAF4B255D0D0400020D38 /* JuiceMaker.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
73B6685B27BBFEE3005CF6E3 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = C73DAF2B255D0CDC00020D38 /* Project object */;
proxyType = 1;
remoteGlobalIDString = C73DAF32255D0CDC00020D38;
remoteInfo = JuiceMaker;
};
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
73B6685127BBE7CE005CF6E3 /* FruitType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FruitType.swift; sourceTree = "<group>"; };
73B6685727BBFEE3005CF6E3 /* JuiceMakerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = JuiceMakerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
73B6685927BBFEE3005CF6E3 /* FruitStoreTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FruitStoreTests.swift; sourceTree = "<group>"; };
C71CD66A266C7ACB0038B9CB /* FruitStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FruitStore.swift; sourceTree = "<group>"; };
C73DAF33255D0CDD00020D38 /* JuiceMaker.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JuiceMaker.app; sourceTree = BUILT_PRODUCTS_DIR; };
C73DAF36255D0CDD00020D38 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
Expand All @@ -33,6 +46,13 @@
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
73B6685427BBFEE3005CF6E3 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
C73DAF30255D0CDC00020D38 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
Expand All @@ -43,6 +63,14 @@
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
73B6685827BBFEE3005CF6E3 /* JuiceMakerTests */ = {
isa = PBXGroup;
children = (
73B6685927BBFEE3005CF6E3 /* FruitStoreTests.swift */,
);
path = JuiceMakerTests;
sourceTree = "<group>";
};
C71CD66D266C7B470038B9CB /* Controller */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -77,6 +105,7 @@
isa = PBXGroup;
children = (
C73DAF35255D0CDD00020D38 /* JuiceMaker */,
73B6685827BBFEE3005CF6E3 /* JuiceMakerTests */,
C73DAF34255D0CDD00020D38 /* Products */,
);
sourceTree = "<group>";
Expand All @@ -85,6 +114,7 @@
isa = PBXGroup;
children = (
C73DAF33255D0CDD00020D38 /* JuiceMaker.app */,
73B6685727BBFEE3005CF6E3 /* JuiceMakerTests.xctest */,
);
name = Products;
sourceTree = "<group>";
Expand All @@ -103,6 +133,24 @@
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
73B6685627BBFEE3005CF6E3 /* JuiceMakerTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 73B6685D27BBFEE3005CF6E3 /* Build configuration list for PBXNativeTarget "JuiceMakerTests" */;
buildPhases = (
73B6685327BBFEE3005CF6E3 /* Sources */,
73B6685427BBFEE3005CF6E3 /* Frameworks */,
73B6685527BBFEE3005CF6E3 /* Resources */,
);
buildRules = (
);
dependencies = (
73B6685C27BBFEE3005CF6E3 /* PBXTargetDependency */,
);
name = JuiceMakerTests;
productName = JuiceMakerTests;
productReference = 73B6685727BBFEE3005CF6E3 /* JuiceMakerTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
C73DAF32255D0CDC00020D38 /* JuiceMaker */ = {
isa = PBXNativeTarget;
buildConfigurationList = C73DAF47255D0CDF00020D38 /* Build configuration list for PBXNativeTarget "JuiceMaker" */;
Expand All @@ -126,9 +174,13 @@
C73DAF2B255D0CDC00020D38 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1200;
LastSwiftUpdateCheck = 1320;
LastUpgradeCheck = 1200;
TargetAttributes = {
73B6685627BBFEE3005CF6E3 = {
CreatedOnToolsVersion = 13.2.1;
TestTargetID = C73DAF32255D0CDC00020D38;
};
C73DAF32255D0CDC00020D38 = {
CreatedOnToolsVersion = 12.0;
};
Expand All @@ -148,11 +200,19 @@
projectRoot = "";
targets = (
C73DAF32255D0CDC00020D38 /* JuiceMaker */,
73B6685627BBFEE3005CF6E3 /* JuiceMakerTests */,
);
};
/* End PBXProject section */

/* Begin PBXResourcesBuildPhase section */
73B6685527BBFEE3005CF6E3 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
C73DAF31255D0CDC00020D38 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
Expand All @@ -166,6 +226,14 @@
/* End PBXResourcesBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
73B6685327BBFEE3005CF6E3 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
73B6686127BC026A005CF6E3 /* FruitStoreTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
C73DAF2F255D0CDC00020D38 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
Expand All @@ -181,6 +249,14 @@
};
/* End PBXSourcesBuildPhase section */

/* Begin PBXTargetDependency section */
73B6685C27BBFEE3005CF6E3 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = C73DAF32255D0CDC00020D38 /* JuiceMaker */;
targetProxy = 73B6685B27BBFEE3005CF6E3 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */

/* Begin PBXVariantGroup section */
C73DAF3C255D0CDD00020D38 /* Main.storyboard */ = {
isa = PBXVariantGroup;
Expand All @@ -201,6 +277,46 @@
/* End PBXVariantGroup section */

/* Begin XCBuildConfiguration section */
73B6685E27BBFEE3005CF6E3 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = QQF2SQ9MZZ;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.2;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.topkim.JuiceMakerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/JuiceMaker.app/JuiceMaker";
};
name = Debug;
};
73B6685F27BBFEE3005CF6E3 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = QQF2SQ9MZZ;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.2;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.topkim.JuiceMakerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/JuiceMaker.app/JuiceMaker";
};
name = Release;
};
C73DAF45255D0CDF00020D38 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
Expand Down Expand Up @@ -356,6 +472,15 @@
/* End XCBuildConfiguration section */

/* Begin XCConfigurationList section */
73B6685D27BBFEE3005CF6E3 /* Build configuration list for PBXNativeTarget "JuiceMakerTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
73B6685E27BBFEE3005CF6E3 /* Debug */,
73B6685F27BBFEE3005CF6E3 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
C73DAF2E255D0CDC00020D38 /* Build configuration list for PBXProject "JuiceMaker" */ = {
isa = XCConfigurationList;
buildConfigurations = (
Expand Down
27 changes: 14 additions & 13 deletions JuiceMaker/JuiceMaker/Model/FruitStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,36 +21,37 @@ extension FruitStoreError: LocalizedError {

/// 과일 저장소 타입
struct FruitStore {
private var inventory = [FruitType: Int]()
private(set) var inventory = [FruitType: Int]()

init(initialFruitCount: Int = 10) {
FruitType.allCases.forEach { fruit in
inventory[fruit] = initialFruitCount
}
}

func updateInventory(of fruits: [FruitType: Int]) -> Result<Void, Error> {
let result = checkInventory(of: fruits)

switch result {
mutating func use(of fruitTypes: [FruitType: Int]) -> Result<Void, FruitStoreError> {
let checkedInventory = checkInventory(of: fruitTypes)
switch checkedInventory {
case .success():
inventory = calculateUsableInventory(toSubtract: fruitTypes)
return .success(Void())
case .failure(let error):
return .failure(error)
}
}

private func checkInventory(of fruits: [FruitType: Int]) -> Result<Void, FruitStoreError> {
let result = inventory
.merging(fruits, uniquingKeysWith: {
$0 + $1
})
private func checkInventory(of fruitTypes: [FruitType: Int]) -> Result<Void, FruitStoreError> {
let negativeFruitTypes = calculateUsableInventory(toSubtract: fruitTypes)
.filter { $0.value < 0 }

guard result.count < 0 else {
guard negativeFruitTypes.count < 1 else {
return .failure(.notEnoughFruits)
}

return .success(Void())
}

private func calculateUsableInventory(toSubtract fruitTypes: [FruitType: Int]) -> [FruitType: Int] {
return inventory.merging(fruitTypes, uniquingKeysWith: {
$0 - $1
})
}
}
87 changes: 87 additions & 0 deletions JuiceMaker/JuiceMakerTests/FruitStoreTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
//
// FruitStoreTests.swift
// FruitStoreTests
//
// Created by 김정상 on 2022/02/16.
//

import XCTest
@testable import JuiceMaker

class FruitStoreTests: XCTestCase {

// MARK: - Property

private var fruitStore: FruitStore?


// MARK: - Overrides

override func setUpWithError() throws {
try super.setUpWithError()
fruitStore = FruitStore()
}

override func tearDownWithError() throws {
try super.tearDownWithError()
fruitStore = nil
}


// MARK: - Test codes

func test_인벤토리보다_적은과일을_사용했을때_성공을_반환하는가() {
// given
guard var fruitStore = fruitStore else {
XCTFail()
return
}
let input: [FruitType: Int] = [
.banana: 5,
.strawberry: 5
]
let expected: [FruitType: Int] = [
.strawberry: 5,
.banana: 5,
.pineapple: 10,
.kiwi: 10,
.mango: 10
]

// when
let writeResult = fruitStore.use(of: input)

// then
switch writeResult {
case .success(_):
XCTAssertEqual(fruitStore.inventory, expected)
case .failure(let error):
XCTFail(error.localizedDescription)
}
}

func test_인벤토리보다_많은과일을_사용했을때_실패을_반환하는가() {
// given
guard var fruitStore = fruitStore else {
XCTFail()
return
}
let input: [FruitType: Int] = [
.banana: 5,
.strawberry: 15
]
let expected = FruitStoreError.notEnoughFruits

// when
let writeResult = fruitStore.use(of: input)

// then
switch writeResult {
case .success(_):
XCTFail()
case .failure(let error):
XCTAssertEqual(expected, error)
}
}

}

0 comments on commit 2d6f417

Please sign in to comment.