diff --git a/CalculatorTest/CalculatorTest.xcodeproj/project.pbxproj b/CalculatorTest/CalculatorTest.xcodeproj/project.pbxproj new file mode 100644 index 0000000..1edc1b6 --- /dev/null +++ b/CalculatorTest/CalculatorTest.xcodeproj/project.pbxproj @@ -0,0 +1,575 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 77; + objects = { + +/* Begin PBXContainerItemProxy section */ + 33A5D54D2EFEB7030049557E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33A5D5372EFEB7000049557E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33A5D53E2EFEB7000049557E; + remoteInfo = CalculatorTest; + }; + 33A5D5572EFEB7040049557E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33A5D5372EFEB7000049557E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33A5D53E2EFEB7000049557E; + remoteInfo = CalculatorTest; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 33A5D53F2EFEB7000049557E /* CalculatorTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CalculatorTest.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 33A5D54C2EFEB7030049557E /* CalculatorTestTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CalculatorTestTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 33A5D5562EFEB7040049557E /* CalculatorTestUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CalculatorTestUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ + 33A5D5792EFECAE20049557E /* Exceptions for "CalculatorTest" folder in "CalculatorTestTests" target */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + CalculatorApp.swift, + CalculatorButtonView.swift, + CalculatorModel.swift, + CalculatorView.swift, + CalculatorViewModel.swift, + ); + target = 33A5D54B2EFEB7030049557E /* CalculatorTestTests */; + }; + 33A5D57A2EFECAE20049557E /* Exceptions for "CalculatorTest" folder in "CalculatorTestUITests" target */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + CalculatorApp.swift, + CalculatorButtonView.swift, + CalculatorModel.swift, + CalculatorView.swift, + CalculatorViewModel.swift, + ); + target = 33A5D5552EFEB7040049557E /* CalculatorTestUITests */; + }; +/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */ + +/* Begin PBXFileSystemSynchronizedRootGroup section */ + 33A5D5412EFEB7000049557E /* CalculatorTest */ = { + isa = PBXFileSystemSynchronizedRootGroup; + exceptions = ( + 33A5D5792EFECAE20049557E /* Exceptions for "CalculatorTest" folder in "CalculatorTestTests" target */, + 33A5D57A2EFECAE20049557E /* Exceptions for "CalculatorTest" folder in "CalculatorTestUITests" target */, + ); + path = CalculatorTest; + sourceTree = ""; + }; + 33A5D54F2EFEB7030049557E /* CalculatorTestTests */ = { + isa = PBXFileSystemSynchronizedRootGroup; + path = CalculatorTestTests; + sourceTree = ""; + }; +/* End PBXFileSystemSynchronizedRootGroup section */ + +/* Begin PBXFrameworksBuildPhase section */ + 33A5D53C2EFEB7000049557E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33A5D5492EFEB7030049557E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33A5D5532EFEB7040049557E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 33A5D5362EFEB7000049557E = { + isa = PBXGroup; + children = ( + 33A5D5412EFEB7000049557E /* CalculatorTest */, + 33A5D54F2EFEB7030049557E /* CalculatorTestTests */, + 33A5D5402EFEB7000049557E /* Products */, + ); + sourceTree = ""; + }; + 33A5D5402EFEB7000049557E /* Products */ = { + isa = PBXGroup; + children = ( + 33A5D53F2EFEB7000049557E /* CalculatorTest.app */, + 33A5D54C2EFEB7030049557E /* CalculatorTestTests.xctest */, + 33A5D5562EFEB7040049557E /* CalculatorTestUITests.xctest */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 33A5D53E2EFEB7000049557E /* CalculatorTest */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33A5D5602EFEB7040049557E /* Build configuration list for PBXNativeTarget "CalculatorTest" */; + buildPhases = ( + 33A5D53B2EFEB7000049557E /* Sources */, + 33A5D53C2EFEB7000049557E /* Frameworks */, + 33A5D53D2EFEB7000049557E /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + fileSystemSynchronizedGroups = ( + 33A5D5412EFEB7000049557E /* CalculatorTest */, + ); + name = CalculatorTest; + packageProductDependencies = ( + ); + productName = CalculatorTest; + productReference = 33A5D53F2EFEB7000049557E /* CalculatorTest.app */; + productType = "com.apple.product-type.application"; + }; + 33A5D54B2EFEB7030049557E /* CalculatorTestTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33A5D5632EFEB7040049557E /* Build configuration list for PBXNativeTarget "CalculatorTestTests" */; + buildPhases = ( + 33A5D5482EFEB7030049557E /* Sources */, + 33A5D5492EFEB7030049557E /* Frameworks */, + 33A5D54A2EFEB7030049557E /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 33A5D54E2EFEB7030049557E /* PBXTargetDependency */, + ); + fileSystemSynchronizedGroups = ( + 33A5D54F2EFEB7030049557E /* CalculatorTestTests */, + ); + name = CalculatorTestTests; + packageProductDependencies = ( + ); + productName = CalculatorTestTests; + productReference = 33A5D54C2EFEB7030049557E /* CalculatorTestTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 33A5D5552EFEB7040049557E /* CalculatorTestUITests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33A5D5662EFEB7040049557E /* Build configuration list for PBXNativeTarget "CalculatorTestUITests" */; + buildPhases = ( + 33A5D5522EFEB7040049557E /* Sources */, + 33A5D5532EFEB7040049557E /* Frameworks */, + 33A5D5542EFEB7040049557E /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 33A5D5582EFEB7040049557E /* PBXTargetDependency */, + ); + name = CalculatorTestUITests; + packageProductDependencies = ( + ); + productName = CalculatorTestUITests; + productReference = 33A5D5562EFEB7040049557E /* CalculatorTestUITests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33A5D5372EFEB7000049557E /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1640; + LastUpgradeCheck = 1640; + TargetAttributes = { + 33A5D53E2EFEB7000049557E = { + CreatedOnToolsVersion = 16.4; + }; + 33A5D54B2EFEB7030049557E = { + CreatedOnToolsVersion = 16.4; + TestTargetID = 33A5D53E2EFEB7000049557E; + }; + 33A5D5552EFEB7040049557E = { + CreatedOnToolsVersion = 16.4; + TestTargetID = 33A5D53E2EFEB7000049557E; + }; + }; + }; + buildConfigurationList = 33A5D53A2EFEB7000049557E /* Build configuration list for PBXProject "CalculatorTest" */; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33A5D5362EFEB7000049557E; + minimizedProjectReferenceProxies = 1; + preferredProjectObjectVersion = 77; + productRefGroup = 33A5D5402EFEB7000049557E /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33A5D53E2EFEB7000049557E /* CalculatorTest */, + 33A5D54B2EFEB7030049557E /* CalculatorTestTests */, + 33A5D5552EFEB7040049557E /* CalculatorTestUITests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 33A5D53D2EFEB7000049557E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33A5D54A2EFEB7030049557E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33A5D5542EFEB7040049557E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 33A5D53B2EFEB7000049557E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33A5D5482EFEB7030049557E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33A5D5522EFEB7040049557E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 33A5D54E2EFEB7030049557E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33A5D53E2EFEB7000049557E /* CalculatorTest */; + targetProxy = 33A5D54D2EFEB7030049557E /* PBXContainerItemProxy */; + }; + 33A5D5582EFEB7040049557E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33A5D53E2EFEB7000049557E /* CalculatorTest */; + targetProxy = 33A5D5572EFEB7040049557E /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 33A5D55E2EFEB7040049557E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 18.5; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33A5D55F2EFEB7040049557E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 18.5; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 33A5D5612EFEB7040049557E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = yeonnies.CalculatorTest; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 33A5D5622EFEB7040049557E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = yeonnies.CalculatorTest; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 33A5D5642EFEB7040049557E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 18.5; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = yeonnies.CalculatorTestTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CalculatorTest.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/CalculatorTest"; + }; + name = Debug; + }; + 33A5D5652EFEB7040049557E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 18.5; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = yeonnies.CalculatorTestTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CalculatorTest.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/CalculatorTest"; + }; + name = Release; + }; + 33A5D5672EFEB7040049557E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = yeonnies.CalculatorTestUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = CalculatorTest; + }; + name = Debug; + }; + 33A5D5682EFEB7040049557E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = yeonnies.CalculatorTestUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = CalculatorTest; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 33A5D53A2EFEB7000049557E /* Build configuration list for PBXProject "CalculatorTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33A5D55E2EFEB7040049557E /* Debug */, + 33A5D55F2EFEB7040049557E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33A5D5602EFEB7040049557E /* Build configuration list for PBXNativeTarget "CalculatorTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33A5D5612EFEB7040049557E /* Debug */, + 33A5D5622EFEB7040049557E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33A5D5632EFEB7040049557E /* Build configuration list for PBXNativeTarget "CalculatorTestTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33A5D5642EFEB7040049557E /* Debug */, + 33A5D5652EFEB7040049557E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33A5D5662EFEB7040049557E /* Build configuration list for PBXNativeTarget "CalculatorTestUITests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33A5D5672EFEB7040049557E /* Debug */, + 33A5D5682EFEB7040049557E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33A5D5372EFEB7000049557E /* Project object */; +} diff --git a/CalculatorTest/CalculatorTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/CalculatorTest/CalculatorTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/CalculatorTest/CalculatorTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/CalculatorTest/CalculatorTest/Assets.xcassets/AccentColor.colorset/Contents.json b/CalculatorTest/CalculatorTest/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/CalculatorTest/CalculatorTest/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/CalculatorTest/CalculatorTest/Assets.xcassets/AppIcon.appiconset/Contents.json b/CalculatorTest/CalculatorTest/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..2305880 --- /dev/null +++ b/CalculatorTest/CalculatorTest/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,35 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "tinted" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/CalculatorTest/CalculatorTest/Assets.xcassets/Contents.json b/CalculatorTest/CalculatorTest/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/CalculatorTest/CalculatorTest/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/CalculatorTest/CalculatorTest/CalculatorApp.swift b/CalculatorTest/CalculatorTest/CalculatorApp.swift new file mode 100644 index 0000000..88daa21 --- /dev/null +++ b/CalculatorTest/CalculatorTest/CalculatorApp.swift @@ -0,0 +1,17 @@ +// +// CalculatorApp.swift +// CalculatorTest +// +// Created by 김나연 on 12/26/25. +// + +import SwiftUI + +@main +struct CalculatorApp: App { + var body: some Scene { + WindowGroup { + CalculatorView() + } + } +} diff --git a/CalculatorTest/CalculatorTest/CalculatorButtonView.swift b/CalculatorTest/CalculatorTest/CalculatorButtonView.swift new file mode 100644 index 0000000..ad15411 --- /dev/null +++ b/CalculatorTest/CalculatorTest/CalculatorButtonView.swift @@ -0,0 +1,53 @@ +// +// CalculatorButtonView.swift +// CalculatorTest +// +// Created by 김나연 on 12/26/25. +// + +import SwiftUI + +struct CalculatorButtonView: View { + let button: CalculatorButton + let action: () -> Void + + var body: some View { + Button(action: action) { + Text(button.title) + .font(.system(size: 32, weight: .medium)) + .foregroundColor(buttonForegroundColor) + .frame(width: buttonWidth, height: buttonHeight) + .background(buttonBackgroundColor) + .cornerRadius(buttonWidth / 2) + } + } + + private var buttonWidth: CGFloat { + // 0 버튼은 2배 너비 + if case .digit(0) = button { + return (UIScreen.main.bounds.width - 5 * 12) / 4 * 2 + 12 + } + return (UIScreen.main.bounds.width - 5 * 12) / 4 + } + + private var buttonHeight: CGFloat { + return (UIScreen.main.bounds.width - 5 * 12) / 4 + } + + private var buttonBackgroundColor: Color { + switch button.backgroundColor { + case "orange": + return Color.orange + case "lightGray": + return Color(white: 0.8) + case "darkGray": + return Color(white: 0.3) + default: + return Color.gray + } + } + + private var buttonForegroundColor: Color { + button.backgroundColor == "lightGray" ? .black : .white + } +} diff --git a/CalculatorTest/CalculatorTest/CalculatorModel.swift b/CalculatorTest/CalculatorTest/CalculatorModel.swift new file mode 100644 index 0000000..4a7a198 --- /dev/null +++ b/CalculatorTest/CalculatorTest/CalculatorModel.swift @@ -0,0 +1,115 @@ +// +// CalculatorModel.swift +// CalculatorTest +// +// Created by 김나연 on 12/26/25. +// + +import Foundation + +enum CalculatorOperation { + case add, subtract, multiply, divide, none +} + +// Protocol for dependency injection +protocol CalculatorModelProtocol { + var displayValue: String { get } + mutating func inputNumber(_ number: String) + mutating func inputOperation(_ operation: CalculatorOperation) + mutating func performOperation() + mutating func reset() + mutating func toggleSign() + mutating func percentage() +} + +struct CalculatorModel: CalculatorModelProtocol { + private var accumulator: Double = 0 + private var currentOperation: CalculatorOperation = .none + private var isNewNumber: Bool = true + + var displayValue: String = "0" + + // 숫자 입력 처리 + mutating func inputNumber(_ number: String) { + if isNewNumber { + displayValue = number + isNewNumber = false + } else { + if number == "." && displayValue.contains(".") { + return // 소수점 중복 방지 + } + displayValue += number + } + } + + // 연산자 입력 처리 + mutating func inputOperation(_ operation: CalculatorOperation) { + if let currentValue = Double(displayValue) { + if !isNewNumber { + performOperation() + } + accumulator = currentValue + currentOperation = operation + isNewNumber = true + } + } + + // 계산 실행 + mutating func performOperation() { + guard let currentValue = Double(displayValue) else { return } + + switch currentOperation { + case .add: + accumulator += currentValue + case .subtract: + accumulator -= currentValue + case .multiply: + accumulator *= currentValue + case .divide: + if currentValue != 0 { + accumulator /= currentValue + } else { + displayValue = "Error" + reset() + return + } + case .none: + accumulator = currentValue + } + + displayValue = formatNumber(accumulator) + currentOperation = .none + isNewNumber = true + } + + // 초기화 + mutating func reset() { + accumulator = 0 + currentOperation = .none + isNewNumber = true + displayValue = "0" + } + + // +/- 부호 변경 + mutating func toggleSign() { + if let value = Double(displayValue) { + displayValue = formatNumber(-value) + } + } + + // 퍼센트 계산 + mutating func percentage() { + if let value = Double(displayValue) { + displayValue = formatNumber(value / 100) + } + } + + // 숫자 포맷팅 (불필요한 소수점 제거) + private func formatNumber(_ number: Double) -> String { + if number.truncatingRemainder(dividingBy: 1) == 0 { + return String(format: "%.0f", number) + } else { + return String(number) + } + } +} diff --git a/CalculatorTest/CalculatorTest/CalculatorView.swift b/CalculatorTest/CalculatorTest/CalculatorView.swift new file mode 100644 index 0000000..c953c68 --- /dev/null +++ b/CalculatorTest/CalculatorTest/CalculatorView.swift @@ -0,0 +1,67 @@ +// +// CalculatorView.swift +// CalculatorTest +// +// Created by 김나연 on 12/26/25. +// + +import SwiftUI + +struct CalculatorView: View { + @StateObject private var viewModel = CalculatorViewModel() + + let buttons: [[CalculatorButton]] = [ + [.clear, .toggleSign, .percentage, .operation(.divide)], + [.digit(7), .digit(8), .digit(9), .operation(.multiply)], + [.digit(4), .digit(5), .digit(6), .operation(.subtract)], + [.digit(1), .digit(2), .digit(3), .operation(.add)], + [.digit(0), .decimal, .equals] + ] + + var body: some View { + ZStack { + Color.black.ignoresSafeArea() + + VStack(spacing: 12) { + Spacer() + + // 디스플레이 + displayView + + // 버튼 그리드 + buttonGrid + } + .padding() + } + } + + // MARK: - Display View + private var displayView: some View { + HStack { + Spacer() + Text(viewModel.displayText) + .font(.system(size: 80, weight: .light)) + .foregroundColor(.white) + .lineLimit(1) + .minimumScaleFactor(0.5) + .padding(.horizontal) + } + .frame(maxWidth: .infinity, alignment: .trailing) + .padding(.bottom, 20) + } + + // MARK: - Button Grid + private var buttonGrid: some View { + VStack(spacing: 12) { + ForEach(buttons.indices, id: \.self) { row in + HStack(spacing: 12) { + ForEach(buttons[row], id: \.title) { button in + CalculatorButtonView(button: button) { + viewModel.buttonTapped(button) + } + } + } + } + } + } +} diff --git a/CalculatorTest/CalculatorTest/CalculatorViewModel.swift b/CalculatorTest/CalculatorTest/CalculatorViewModel.swift new file mode 100644 index 0000000..352d047 --- /dev/null +++ b/CalculatorTest/CalculatorTest/CalculatorViewModel.swift @@ -0,0 +1,92 @@ +// +// CalculatorViewModel.swift +// CalculatorTest +// +// Created by 김나연 on 12/26/25. +// + +import SwiftUI +import Combine + +class CalculatorViewModel: ObservableObject { + @Published private(set) var displayText: String = "0" + + private var model: CalculatorModelProtocol + + init(model: CalculatorModelProtocol = CalculatorModel()) { + self.model = model + updateDisplay() + } + + func buttonTapped(_ button: CalculatorButton) { + switch button { + case .digit(let number): + model.inputNumber(String(number)) + case .decimal: + model.inputNumber(".") + case .operation(let op): + model.inputOperation(op) + case .equals: + model.performOperation() + case .clear: + model.reset() + case .toggleSign: + model.toggleSign() + case .percentage: + model.percentage() + } + + updateDisplay() + } + + private func updateDisplay() { + displayText = model.displayValue + } +} + +// 계산기 버튼 타입 정의 +enum CalculatorButton: Equatable { + case digit(Int) + case decimal + case operation(CalculatorOperation) + case equals + case clear + case toggleSign + case percentage + + var title: String { + switch self { + case .digit(let number): + return "\(number)" + case .decimal: + return "." + case .operation(let op): + switch op { + case .add: return "+" + case .subtract: return "-" + case .multiply: return "×" + case .divide: return "÷" + case .none: return "" + } + case .equals: + return "=" + case .clear: + return "AC" + case .toggleSign: + return "±" + case .percentage: + return "%" + } + } + + var backgroundColor: String { + switch self { + case .operation, .equals: + return "orange" + case .clear, .toggleSign, .percentage: + return "lightGray" + default: + return "darkGray" + } + } +} diff --git a/CalculatorTest/CalculatorTestTests/CalculatorTestTests.swift b/CalculatorTest/CalculatorTestTests/CalculatorTestTests.swift new file mode 100644 index 0000000..ac5552c --- /dev/null +++ b/CalculatorTest/CalculatorTestTests/CalculatorTestTests.swift @@ -0,0 +1,90 @@ +// +// CalculatorTestTests.swift +// CalculatorTestTests +// +// Created by 김나연 on 12/26/25. +// + +import XCTest +@testable import CalculatorTest + +final class CalculatorTestTests: XCTestCase { + + var sut: CalculatorModel! + + override func setUp() { + super.setUp() + sut = CalculatorModel() + } + + override func tearDown() { + sut = nil + super.tearDown() + } + + + // MARK: - Addition Tests + + func test_performOperation_AddTwoNumbers_ReturnsSum() { + // Given: 5 + 3을 입력 + sut.inputNumber("5") + sut.inputOperation(.add) + sut.inputNumber("3") + + // When: = 버튼을 누름 + sut.performOperation() + + // Then: 결과는 8 + XCTAssertEqual(sut.displayValue, "8") + } + + + // MARK: - Subtraction Tests + + func test_performOperation_SubtractTwoNumbers_ReturnsDifference() { + // Given: 10 - 3을 입력 + sut.inputNumber("1") + sut.inputNumber("0") + sut.inputOperation(.subtract) + sut.inputNumber("3") + + // When: = 버튼을 누름 + sut.performOperation() + + // Then: 결과는 7 + XCTAssertEqual(sut.displayValue, "7") + } + + + // MARK: - Multiplication Tests + + func test_performOperation_MultiplyTwoNumbers_ReturnsProduct() { + // Given: 4 × 5를 입력 + sut.inputNumber("4") + sut.inputOperation(.multiply) + sut.inputNumber("5") + + // When: = 버튼을 누름 + sut.performOperation() + + // Then: 결과는 20 + XCTAssertEqual(sut.displayValue, "20") + } + + + // MARK: - Division Tests + + func test_performOperation_DivideTwoNumbers_ReturnsQuotient() { + // Given: 15 ÷ 3을 입력 + sut.inputNumber("1") + sut.inputNumber("5") + sut.inputOperation(.divide) + sut.inputNumber("3") + + // When: = 버튼을 누름 + sut.performOperation() + + // Then: 결과는 5 + XCTAssertEqual(sut.displayValue, "5") + } +} diff --git a/README.md b/README.md index b86bb3b..fc4200e 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,9 @@ # 37-STUDY-iOS-TestCode 37기 iOS 테스트코드 스터디 + +### 2주차 과제 방법 +1. `이름/main` 형식의 브랜치를 팝니다. +2. 그 브랜치를 베이스로 `이름/week03` 브랜치를 파신 후 +3. PR을 작성하시면 끗~ +4. 베이스가 본인이 생성한 브랜치가 맞는지 확인해주세요. + 스크린샷 2025-11-03 오후 3 27 51