From 17315d868031b64bb928ce834dfcfaa96c551cb4 Mon Sep 17 00:00:00 2001 From: JIN Date: Thu, 25 Dec 2025 21:11:22 +0900 Subject: [PATCH 1/6] =?UTF-8?q?=ED=94=84=EB=A1=9C=EC=A0=9D=ED=8A=B8=20?= =?UTF-8?q?=EC=85=8B=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Testcode-last.xcodeproj/project.pbxproj | 581 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../AccentColor.colorset/Contents.json | 11 + .../AppIcon.appiconset/Contents.json | 35 ++ .../Assets.xcassets/Contents.json | 6 + Testcode-last/Testcode-last/ContentView.swift | 24 + .../Testcode-last/Testcode_lastApp.swift | 17 + .../Testcode-lastTest/Testcode_lastTest.swift | 35 ++ .../Testcode_lastUITest.swift | 41 ++ .../Testcode_lastUITestLaunchTests.swift | 33 + 10 files changed, 790 insertions(+) create mode 100644 Testcode-last/Testcode-last.xcodeproj/project.pbxproj create mode 100644 Testcode-last/Testcode-last.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Testcode-last/Testcode-last/Assets.xcassets/AccentColor.colorset/Contents.json create mode 100644 Testcode-last/Testcode-last/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 Testcode-last/Testcode-last/Assets.xcassets/Contents.json create mode 100644 Testcode-last/Testcode-last/ContentView.swift create mode 100644 Testcode-last/Testcode-last/Testcode_lastApp.swift create mode 100644 Testcode-last/Testcode-lastTest/Testcode_lastTest.swift create mode 100644 Testcode-last/Testcode-lastUITest/Testcode_lastUITest.swift create mode 100644 Testcode-last/Testcode-lastUITest/Testcode_lastUITestLaunchTests.swift diff --git a/Testcode-last/Testcode-last.xcodeproj/project.pbxproj b/Testcode-last/Testcode-last.xcodeproj/project.pbxproj new file mode 100644 index 0000000..a12a415 --- /dev/null +++ b/Testcode-last/Testcode-last.xcodeproj/project.pbxproj @@ -0,0 +1,581 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 77; + objects = { + +/* Begin PBXContainerItemProxy section */ + 1ECDD3E02EFB1FEB005A9325 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1ECDD30E2EFAB723005A9325 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1ECDD3152EFAB723005A9325; + remoteInfo = "Testcode-last"; + }; + 1ECDD3EF2EFB2026005A9325 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1ECDD30E2EFAB723005A9325 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1ECDD3152EFAB723005A9325; + remoteInfo = "Testcode-last"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 1ECDD3162EFAB723005A9325 /* Testcode-last.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Testcode-last.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1ECDD3DC2EFB1FEB005A9325 /* Testcode-lastTest.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Testcode-lastTest.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1ECDD3E92EFB2026005A9325 /* Testcode-lastUITest.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Testcode-lastUITest.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFileSystemSynchronizedRootGroup section */ + 1ECDD3182EFAB723005A9325 /* Testcode-last */ = { + isa = PBXFileSystemSynchronizedRootGroup; + path = "Testcode-last"; + sourceTree = ""; + }; + 1ECDD3DD2EFB1FEB005A9325 /* Testcode-lastTest */ = { + isa = PBXFileSystemSynchronizedRootGroup; + path = "Testcode-lastTest"; + sourceTree = ""; + }; + 1ECDD3EA2EFB2026005A9325 /* Testcode-lastUITest */ = { + isa = PBXFileSystemSynchronizedRootGroup; + path = "Testcode-lastUITest"; + sourceTree = ""; + }; +/* End PBXFileSystemSynchronizedRootGroup section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1ECDD3132EFAB723005A9325 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1ECDD3D92EFB1FEB005A9325 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1ECDD3E62EFB2026005A9325 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1ECDD30D2EFAB723005A9325 = { + isa = PBXGroup; + children = ( + 1ECDD3182EFAB723005A9325 /* Testcode-last */, + 1ECDD3DD2EFB1FEB005A9325 /* Testcode-lastTest */, + 1ECDD3EA2EFB2026005A9325 /* Testcode-lastUITest */, + 1ECDD3172EFAB723005A9325 /* Products */, + ); + sourceTree = ""; + }; + 1ECDD3172EFAB723005A9325 /* Products */ = { + isa = PBXGroup; + children = ( + 1ECDD3162EFAB723005A9325 /* Testcode-last.app */, + 1ECDD3DC2EFB1FEB005A9325 /* Testcode-lastTest.xctest */, + 1ECDD3E92EFB2026005A9325 /* Testcode-lastUITest.xctest */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1ECDD3152EFAB723005A9325 /* Testcode-last */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1ECDD3212EFAB724005A9325 /* Build configuration list for PBXNativeTarget "Testcode-last" */; + buildPhases = ( + 1ECDD3122EFAB723005A9325 /* Sources */, + 1ECDD3132EFAB723005A9325 /* Frameworks */, + 1ECDD3142EFAB723005A9325 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + fileSystemSynchronizedGroups = ( + 1ECDD3182EFAB723005A9325 /* Testcode-last */, + ); + name = "Testcode-last"; + packageProductDependencies = ( + ); + productName = "Testcode-last"; + productReference = 1ECDD3162EFAB723005A9325 /* Testcode-last.app */; + productType = "com.apple.product-type.application"; + }; + 1ECDD3DB2EFB1FEB005A9325 /* Testcode-lastTest */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1ECDD3E22EFB1FEB005A9325 /* Build configuration list for PBXNativeTarget "Testcode-lastTest" */; + buildPhases = ( + 1ECDD3D82EFB1FEB005A9325 /* Sources */, + 1ECDD3D92EFB1FEB005A9325 /* Frameworks */, + 1ECDD3DA2EFB1FEB005A9325 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 1ECDD3E12EFB1FEB005A9325 /* PBXTargetDependency */, + ); + fileSystemSynchronizedGroups = ( + 1ECDD3DD2EFB1FEB005A9325 /* Testcode-lastTest */, + ); + name = "Testcode-lastTest"; + packageProductDependencies = ( + ); + productName = "Testcode-lastTest"; + productReference = 1ECDD3DC2EFB1FEB005A9325 /* Testcode-lastTest.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 1ECDD3E82EFB2026005A9325 /* Testcode-lastUITest */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1ECDD3F12EFB2026005A9325 /* Build configuration list for PBXNativeTarget "Testcode-lastUITest" */; + buildPhases = ( + 1ECDD3E52EFB2026005A9325 /* Sources */, + 1ECDD3E62EFB2026005A9325 /* Frameworks */, + 1ECDD3E72EFB2026005A9325 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 1ECDD3F02EFB2026005A9325 /* PBXTargetDependency */, + ); + fileSystemSynchronizedGroups = ( + 1ECDD3EA2EFB2026005A9325 /* Testcode-lastUITest */, + ); + name = "Testcode-lastUITest"; + packageProductDependencies = ( + ); + productName = "Testcode-lastUITest"; + productReference = 1ECDD3E92EFB2026005A9325 /* Testcode-lastUITest.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 1ECDD30E2EFAB723005A9325 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 2600; + LastUpgradeCheck = 2600; + TargetAttributes = { + 1ECDD3152EFAB723005A9325 = { + CreatedOnToolsVersion = 26.0.1; + }; + 1ECDD3DB2EFB1FEB005A9325 = { + CreatedOnToolsVersion = 26.0.1; + TestTargetID = 1ECDD3152EFAB723005A9325; + }; + 1ECDD3E82EFB2026005A9325 = { + CreatedOnToolsVersion = 26.0.1; + TestTargetID = 1ECDD3152EFAB723005A9325; + }; + }; + }; + buildConfigurationList = 1ECDD3112EFAB723005A9325 /* Build configuration list for PBXProject "Testcode-last" */; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 1ECDD30D2EFAB723005A9325; + minimizedProjectReferenceProxies = 1; + preferredProjectObjectVersion = 77; + productRefGroup = 1ECDD3172EFAB723005A9325 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 1ECDD3152EFAB723005A9325 /* Testcode-last */, + 1ECDD3DB2EFB1FEB005A9325 /* Testcode-lastTest */, + 1ECDD3E82EFB2026005A9325 /* Testcode-lastUITest */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1ECDD3142EFAB723005A9325 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1ECDD3DA2EFB1FEB005A9325 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1ECDD3E72EFB2026005A9325 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1ECDD3122EFAB723005A9325 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1ECDD3D82EFB1FEB005A9325 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1ECDD3E52EFB2026005A9325 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 1ECDD3E12EFB1FEB005A9325 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1ECDD3152EFAB723005A9325 /* Testcode-last */; + targetProxy = 1ECDD3E02EFB1FEB005A9325 /* PBXContainerItemProxy */; + }; + 1ECDD3F02EFB2026005A9325 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1ECDD3152EFAB723005A9325 /* Testcode-last */; + targetProxy = 1ECDD3EF2EFB2026005A9325 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 1ECDD31F2EFAB724005A9325 /* 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; + DEVELOPMENT_TEAM = 5RA2A76S4S; + 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 = 26.0; + 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; + }; + 1ECDD3202EFAB724005A9325 /* 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"; + DEVELOPMENT_TEAM = 5RA2A76S4S; + 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 = 26.0; + 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; + }; + 1ECDD3222EFAB724005A9325 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 5RA2A76S4S; + 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 = "come.Jin.Testcode-last"; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 1ECDD3232EFAB724005A9325 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 5RA2A76S4S; + 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 = "come.Jin.Testcode-last"; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 1ECDD3E32EFB1FEB005A9325 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 5RA2A76S4S; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "come.Jin.Testcode-lastTest"; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRING_CATALOG_GENERATE_SYMBOLS = NO; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Testcode-last.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Testcode-last"; + }; + name = Debug; + }; + 1ECDD3E42EFB1FEB005A9325 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 5RA2A76S4S; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "come.Jin.Testcode-lastTest"; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRING_CATALOG_GENERATE_SYMBOLS = NO; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Testcode-last.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Testcode-last"; + }; + name = Release; + }; + 1ECDD3F22EFB2026005A9325 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 5RA2A76S4S; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "come.Jin.Testcode-lastUITest"; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRING_CATALOG_GENERATE_SYMBOLS = NO; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = "Testcode-last"; + }; + name = Debug; + }; + 1ECDD3F32EFB2026005A9325 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 5RA2A76S4S; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "come.Jin.Testcode-lastUITest"; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRING_CATALOG_GENERATE_SYMBOLS = NO; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = "Testcode-last"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1ECDD3112EFAB723005A9325 /* Build configuration list for PBXProject "Testcode-last" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1ECDD31F2EFAB724005A9325 /* Debug */, + 1ECDD3202EFAB724005A9325 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1ECDD3212EFAB724005A9325 /* Build configuration list for PBXNativeTarget "Testcode-last" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1ECDD3222EFAB724005A9325 /* Debug */, + 1ECDD3232EFAB724005A9325 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1ECDD3E22EFB1FEB005A9325 /* Build configuration list for PBXNativeTarget "Testcode-lastTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1ECDD3E32EFB1FEB005A9325 /* Debug */, + 1ECDD3E42EFB1FEB005A9325 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1ECDD3F12EFB2026005A9325 /* Build configuration list for PBXNativeTarget "Testcode-lastUITest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1ECDD3F22EFB2026005A9325 /* Debug */, + 1ECDD3F32EFB2026005A9325 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 1ECDD30E2EFAB723005A9325 /* Project object */; +} diff --git a/Testcode-last/Testcode-last.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Testcode-last/Testcode-last.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/Testcode-last/Testcode-last.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Testcode-last/Testcode-last/Assets.xcassets/AccentColor.colorset/Contents.json b/Testcode-last/Testcode-last/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/Testcode-last/Testcode-last/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Testcode-last/Testcode-last/Assets.xcassets/AppIcon.appiconset/Contents.json b/Testcode-last/Testcode-last/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..2305880 --- /dev/null +++ b/Testcode-last/Testcode-last/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/Testcode-last/Testcode-last/Assets.xcassets/Contents.json b/Testcode-last/Testcode-last/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/Testcode-last/Testcode-last/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Testcode-last/Testcode-last/ContentView.swift b/Testcode-last/Testcode-last/ContentView.swift new file mode 100644 index 0000000..85beb0d --- /dev/null +++ b/Testcode-last/Testcode-last/ContentView.swift @@ -0,0 +1,24 @@ +// +// ContentView.swift +// Testcode-last +// +// Created by JIN on 12/23/25. +// + +import SwiftUI + +struct ContentView: View { + var body: some View { + VStack { + Image(systemName: "globe") + .imageScale(.large) + .foregroundStyle(.tint) + Text("Hello, world!") + } + .padding() + } +} + +#Preview { + ContentView() +} diff --git a/Testcode-last/Testcode-last/Testcode_lastApp.swift b/Testcode-last/Testcode-last/Testcode_lastApp.swift new file mode 100644 index 0000000..1465b07 --- /dev/null +++ b/Testcode-last/Testcode-last/Testcode_lastApp.swift @@ -0,0 +1,17 @@ +// +// Testcode_lastApp.swift +// Testcode-last +// +// Created by JIN on 12/23/25. +// + +import SwiftUI + +@main +struct Testcode_lastApp: App { + var body: some Scene { + WindowGroup { + ContentView() + } + } +} diff --git a/Testcode-last/Testcode-lastTest/Testcode_lastTest.swift b/Testcode-last/Testcode-lastTest/Testcode_lastTest.swift new file mode 100644 index 0000000..068a6a5 --- /dev/null +++ b/Testcode-last/Testcode-lastTest/Testcode_lastTest.swift @@ -0,0 +1,35 @@ +// +// Testcode_lastTest.swift +// Testcode-lastTest +// +// Created by JIN on 12/24/25. +// + +import XCTest + +final class Testcode_lastTest: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + 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. + // Any test you write for XCTest can be annotated as throws and async. + // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. + // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. + } + + func testPerformanceExample() throws { + // This is an example of a performance test case. + measure { + // Put the code you want to measure the time of here. + } + } + +} diff --git a/Testcode-last/Testcode-lastUITest/Testcode_lastUITest.swift b/Testcode-last/Testcode-lastUITest/Testcode_lastUITest.swift new file mode 100644 index 0000000..56fe25d --- /dev/null +++ b/Testcode-last/Testcode-lastUITest/Testcode_lastUITest.swift @@ -0,0 +1,41 @@ +// +// Testcode_lastUITest.swift +// Testcode-lastUITest +// +// Created by JIN on 12/24/25. +// + +import XCTest + +final class Testcode_lastUITest: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + + // In UI tests it is usually best to stop immediately when a failure occurs. + continueAfterFailure = false + + // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + @MainActor + func testExample() throws { + // UI tests must launch the application that they test. + let app = XCUIApplication() + app.launch() + + // Use XCTAssert and related functions to verify your tests produce the correct results. + } + + @MainActor + func testLaunchPerformance() throws { + // This measures how long it takes to launch your application. + measure(metrics: [XCTApplicationLaunchMetric()]) { + XCUIApplication().launch() + } + } +} diff --git a/Testcode-last/Testcode-lastUITest/Testcode_lastUITestLaunchTests.swift b/Testcode-last/Testcode-lastUITest/Testcode_lastUITestLaunchTests.swift new file mode 100644 index 0000000..59f981f --- /dev/null +++ b/Testcode-last/Testcode-lastUITest/Testcode_lastUITestLaunchTests.swift @@ -0,0 +1,33 @@ +// +// Testcode_lastUITestLaunchTests.swift +// Testcode-lastUITest +// +// Created by JIN on 12/24/25. +// + +import XCTest + +final class Testcode_lastUITestLaunchTests: XCTestCase { + + override class var runsForEachTargetApplicationUIConfiguration: Bool { + true + } + + override func setUpWithError() throws { + continueAfterFailure = false + } + + @MainActor + func testLaunch() throws { + let app = XCUIApplication() + app.launch() + + // Insert steps here to perform after app launch but before taking a screenshot, + // such as logging into a test account or navigating somewhere in the app + + let attachment = XCTAttachment(screenshot: app.screenshot()) + attachment.name = "Launch Screen" + attachment.lifetime = .keepAlways + add(attachment) + } +} From 8a125b684a1dd0ded0b095507d0116dade739205 Mon Sep 17 00:00:00 2001 From: JIN Date: Thu, 25 Dec 2025 22:58:53 +0900 Subject: [PATCH 2/6] =?UTF-8?q?=ED=94=84=EB=A1=9C=EC=A0=9D=ED=8A=B8=20?= =?UTF-8?q?=ED=8F=B4=EB=8D=94=20=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Testcode-last.xcodeproj/project.pbxproj | 19 ++------- .../Testcode-last/Models/Operation.swift | 24 +++++++++++ .../Testcode-lastTest/Testcode_lastTest.swift | 35 ---------------- .../Testcode_lastUITest.swift | 41 ------------------- .../Testcode_lastUITestLaunchTests.swift | 33 --------------- 5 files changed, 28 insertions(+), 124 deletions(-) create mode 100644 Testcode-last/Testcode-last/Models/Operation.swift delete mode 100644 Testcode-last/Testcode-lastTest/Testcode_lastTest.swift delete mode 100644 Testcode-last/Testcode-lastUITest/Testcode_lastUITest.swift delete mode 100644 Testcode-last/Testcode-lastUITest/Testcode_lastUITestLaunchTests.swift diff --git a/Testcode-last/Testcode-last.xcodeproj/project.pbxproj b/Testcode-last/Testcode-last.xcodeproj/project.pbxproj index a12a415..4f4685b 100644 --- a/Testcode-last/Testcode-last.xcodeproj/project.pbxproj +++ b/Testcode-last/Testcode-last.xcodeproj/project.pbxproj @@ -35,14 +35,9 @@ path = "Testcode-last"; sourceTree = ""; }; - 1ECDD3DD2EFB1FEB005A9325 /* Testcode-lastTest */ = { + 1ECDD4B82EFD670C005A9325 /* Testcode-last-test */ = { isa = PBXFileSystemSynchronizedRootGroup; - path = "Testcode-lastTest"; - sourceTree = ""; - }; - 1ECDD3EA2EFB2026005A9325 /* Testcode-lastUITest */ = { - isa = PBXFileSystemSynchronizedRootGroup; - path = "Testcode-lastUITest"; + path = "Testcode-last-test"; sourceTree = ""; }; /* End PBXFileSystemSynchronizedRootGroup section */ @@ -75,9 +70,8 @@ 1ECDD30D2EFAB723005A9325 = { isa = PBXGroup; children = ( + 1ECDD4B82EFD670C005A9325 /* Testcode-last-test */, 1ECDD3182EFAB723005A9325 /* Testcode-last */, - 1ECDD3DD2EFB1FEB005A9325 /* Testcode-lastTest */, - 1ECDD3EA2EFB2026005A9325 /* Testcode-lastUITest */, 1ECDD3172EFAB723005A9325 /* Products */, ); sourceTree = ""; @@ -109,6 +103,7 @@ ); fileSystemSynchronizedGroups = ( 1ECDD3182EFAB723005A9325 /* Testcode-last */, + 1ECDD4B82EFD670C005A9325 /* Testcode-last-test */, ); name = "Testcode-last"; packageProductDependencies = ( @@ -130,9 +125,6 @@ dependencies = ( 1ECDD3E12EFB1FEB005A9325 /* PBXTargetDependency */, ); - fileSystemSynchronizedGroups = ( - 1ECDD3DD2EFB1FEB005A9325 /* Testcode-lastTest */, - ); name = "Testcode-lastTest"; packageProductDependencies = ( ); @@ -153,9 +145,6 @@ dependencies = ( 1ECDD3F02EFB2026005A9325 /* PBXTargetDependency */, ); - fileSystemSynchronizedGroups = ( - 1ECDD3EA2EFB2026005A9325 /* Testcode-lastUITest */, - ); name = "Testcode-lastUITest"; packageProductDependencies = ( ); diff --git a/Testcode-last/Testcode-last/Models/Operation.swift b/Testcode-last/Testcode-last/Models/Operation.swift new file mode 100644 index 0000000..6060756 --- /dev/null +++ b/Testcode-last/Testcode-last/Models/Operation.swift @@ -0,0 +1,24 @@ +// +// Operation.swift +// Testcode-last +// +// Created by JIN on 12/25/25. +// + +import Foundation + +enum Operation { + case add + case subtract + case multiply + case divide + + var symbol: String { + switch self { + case .add: return "+" + case .subtract: return "-" + case .multiply: return "×" + case .divide: return "÷" + } + } +} diff --git a/Testcode-last/Testcode-lastTest/Testcode_lastTest.swift b/Testcode-last/Testcode-lastTest/Testcode_lastTest.swift deleted file mode 100644 index 068a6a5..0000000 --- a/Testcode-last/Testcode-lastTest/Testcode_lastTest.swift +++ /dev/null @@ -1,35 +0,0 @@ -// -// Testcode_lastTest.swift -// Testcode-lastTest -// -// Created by JIN on 12/24/25. -// - -import XCTest - -final class Testcode_lastTest: XCTestCase { - - override func setUpWithError() throws { - // Put setup code here. This method is called before the invocation of each test method in the class. - } - - override func tearDownWithError() throws { - // Put teardown code here. This method is called after the invocation of each test method in the class. - } - - 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. - // Any test you write for XCTest can be annotated as throws and async. - // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. - // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. - } - - func testPerformanceExample() throws { - // This is an example of a performance test case. - measure { - // Put the code you want to measure the time of here. - } - } - -} diff --git a/Testcode-last/Testcode-lastUITest/Testcode_lastUITest.swift b/Testcode-last/Testcode-lastUITest/Testcode_lastUITest.swift deleted file mode 100644 index 56fe25d..0000000 --- a/Testcode-last/Testcode-lastUITest/Testcode_lastUITest.swift +++ /dev/null @@ -1,41 +0,0 @@ -// -// Testcode_lastUITest.swift -// Testcode-lastUITest -// -// Created by JIN on 12/24/25. -// - -import XCTest - -final class Testcode_lastUITest: XCTestCase { - - override func setUpWithError() throws { - // Put setup code here. This method is called before the invocation of each test method in the class. - - // In UI tests it is usually best to stop immediately when a failure occurs. - continueAfterFailure = false - - // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. - } - - override func tearDownWithError() throws { - // Put teardown code here. This method is called after the invocation of each test method in the class. - } - - @MainActor - func testExample() throws { - // UI tests must launch the application that they test. - let app = XCUIApplication() - app.launch() - - // Use XCTAssert and related functions to verify your tests produce the correct results. - } - - @MainActor - func testLaunchPerformance() throws { - // This measures how long it takes to launch your application. - measure(metrics: [XCTApplicationLaunchMetric()]) { - XCUIApplication().launch() - } - } -} diff --git a/Testcode-last/Testcode-lastUITest/Testcode_lastUITestLaunchTests.swift b/Testcode-last/Testcode-lastUITest/Testcode_lastUITestLaunchTests.swift deleted file mode 100644 index 59f981f..0000000 --- a/Testcode-last/Testcode-lastUITest/Testcode_lastUITestLaunchTests.swift +++ /dev/null @@ -1,33 +0,0 @@ -// -// Testcode_lastUITestLaunchTests.swift -// Testcode-lastUITest -// -// Created by JIN on 12/24/25. -// - -import XCTest - -final class Testcode_lastUITestLaunchTests: XCTestCase { - - override class var runsForEachTargetApplicationUIConfiguration: Bool { - true - } - - override func setUpWithError() throws { - continueAfterFailure = false - } - - @MainActor - func testLaunch() throws { - let app = XCUIApplication() - app.launch() - - // Insert steps here to perform after app launch but before taking a screenshot, - // such as logging into a test account or navigating somewhere in the app - - let attachment = XCTAttachment(screenshot: app.screenshot()) - attachment.name = "Launch Screen" - attachment.lifetime = .keepAlways - add(attachment) - } -} From 5ff9e7653906d42354e644df287584d1914d0a51 Mon Sep 17 00:00:00 2001 From: JIN Date: Thu, 25 Dec 2025 23:21:27 +0900 Subject: [PATCH 3/6] =?UTF-8?q?=ED=94=84=EB=A1=9C=EC=A0=9D=ED=8A=B8=20?= =?UTF-8?q?=EC=B4=88=EA=B8=B0=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../project.pbxproj | 231 +++++++++--------- .../contents.xcworkspacedata | 0 .../AccentColor.colorset/Contents.json | 0 .../AppIcon.appiconset/Contents.json | 0 .../Assets.xcassets/Contents.json | 0 .../CalculatorProjectApp.swift | 8 +- .../CalculatorProject}/ContentView.swift | 4 +- .../CalculatorProjectTests.swift | 36 +++ .../CalculatorProjectUITests.swift | 41 ++++ .../CalculatorProjectUITestsLaunchTests.swift | 33 +++ .../Testcode-last/Models/Operation.swift | 24 -- 11 files changed, 238 insertions(+), 139 deletions(-) rename {Testcode-last/Testcode-last.xcodeproj => CalculatorProject/CalculatorProject.xcodeproj}/project.pbxproj (66%) rename {Testcode-last/Testcode-last.xcodeproj => CalculatorProject/CalculatorProject.xcodeproj}/project.xcworkspace/contents.xcworkspacedata (100%) rename {Testcode-last/Testcode-last => CalculatorProject/CalculatorProject}/Assets.xcassets/AccentColor.colorset/Contents.json (100%) rename {Testcode-last/Testcode-last => CalculatorProject/CalculatorProject}/Assets.xcassets/AppIcon.appiconset/Contents.json (100%) rename {Testcode-last/Testcode-last => CalculatorProject/CalculatorProject}/Assets.xcassets/Contents.json (100%) rename Testcode-last/Testcode-last/Testcode_lastApp.swift => CalculatorProject/CalculatorProject/CalculatorProjectApp.swift (51%) rename {Testcode-last/Testcode-last => CalculatorProject/CalculatorProject}/ContentView.swift (86%) create mode 100644 CalculatorProject/CalculatorProjectTests/CalculatorProjectTests.swift create mode 100644 CalculatorProject/CalculatorProjectUITests/CalculatorProjectUITests.swift create mode 100644 CalculatorProject/CalculatorProjectUITests/CalculatorProjectUITestsLaunchTests.swift delete mode 100644 Testcode-last/Testcode-last/Models/Operation.swift diff --git a/Testcode-last/Testcode-last.xcodeproj/project.pbxproj b/CalculatorProject/CalculatorProject.xcodeproj/project.pbxproj similarity index 66% rename from Testcode-last/Testcode-last.xcodeproj/project.pbxproj rename to CalculatorProject/CalculatorProject.xcodeproj/project.pbxproj index 4f4685b..c116716 100644 --- a/Testcode-last/Testcode-last.xcodeproj/project.pbxproj +++ b/CalculatorProject/CalculatorProject.xcodeproj/project.pbxproj @@ -7,57 +7,62 @@ objects = { /* Begin PBXContainerItemProxy section */ - 1ECDD3E02EFB1FEB005A9325 /* PBXContainerItemProxy */ = { + 1ECDD4DC2EFD7FC9005A9325 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1ECDD30E2EFAB723005A9325 /* Project object */; + containerPortal = 1ECDD4C62EFD7FC8005A9325 /* Project object */; proxyType = 1; - remoteGlobalIDString = 1ECDD3152EFAB723005A9325; - remoteInfo = "Testcode-last"; + remoteGlobalIDString = 1ECDD4CD2EFD7FC8005A9325; + remoteInfo = CalculatorProject; }; - 1ECDD3EF2EFB2026005A9325 /* PBXContainerItemProxy */ = { + 1ECDD4E62EFD7FC9005A9325 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1ECDD30E2EFAB723005A9325 /* Project object */; + containerPortal = 1ECDD4C62EFD7FC8005A9325 /* Project object */; proxyType = 1; - remoteGlobalIDString = 1ECDD3152EFAB723005A9325; - remoteInfo = "Testcode-last"; + remoteGlobalIDString = 1ECDD4CD2EFD7FC8005A9325; + remoteInfo = CalculatorProject; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 1ECDD3162EFAB723005A9325 /* Testcode-last.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Testcode-last.app"; sourceTree = BUILT_PRODUCTS_DIR; }; - 1ECDD3DC2EFB1FEB005A9325 /* Testcode-lastTest.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Testcode-lastTest.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; - 1ECDD3E92EFB2026005A9325 /* Testcode-lastUITest.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Testcode-lastUITest.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1ECDD4CE2EFD7FC8005A9325 /* CalculatorProject.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CalculatorProject.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 1ECDD4DB2EFD7FC9005A9325 /* CalculatorProjectTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CalculatorProjectTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 1ECDD4E52EFD7FC9005A9325 /* CalculatorProjectUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CalculatorProjectUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFileSystemSynchronizedRootGroup section */ - 1ECDD3182EFAB723005A9325 /* Testcode-last */ = { + 1ECDD4D02EFD7FC8005A9325 /* CalculatorProject */ = { isa = PBXFileSystemSynchronizedRootGroup; - path = "Testcode-last"; + path = CalculatorProject; sourceTree = ""; }; - 1ECDD4B82EFD670C005A9325 /* Testcode-last-test */ = { + 1ECDD4DE2EFD7FC9005A9325 /* CalculatorProjectTests */ = { isa = PBXFileSystemSynchronizedRootGroup; - path = "Testcode-last-test"; + path = CalculatorProjectTests; + sourceTree = ""; + }; + 1ECDD4E82EFD7FC9005A9325 /* CalculatorProjectUITests */ = { + isa = PBXFileSystemSynchronizedRootGroup; + path = CalculatorProjectUITests; sourceTree = ""; }; /* End PBXFileSystemSynchronizedRootGroup section */ /* Begin PBXFrameworksBuildPhase section */ - 1ECDD3132EFAB723005A9325 /* Frameworks */ = { + 1ECDD4CB2EFD7FC8005A9325 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - 1ECDD3D92EFB1FEB005A9325 /* Frameworks */ = { + 1ECDD4D82EFD7FC9005A9325 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - 1ECDD3E62EFB2026005A9325 /* Frameworks */ = { + 1ECDD4E22EFD7FC9005A9325 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( @@ -67,21 +72,22 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 1ECDD30D2EFAB723005A9325 = { + 1ECDD4C52EFD7FC8005A9325 = { isa = PBXGroup; children = ( - 1ECDD4B82EFD670C005A9325 /* Testcode-last-test */, - 1ECDD3182EFAB723005A9325 /* Testcode-last */, - 1ECDD3172EFAB723005A9325 /* Products */, + 1ECDD4D02EFD7FC8005A9325 /* CalculatorProject */, + 1ECDD4DE2EFD7FC9005A9325 /* CalculatorProjectTests */, + 1ECDD4E82EFD7FC9005A9325 /* CalculatorProjectUITests */, + 1ECDD4CF2EFD7FC8005A9325 /* Products */, ); sourceTree = ""; }; - 1ECDD3172EFAB723005A9325 /* Products */ = { + 1ECDD4CF2EFD7FC8005A9325 /* Products */ = { isa = PBXGroup; children = ( - 1ECDD3162EFAB723005A9325 /* Testcode-last.app */, - 1ECDD3DC2EFB1FEB005A9325 /* Testcode-lastTest.xctest */, - 1ECDD3E92EFB2026005A9325 /* Testcode-lastUITest.xctest */, + 1ECDD4CE2EFD7FC8005A9325 /* CalculatorProject.app */, + 1ECDD4DB2EFD7FC9005A9325 /* CalculatorProjectTests.xctest */, + 1ECDD4E52EFD7FC9005A9325 /* CalculatorProjectUITests.xctest */, ); name = Products; sourceTree = ""; @@ -89,129 +95,134 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - 1ECDD3152EFAB723005A9325 /* Testcode-last */ = { + 1ECDD4CD2EFD7FC8005A9325 /* CalculatorProject */ = { isa = PBXNativeTarget; - buildConfigurationList = 1ECDD3212EFAB724005A9325 /* Build configuration list for PBXNativeTarget "Testcode-last" */; + buildConfigurationList = 1ECDD4EF2EFD7FC9005A9325 /* Build configuration list for PBXNativeTarget "CalculatorProject" */; buildPhases = ( - 1ECDD3122EFAB723005A9325 /* Sources */, - 1ECDD3132EFAB723005A9325 /* Frameworks */, - 1ECDD3142EFAB723005A9325 /* Resources */, + 1ECDD4CA2EFD7FC8005A9325 /* Sources */, + 1ECDD4CB2EFD7FC8005A9325 /* Frameworks */, + 1ECDD4CC2EFD7FC8005A9325 /* Resources */, ); buildRules = ( ); dependencies = ( ); fileSystemSynchronizedGroups = ( - 1ECDD3182EFAB723005A9325 /* Testcode-last */, - 1ECDD4B82EFD670C005A9325 /* Testcode-last-test */, + 1ECDD4D02EFD7FC8005A9325 /* CalculatorProject */, ); - name = "Testcode-last"; + name = CalculatorProject; packageProductDependencies = ( ); - productName = "Testcode-last"; - productReference = 1ECDD3162EFAB723005A9325 /* Testcode-last.app */; + productName = CalculatorProject; + productReference = 1ECDD4CE2EFD7FC8005A9325 /* CalculatorProject.app */; productType = "com.apple.product-type.application"; }; - 1ECDD3DB2EFB1FEB005A9325 /* Testcode-lastTest */ = { + 1ECDD4DA2EFD7FC9005A9325 /* CalculatorProjectTests */ = { isa = PBXNativeTarget; - buildConfigurationList = 1ECDD3E22EFB1FEB005A9325 /* Build configuration list for PBXNativeTarget "Testcode-lastTest" */; + buildConfigurationList = 1ECDD4F22EFD7FC9005A9325 /* Build configuration list for PBXNativeTarget "CalculatorProjectTests" */; buildPhases = ( - 1ECDD3D82EFB1FEB005A9325 /* Sources */, - 1ECDD3D92EFB1FEB005A9325 /* Frameworks */, - 1ECDD3DA2EFB1FEB005A9325 /* Resources */, + 1ECDD4D72EFD7FC9005A9325 /* Sources */, + 1ECDD4D82EFD7FC9005A9325 /* Frameworks */, + 1ECDD4D92EFD7FC9005A9325 /* Resources */, ); buildRules = ( ); dependencies = ( - 1ECDD3E12EFB1FEB005A9325 /* PBXTargetDependency */, + 1ECDD4DD2EFD7FC9005A9325 /* PBXTargetDependency */, + ); + fileSystemSynchronizedGroups = ( + 1ECDD4DE2EFD7FC9005A9325 /* CalculatorProjectTests */, ); - name = "Testcode-lastTest"; + name = CalculatorProjectTests; packageProductDependencies = ( ); - productName = "Testcode-lastTest"; - productReference = 1ECDD3DC2EFB1FEB005A9325 /* Testcode-lastTest.xctest */; + productName = CalculatorProjectTests; + productReference = 1ECDD4DB2EFD7FC9005A9325 /* CalculatorProjectTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; - 1ECDD3E82EFB2026005A9325 /* Testcode-lastUITest */ = { + 1ECDD4E42EFD7FC9005A9325 /* CalculatorProjectUITests */ = { isa = PBXNativeTarget; - buildConfigurationList = 1ECDD3F12EFB2026005A9325 /* Build configuration list for PBXNativeTarget "Testcode-lastUITest" */; + buildConfigurationList = 1ECDD4F52EFD7FC9005A9325 /* Build configuration list for PBXNativeTarget "CalculatorProjectUITests" */; buildPhases = ( - 1ECDD3E52EFB2026005A9325 /* Sources */, - 1ECDD3E62EFB2026005A9325 /* Frameworks */, - 1ECDD3E72EFB2026005A9325 /* Resources */, + 1ECDD4E12EFD7FC9005A9325 /* Sources */, + 1ECDD4E22EFD7FC9005A9325 /* Frameworks */, + 1ECDD4E32EFD7FC9005A9325 /* Resources */, ); buildRules = ( ); dependencies = ( - 1ECDD3F02EFB2026005A9325 /* PBXTargetDependency */, + 1ECDD4E72EFD7FC9005A9325 /* PBXTargetDependency */, ); - name = "Testcode-lastUITest"; + fileSystemSynchronizedGroups = ( + 1ECDD4E82EFD7FC9005A9325 /* CalculatorProjectUITests */, + ); + name = CalculatorProjectUITests; packageProductDependencies = ( ); - productName = "Testcode-lastUITest"; - productReference = 1ECDD3E92EFB2026005A9325 /* Testcode-lastUITest.xctest */; + productName = CalculatorProjectUITests; + productReference = 1ECDD4E52EFD7FC9005A9325 /* CalculatorProjectUITests.xctest */; productType = "com.apple.product-type.bundle.ui-testing"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ - 1ECDD30E2EFAB723005A9325 /* Project object */ = { + 1ECDD4C62EFD7FC8005A9325 /* Project object */ = { isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = 1; LastSwiftUpdateCheck = 2600; LastUpgradeCheck = 2600; TargetAttributes = { - 1ECDD3152EFAB723005A9325 = { + 1ECDD4CD2EFD7FC8005A9325 = { CreatedOnToolsVersion = 26.0.1; }; - 1ECDD3DB2EFB1FEB005A9325 = { + 1ECDD4DA2EFD7FC9005A9325 = { CreatedOnToolsVersion = 26.0.1; - TestTargetID = 1ECDD3152EFAB723005A9325; + TestTargetID = 1ECDD4CD2EFD7FC8005A9325; }; - 1ECDD3E82EFB2026005A9325 = { + 1ECDD4E42EFD7FC9005A9325 = { CreatedOnToolsVersion = 26.0.1; - TestTargetID = 1ECDD3152EFAB723005A9325; + TestTargetID = 1ECDD4CD2EFD7FC8005A9325; }; }; }; - buildConfigurationList = 1ECDD3112EFAB723005A9325 /* Build configuration list for PBXProject "Testcode-last" */; + buildConfigurationList = 1ECDD4C92EFD7FC8005A9325 /* Build configuration list for PBXProject "CalculatorProject" */; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); - mainGroup = 1ECDD30D2EFAB723005A9325; + mainGroup = 1ECDD4C52EFD7FC8005A9325; minimizedProjectReferenceProxies = 1; preferredProjectObjectVersion = 77; - productRefGroup = 1ECDD3172EFAB723005A9325 /* Products */; + productRefGroup = 1ECDD4CF2EFD7FC8005A9325 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( - 1ECDD3152EFAB723005A9325 /* Testcode-last */, - 1ECDD3DB2EFB1FEB005A9325 /* Testcode-lastTest */, - 1ECDD3E82EFB2026005A9325 /* Testcode-lastUITest */, + 1ECDD4CD2EFD7FC8005A9325 /* CalculatorProject */, + 1ECDD4DA2EFD7FC9005A9325 /* CalculatorProjectTests */, + 1ECDD4E42EFD7FC9005A9325 /* CalculatorProjectUITests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 1ECDD3142EFAB723005A9325 /* Resources */ = { + 1ECDD4CC2EFD7FC8005A9325 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - 1ECDD3DA2EFB1FEB005A9325 /* Resources */ = { + 1ECDD4D92EFD7FC9005A9325 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - 1ECDD3E72EFB2026005A9325 /* Resources */ = { + 1ECDD4E32EFD7FC9005A9325 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( @@ -221,21 +232,21 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 1ECDD3122EFAB723005A9325 /* Sources */ = { + 1ECDD4CA2EFD7FC8005A9325 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - 1ECDD3D82EFB1FEB005A9325 /* Sources */ = { + 1ECDD4D72EFD7FC9005A9325 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - 1ECDD3E52EFB2026005A9325 /* Sources */ = { + 1ECDD4E12EFD7FC9005A9325 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( @@ -245,20 +256,20 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 1ECDD3E12EFB1FEB005A9325 /* PBXTargetDependency */ = { + 1ECDD4DD2EFD7FC9005A9325 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 1ECDD3152EFAB723005A9325 /* Testcode-last */; - targetProxy = 1ECDD3E02EFB1FEB005A9325 /* PBXContainerItemProxy */; + target = 1ECDD4CD2EFD7FC8005A9325 /* CalculatorProject */; + targetProxy = 1ECDD4DC2EFD7FC9005A9325 /* PBXContainerItemProxy */; }; - 1ECDD3F02EFB2026005A9325 /* PBXTargetDependency */ = { + 1ECDD4E72EFD7FC9005A9325 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 1ECDD3152EFAB723005A9325 /* Testcode-last */; - targetProxy = 1ECDD3EF2EFB2026005A9325 /* PBXContainerItemProxy */; + target = 1ECDD4CD2EFD7FC8005A9325 /* CalculatorProject */; + targetProxy = 1ECDD4E62EFD7FC9005A9325 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 1ECDD31F2EFAB724005A9325 /* Debug */ = { + 1ECDD4ED2EFD7FC9005A9325 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -322,7 +333,7 @@ }; name = Debug; }; - 1ECDD3202EFAB724005A9325 /* Release */ = { + 1ECDD4EE2EFD7FC9005A9325 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -379,7 +390,7 @@ }; name = Release; }; - 1ECDD3222EFAB724005A9325 /* Debug */ = { + 1ECDD4F02EFD7FC9005A9325 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; @@ -399,7 +410,7 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = "come.Jin.Testcode-last"; + PRODUCT_BUNDLE_IDENTIFIER = come.Jin.CalculatorProject; PRODUCT_NAME = "$(TARGET_NAME)"; STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_APPROACHABLE_CONCURRENCY = YES; @@ -411,7 +422,7 @@ }; name = Debug; }; - 1ECDD3232EFAB724005A9325 /* Release */ = { + 1ECDD4F12EFD7FC9005A9325 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; @@ -431,7 +442,7 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = "come.Jin.Testcode-last"; + PRODUCT_BUNDLE_IDENTIFIER = come.Jin.CalculatorProject; PRODUCT_NAME = "$(TARGET_NAME)"; STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_APPROACHABLE_CONCURRENCY = YES; @@ -443,7 +454,7 @@ }; name = Release; }; - 1ECDD3E32EFB1FEB005A9325 /* Debug */ = { + 1ECDD4F32EFD7FC9005A9325 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; @@ -451,8 +462,9 @@ CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = 5RA2A76S4S; GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 26.0; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = "come.Jin.Testcode-lastTest"; + PRODUCT_BUNDLE_IDENTIFIER = come.Jin.CalculatorProjectTests; PRODUCT_NAME = "$(TARGET_NAME)"; STRING_CATALOG_GENERATE_SYMBOLS = NO; SWIFT_APPROACHABLE_CONCURRENCY = YES; @@ -460,11 +472,11 @@ SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Testcode-last.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Testcode-last"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CalculatorProject.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/CalculatorProject"; }; name = Debug; }; - 1ECDD3E42EFB1FEB005A9325 /* Release */ = { + 1ECDD4F42EFD7FC9005A9325 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; @@ -472,8 +484,9 @@ CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = 5RA2A76S4S; GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 26.0; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = "come.Jin.Testcode-lastTest"; + PRODUCT_BUNDLE_IDENTIFIER = come.Jin.CalculatorProjectTests; PRODUCT_NAME = "$(TARGET_NAME)"; STRING_CATALOG_GENERATE_SYMBOLS = NO; SWIFT_APPROACHABLE_CONCURRENCY = YES; @@ -481,11 +494,11 @@ SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Testcode-last.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Testcode-last"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CalculatorProject.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/CalculatorProject"; }; name = Release; }; - 1ECDD3F22EFB2026005A9325 /* Debug */ = { + 1ECDD4F62EFD7FC9005A9325 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; @@ -493,7 +506,7 @@ DEVELOPMENT_TEAM = 5RA2A76S4S; GENERATE_INFOPLIST_FILE = YES; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = "come.Jin.Testcode-lastUITest"; + PRODUCT_BUNDLE_IDENTIFIER = come.Jin.CalculatorProjectUITests; PRODUCT_NAME = "$(TARGET_NAME)"; STRING_CATALOG_GENERATE_SYMBOLS = NO; SWIFT_APPROACHABLE_CONCURRENCY = YES; @@ -501,11 +514,11 @@ SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; - TEST_TARGET_NAME = "Testcode-last"; + TEST_TARGET_NAME = CalculatorProject; }; name = Debug; }; - 1ECDD3F32EFB2026005A9325 /* Release */ = { + 1ECDD4F72EFD7FC9005A9325 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; @@ -513,7 +526,7 @@ DEVELOPMENT_TEAM = 5RA2A76S4S; GENERATE_INFOPLIST_FILE = YES; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = "come.Jin.Testcode-lastUITest"; + PRODUCT_BUNDLE_IDENTIFIER = come.Jin.CalculatorProjectUITests; PRODUCT_NAME = "$(TARGET_NAME)"; STRING_CATALOG_GENERATE_SYMBOLS = NO; SWIFT_APPROACHABLE_CONCURRENCY = YES; @@ -521,50 +534,50 @@ SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; - TEST_TARGET_NAME = "Testcode-last"; + TEST_TARGET_NAME = CalculatorProject; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 1ECDD3112EFAB723005A9325 /* Build configuration list for PBXProject "Testcode-last" */ = { + 1ECDD4C92EFD7FC8005A9325 /* Build configuration list for PBXProject "CalculatorProject" */ = { isa = XCConfigurationList; buildConfigurations = ( - 1ECDD31F2EFAB724005A9325 /* Debug */, - 1ECDD3202EFAB724005A9325 /* Release */, + 1ECDD4ED2EFD7FC9005A9325 /* Debug */, + 1ECDD4EE2EFD7FC9005A9325 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 1ECDD3212EFAB724005A9325 /* Build configuration list for PBXNativeTarget "Testcode-last" */ = { + 1ECDD4EF2EFD7FC9005A9325 /* Build configuration list for PBXNativeTarget "CalculatorProject" */ = { isa = XCConfigurationList; buildConfigurations = ( - 1ECDD3222EFAB724005A9325 /* Debug */, - 1ECDD3232EFAB724005A9325 /* Release */, + 1ECDD4F02EFD7FC9005A9325 /* Debug */, + 1ECDD4F12EFD7FC9005A9325 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 1ECDD3E22EFB1FEB005A9325 /* Build configuration list for PBXNativeTarget "Testcode-lastTest" */ = { + 1ECDD4F22EFD7FC9005A9325 /* Build configuration list for PBXNativeTarget "CalculatorProjectTests" */ = { isa = XCConfigurationList; buildConfigurations = ( - 1ECDD3E32EFB1FEB005A9325 /* Debug */, - 1ECDD3E42EFB1FEB005A9325 /* Release */, + 1ECDD4F32EFD7FC9005A9325 /* Debug */, + 1ECDD4F42EFD7FC9005A9325 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 1ECDD3F12EFB2026005A9325 /* Build configuration list for PBXNativeTarget "Testcode-lastUITest" */ = { + 1ECDD4F52EFD7FC9005A9325 /* Build configuration list for PBXNativeTarget "CalculatorProjectUITests" */ = { isa = XCConfigurationList; buildConfigurations = ( - 1ECDD3F22EFB2026005A9325 /* Debug */, - 1ECDD3F32EFB2026005A9325 /* Release */, + 1ECDD4F62EFD7FC9005A9325 /* Debug */, + 1ECDD4F72EFD7FC9005A9325 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; - rootObject = 1ECDD30E2EFAB723005A9325 /* Project object */; + rootObject = 1ECDD4C62EFD7FC8005A9325 /* Project object */; } diff --git a/Testcode-last/Testcode-last.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/CalculatorProject/CalculatorProject.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 100% rename from Testcode-last/Testcode-last.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to CalculatorProject/CalculatorProject.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/Testcode-last/Testcode-last/Assets.xcassets/AccentColor.colorset/Contents.json b/CalculatorProject/CalculatorProject/Assets.xcassets/AccentColor.colorset/Contents.json similarity index 100% rename from Testcode-last/Testcode-last/Assets.xcassets/AccentColor.colorset/Contents.json rename to CalculatorProject/CalculatorProject/Assets.xcassets/AccentColor.colorset/Contents.json diff --git a/Testcode-last/Testcode-last/Assets.xcassets/AppIcon.appiconset/Contents.json b/CalculatorProject/CalculatorProject/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from Testcode-last/Testcode-last/Assets.xcassets/AppIcon.appiconset/Contents.json rename to CalculatorProject/CalculatorProject/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/Testcode-last/Testcode-last/Assets.xcassets/Contents.json b/CalculatorProject/CalculatorProject/Assets.xcassets/Contents.json similarity index 100% rename from Testcode-last/Testcode-last/Assets.xcassets/Contents.json rename to CalculatorProject/CalculatorProject/Assets.xcassets/Contents.json diff --git a/Testcode-last/Testcode-last/Testcode_lastApp.swift b/CalculatorProject/CalculatorProject/CalculatorProjectApp.swift similarity index 51% rename from Testcode-last/Testcode-last/Testcode_lastApp.swift rename to CalculatorProject/CalculatorProject/CalculatorProjectApp.swift index 1465b07..6efa3e4 100644 --- a/Testcode-last/Testcode-last/Testcode_lastApp.swift +++ b/CalculatorProject/CalculatorProject/CalculatorProjectApp.swift @@ -1,14 +1,14 @@ // -// Testcode_lastApp.swift -// Testcode-last +// CalculatorProjectApp.swift +// CalculatorProject // -// Created by JIN on 12/23/25. +// Created by JIN on 12/25/25. // import SwiftUI @main -struct Testcode_lastApp: App { +struct CalculatorProjectApp: App { var body: some Scene { WindowGroup { ContentView() diff --git a/Testcode-last/Testcode-last/ContentView.swift b/CalculatorProject/CalculatorProject/ContentView.swift similarity index 86% rename from Testcode-last/Testcode-last/ContentView.swift rename to CalculatorProject/CalculatorProject/ContentView.swift index 85beb0d..c7a8c10 100644 --- a/Testcode-last/Testcode-last/ContentView.swift +++ b/CalculatorProject/CalculatorProject/ContentView.swift @@ -1,8 +1,8 @@ // // ContentView.swift -// Testcode-last +// CalculatorProject // -// Created by JIN on 12/23/25. +// Created by JIN on 12/25/25. // import SwiftUI diff --git a/CalculatorProject/CalculatorProjectTests/CalculatorProjectTests.swift b/CalculatorProject/CalculatorProjectTests/CalculatorProjectTests.swift new file mode 100644 index 0000000..2807f4f --- /dev/null +++ b/CalculatorProject/CalculatorProjectTests/CalculatorProjectTests.swift @@ -0,0 +1,36 @@ +// +// CalculatorProjectTests.swift +// CalculatorProjectTests +// +// Created by JIN on 12/25/25. +// + +import XCTest +@testable import CalculatorProject + +final class CalculatorProjectTests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + 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. + // Any test you write for XCTest can be annotated as throws and async. + // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. + // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. + } + + func testPerformanceExample() throws { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + } + } + +} diff --git a/CalculatorProject/CalculatorProjectUITests/CalculatorProjectUITests.swift b/CalculatorProject/CalculatorProjectUITests/CalculatorProjectUITests.swift new file mode 100644 index 0000000..550fa5d --- /dev/null +++ b/CalculatorProject/CalculatorProjectUITests/CalculatorProjectUITests.swift @@ -0,0 +1,41 @@ +// +// CalculatorProjectUITests.swift +// CalculatorProjectUITests +// +// Created by JIN on 12/25/25. +// + +import XCTest + +final class CalculatorProjectUITests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + + // In UI tests it is usually best to stop immediately when a failure occurs. + continueAfterFailure = false + + // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + @MainActor + func testExample() throws { + // UI tests must launch the application that they test. + let app = XCUIApplication() + app.launch() + + // Use XCTAssert and related functions to verify your tests produce the correct results. + } + + @MainActor + func testLaunchPerformance() throws { + // This measures how long it takes to launch your application. + measure(metrics: [XCTApplicationLaunchMetric()]) { + XCUIApplication().launch() + } + } +} diff --git a/CalculatorProject/CalculatorProjectUITests/CalculatorProjectUITestsLaunchTests.swift b/CalculatorProject/CalculatorProjectUITests/CalculatorProjectUITestsLaunchTests.swift new file mode 100644 index 0000000..5bdb433 --- /dev/null +++ b/CalculatorProject/CalculatorProjectUITests/CalculatorProjectUITestsLaunchTests.swift @@ -0,0 +1,33 @@ +// +// CalculatorProjectUITestsLaunchTests.swift +// CalculatorProjectUITests +// +// Created by JIN on 12/25/25. +// + +import XCTest + +final class CalculatorProjectUITestsLaunchTests: XCTestCase { + + override class var runsForEachTargetApplicationUIConfiguration: Bool { + true + } + + override func setUpWithError() throws { + continueAfterFailure = false + } + + @MainActor + func testLaunch() throws { + let app = XCUIApplication() + app.launch() + + // Insert steps here to perform after app launch but before taking a screenshot, + // such as logging into a test account or navigating somewhere in the app + + let attachment = XCTAttachment(screenshot: app.screenshot()) + attachment.name = "Launch Screen" + attachment.lifetime = .keepAlways + add(attachment) + } +} diff --git a/Testcode-last/Testcode-last/Models/Operation.swift b/Testcode-last/Testcode-last/Models/Operation.swift deleted file mode 100644 index 6060756..0000000 --- a/Testcode-last/Testcode-last/Models/Operation.swift +++ /dev/null @@ -1,24 +0,0 @@ -// -// Operation.swift -// Testcode-last -// -// Created by JIN on 12/25/25. -// - -import Foundation - -enum Operation { - case add - case subtract - case multiply - case divide - - var symbol: String { - switch self { - case .add: return "+" - case .subtract: return "-" - case .multiply: return "×" - case .divide: return "÷" - } - } -} From fbaeb5f6f426a50cf80e4636eaa937c602e061ef Mon Sep 17 00:00:00 2001 From: JIN Date: Fri, 26 Dec 2025 18:47:04 +0900 Subject: [PATCH 4/6] =?UTF-8?q?ViewModel=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CalculatorProject/Models/Calculator.swift | 29 ++++ .../Models/CalculatorButton.swift | 68 +++++++++ .../Models/CalculatorSate.swift | 22 +++ .../CalculatorProject/Models/Operation.swift | 24 +++ .../ViewModels/CalculatorViewModel.swift | 99 ++++++++++++ .../CalculatorProjectTests.swift | 36 ----- .../Models/CalculatorProjectTests.swift | 100 +++++++++++++ .../ViewModels/CalculatroViewModelTest.swift | 141 ++++++++++++++++++ 8 files changed, 483 insertions(+), 36 deletions(-) create mode 100644 CalculatorProject/CalculatorProject/Models/Calculator.swift create mode 100644 CalculatorProject/CalculatorProject/Models/CalculatorButton.swift create mode 100644 CalculatorProject/CalculatorProject/Models/CalculatorSate.swift create mode 100644 CalculatorProject/CalculatorProject/Models/Operation.swift create mode 100644 CalculatorProject/CalculatorProject/ViewModels/CalculatorViewModel.swift delete mode 100644 CalculatorProject/CalculatorProjectTests/CalculatorProjectTests.swift create mode 100644 CalculatorProject/CalculatorProjectTests/Models/CalculatorProjectTests.swift create mode 100644 CalculatorProject/CalculatorProjectTests/ViewModels/CalculatroViewModelTest.swift diff --git a/CalculatorProject/CalculatorProject/Models/Calculator.swift b/CalculatorProject/CalculatorProject/Models/Calculator.swift new file mode 100644 index 0000000..2374d58 --- /dev/null +++ b/CalculatorProject/CalculatorProject/Models/Calculator.swift @@ -0,0 +1,29 @@ +// +// Calculator.swift +// CalculatorProject +// +// Created by JIN on 12/25/25. +// + +import SwiftUI + +// MARK: - Protocol +protocol CalculatorProtocol { + func calculate(lhs: Double, rhs: Double, operation: Operation) -> Double +} + +// MARK: - Implementation +final class Calculator: CalculatorProtocol { + func calculate(lhs: Double, rhs: Double, operation: Operation) -> Double { + switch operation { + case .add: + return lhs + rhs + case .subtract: + return lhs - rhs + case .multiply: + return lhs * rhs + case .divide: + return rhs != 0 ? lhs / rhs : 0 + } + } +} diff --git a/CalculatorProject/CalculatorProject/Models/CalculatorButton.swift b/CalculatorProject/CalculatorProject/Models/CalculatorButton.swift new file mode 100644 index 0000000..6f52d95 --- /dev/null +++ b/CalculatorProject/CalculatorProject/Models/CalculatorButton.swift @@ -0,0 +1,68 @@ +// +// Button.swift +// CalculatorProject +// +// Created by JIN on 12/25/25. +// + +import SwiftUI + +enum CalculatorButton: Hashable { + case zero, one, two, three, four + case five, six, seven, eight, nine + + case add + case subtract + case multiply + case divide + + case equal + case clear + + var title: String { + switch self { + case .zero: return "0" + case .one: return "1" + case .two: return "2" + case .three: return "3" + case .four: return "4" + case .five: return "5" + case .six: return "6" + case .seven: return "7" + case .eight: return "8" + case .nine: return "9" + case .add: return "+" + case .subtract: return "-" + case .multiply: return "×" + case .divide: return "÷" + case .equal: return "=" + case .clear: return "AC" + } + } + + var number: Int? { + switch self { + case .zero: return 0 + case .one: return 1 + case .two: return 2 + case .three: return 3 + case .four: return 4 + case .five: return 5 + case .six: return 6 + case .seven: return 7 + case .eight: return 8 + case .nine: return 9 + default: return nil + } + } + + var operation: Operation? { + switch self { + case .add: return .add + case .subtract: return .subtract + case .multiply: return .multiply + case .divide: return .divide + default: return nil + } + } +} diff --git a/CalculatorProject/CalculatorProject/Models/CalculatorSate.swift b/CalculatorProject/CalculatorProject/Models/CalculatorSate.swift new file mode 100644 index 0000000..21f5a21 --- /dev/null +++ b/CalculatorProject/CalculatorProject/Models/CalculatorSate.swift @@ -0,0 +1,22 @@ +// +// CalculatorSate.swift +// CalculatorProject +// +// Created by JIN on 12/25/25. +// + +import SwiftUI + +struct CalculatorState { + var currentValue: Double = 0 + var storedValue: Double? + var currentOperation: Operation? + var isNewInput: Bool = true + + mutating func reset() { + currentValue = 0 + storedValue = nil + currentOperation = nil + isNewInput = true + } +} diff --git a/CalculatorProject/CalculatorProject/Models/Operation.swift b/CalculatorProject/CalculatorProject/Models/Operation.swift new file mode 100644 index 0000000..12c11c3 --- /dev/null +++ b/CalculatorProject/CalculatorProject/Models/Operation.swift @@ -0,0 +1,24 @@ +// +// Operation.swift +// CalculatorProject +// +// Created by JIN on 12/25/25. +// + +import SwiftUI + +enum Operation { + case add + case subtract + case multiply + case divide + + var symbol: String { + switch self { + case .add: return "+" + case .subtract: return "-" + case .multiply: return "×" + case .divide: return "÷" + } + } +} diff --git a/CalculatorProject/CalculatorProject/ViewModels/CalculatorViewModel.swift b/CalculatorProject/CalculatorProject/ViewModels/CalculatorViewModel.swift new file mode 100644 index 0000000..fc1303d --- /dev/null +++ b/CalculatorProject/CalculatorProject/ViewModels/CalculatorViewModel.swift @@ -0,0 +1,99 @@ +// +// CalculatorViewModel.swift +// CalculatorProject +// +// Created by JIN on 12/26/25. +// + +import Foundation +import Combine + +final class CalculatorViewModel: ObservableObject { + @Published private(set) var state: CalculatorState + private let calculator: CalculatorProtocol + + var displayValue: String { + formatNumber(state.currentValue) + } + + init(calculator: CalculatorProtocol) { + self.calculator = calculator + self.state = CalculatorState() + } + + func buttonPressed(_ button: CalculatorButton) { + switch button { + case .zero, .one, .two, .three, .four, .five, .six, .seven, .eight, .nine: + handleNumberInput(button) + case .add, .subtract, .multiply, .divide: + handleOperation(button) + case .equal: + handleEqual() + case .clear: + handleClear() + } + } + + // MARK: - Private Methods + + private func handleNumberInput(_ button: CalculatorButton) { + guard let number = button.number else { return } + + if state.isNewInput { + state.currentValue = Double(number) + state.isNewInput = false + } else { + let currentString = String(Int(state.currentValue)) + let newString = currentString + String(number) + state.currentValue = Double(newString) ?? state.currentValue + } + } + + private func handleOperation(_ button: CalculatorButton) { + guard let operation = button.operation else { return } + + if let storedValue = state.storedValue, + let currentOperation = state.currentOperation, + !state.isNewInput { + let result = calculator.calculate( + lhs: storedValue, + rhs: state.currentValue, + operation: currentOperation + ) + state.currentValue = result + } + state.storedValue = state.currentValue + state.currentOperation = operation + state.isNewInput = true + } + + private func handleEqual() { + guard let storedValue = state.storedValue, + let operation = state.currentOperation else { + return + } + + let result = calculator.calculate( + lhs: storedValue, + rhs: state.currentValue, + operation: operation + ) + + state.currentValue = result + state.storedValue = nil + state.currentOperation = nil + state.isNewInput = true + } + + private func handleClear() { + state.reset() + } + + private func formatNumber(_ value: Double) -> String { + if value.truncatingRemainder(dividingBy: 1) == 0 { + return String(Int(value)) + } else { + return String(value) + } + } +} diff --git a/CalculatorProject/CalculatorProjectTests/CalculatorProjectTests.swift b/CalculatorProject/CalculatorProjectTests/CalculatorProjectTests.swift deleted file mode 100644 index 2807f4f..0000000 --- a/CalculatorProject/CalculatorProjectTests/CalculatorProjectTests.swift +++ /dev/null @@ -1,36 +0,0 @@ -// -// CalculatorProjectTests.swift -// CalculatorProjectTests -// -// Created by JIN on 12/25/25. -// - -import XCTest -@testable import CalculatorProject - -final class CalculatorProjectTests: XCTestCase { - - override func setUpWithError() throws { - // Put setup code here. This method is called before the invocation of each test method in the class. - } - - override func tearDownWithError() throws { - // Put teardown code here. This method is called after the invocation of each test method in the class. - } - - 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. - // Any test you write for XCTest can be annotated as throws and async. - // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. - // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. - } - - func testPerformanceExample() throws { - // This is an example of a performance test case. - self.measure { - // Put the code you want to measure the time of here. - } - } - -} diff --git a/CalculatorProject/CalculatorProjectTests/Models/CalculatorProjectTests.swift b/CalculatorProject/CalculatorProjectTests/Models/CalculatorProjectTests.swift new file mode 100644 index 0000000..db9a57e --- /dev/null +++ b/CalculatorProject/CalculatorProjectTests/Models/CalculatorProjectTests.swift @@ -0,0 +1,100 @@ +// +// CalculatorProjectTests.swift +// CalculatorProjectTests +// +// Created by JIN on 12/25/25. +// + +import XCTest +@testable import CalculatorProject + +final class CalculatorProjectTests: XCTestCase { + + var sut: Calculator! + + override func setUp() { + super.setUp() + sut = Calculator() + } + + override func tearDown() { + sut = nil + super.tearDown() + } + + // MARK: - Addition Tests + func test_calculate_whenAddingTwoAndThree_returnsFive() { + let lhs = 2.0 + let rhs = 3.0 + + let result = sut.calculate(lhs: lhs, rhs: rhs, operation: .add) + + XCTAssertEqual(result, 5.0) + } + + func test_calculate_whenAddingNegativeAndPositive_returnsCorrectSum() { + let lhs = -5.0 + let rhs = 3.0 + + let result = sut.calculate(lhs: lhs, rhs: rhs, operation: .add) + + XCTAssertEqual(result, -2.0) + } + + // MARK: - Subtraction Tests + func test_calculate_whenSubtractingThreeFromFive_returnsTwo() { + let lhs = 5.0 + let rhs = 3.0 + + let result = sut.calculate(lhs: lhs, rhs: rhs, operation: .subtract) + + XCTAssertEqual(result, 2.0) + } + + func test_calculate_whenSubtractingLargerFromSmaller_returnsNegativeResult() { + let lhs = 3.0 + let rhs = 5.0 + + let result = sut.calculate(lhs: lhs, rhs: rhs, operation: .subtract) + + XCTAssertEqual(result, -2.0) + } + + // MARK: - Multiplication Tests + + func test_calculate_whenMultiplyingFourAndThree_returnsTwelve() { + let lhs = 4.0 + let rhs = 3.0 + + let result = sut.calculate(lhs: lhs, rhs: rhs, operation: .multiply) + + XCTAssertEqual(result, 12.0) + } + + func test_calculate_whenMultiplyingByZero_returnsZero() { + let lhs = 0.0 + let rhs = 5.0 + + let result = sut.calculate(lhs: lhs, rhs: rhs, operation: .multiply) + + XCTAssertEqual(result, 0.0) + } + + func test_calculate_whenDividingTenByTwo_returnsFive() { + let lhs = 10.0 + let rhs = 2.0 + + let result = sut.calculate(lhs: lhs, rhs: rhs, operation: .divide) + + XCTAssertEqual(result, 5.0) + } + + func test_calculate_whenDividingByZero_returnsZero() { + let lhs = 10.0 + let rhs = 0.0 + + let result = sut.calculate(lhs: lhs, rhs: rhs, operation: .divide) + + XCTAssertEqual(result, 0.0) + } +} diff --git a/CalculatorProject/CalculatorProjectTests/ViewModels/CalculatroViewModelTest.swift b/CalculatorProject/CalculatorProjectTests/ViewModels/CalculatroViewModelTest.swift new file mode 100644 index 0000000..5a482f5 --- /dev/null +++ b/CalculatorProject/CalculatorProjectTests/ViewModels/CalculatroViewModelTest.swift @@ -0,0 +1,141 @@ +// +// CalculatroViewModelTest.swift +// CalculatorProjectTests +// +// Created by JIN on 12/26/25. +// + +import XCTest +@testable import CalculatorProject + +final class CalculatorViewModelTests: XCTestCase { + var sut: CalculatorViewModel! + var mockCalculator: Calculator! + + override func setUp() { + super.setUp() + mockCalculator = Calculator() + sut = CalculatorViewModel(calculator: mockCalculator) + } + + override func tearDown() { + sut = nil + mockCalculator = nil + super.tearDown() + } + + // MARK: - Initial State Tests + + func test_initialState_shouldDisplayZero() { + XCTAssertEqual(sut.displayValue, "0") + } + + // MARK: - Number Input Tests + + func test_pressNumberButton_shouldUpdateDisplay() { + sut.buttonPressed(.two) + XCTAssertEqual(sut.displayValue, "2") + } + + func test_pressMultipleNumbers_shouldConcatenate() { + sut.buttonPressed(.two) + sut.buttonPressed(.four) + XCTAssertEqual(sut.displayValue, "24") + } + + // MARK: - Operation Tests + + func test_pressAddOperation_shouldStoreValueAndOperation() { + sut.buttonPressed(.two) + sut.buttonPressed(.four) + sut.buttonPressed(.add) + XCTAssertEqual(sut.displayValue, "24") + } + + func test_afterOperation_newNumberShouldReplaceDisplay() { + sut.buttonPressed(.two) + sut.buttonPressed(.four) + sut.buttonPressed(.add) + sut.buttonPressed(.three) + XCTAssertEqual(sut.displayValue, "3") + } + + // MARK: - Continuous Calculation Tests + + func test_continuousCalculation_24plus36plus20_shouldEqual80() { + sut.buttonPressed(.two) + sut.buttonPressed(.four) + XCTAssertEqual(sut.displayValue, "24") + sut.buttonPressed(.add) + XCTAssertEqual(sut.displayValue, "24") + sut.buttonPressed(.three) + sut.buttonPressed(.six) + XCTAssertEqual(sut.displayValue, "36") + sut.buttonPressed(.add) + XCTAssertEqual(sut.displayValue, "60") + sut.buttonPressed(.two) + sut.buttonPressed(.zero) + XCTAssertEqual(sut.displayValue, "20") + sut.buttonPressed(.equal) + XCTAssertEqual(sut.displayValue, "80") + } + + // MARK: - Equal Operation Tests + + func test_simpleAddition_shouldCalculateCorrectly() { + sut.buttonPressed(.two) + sut.buttonPressed(.four) + sut.buttonPressed(.add) + sut.buttonPressed(.three) + sut.buttonPressed(.six) + sut.buttonPressed(.equal) + XCTAssertEqual(sut.displayValue, "60") + } + + func test_simpleSubtraction_shouldCalculateCorrectly() { + sut.buttonPressed(.five) + sut.buttonPressed(.zero) + sut.buttonPressed(.subtract) + sut.buttonPressed(.three) + sut.buttonPressed(.zero) + sut.buttonPressed(.equal) + XCTAssertEqual(sut.displayValue, "20") + } + + func test_simpleMultiplication_shouldCalculateCorrectly() { + sut.buttonPressed(.one) + sut.buttonPressed(.two) + sut.buttonPressed(.multiply) + sut.buttonPressed(.five) + sut.buttonPressed(.equal) + XCTAssertEqual(sut.displayValue, "60") + } + + func test_simpleDivision_shouldCalculateCorrectly() { + sut.buttonPressed(.eight) + sut.buttonPressed(.zero) + sut.buttonPressed(.divide) + sut.buttonPressed(.four) + sut.buttonPressed(.equal) + XCTAssertEqual(sut.displayValue, "20") + } + + // MARK: - Clear Operation Tests + + func test_clearButton_shouldResetToInitialState() { + sut.buttonPressed(.two) + sut.buttonPressed(.four) + sut.buttonPressed(.add) + sut.buttonPressed(.three) + sut.buttonPressed(.six) + sut.buttonPressed(.clear) + XCTAssertEqual(sut.displayValue, "0") + } + + func test_clearButton_afterClear_canStartNewCalculation() { + sut.buttonPressed(.five) + sut.buttonPressed(.clear) + sut.buttonPressed(.three) + XCTAssertEqual(sut.displayValue, "3") + } +} From f871e1b2fd8b54374bbfed77998f8660ae0e1bae Mon Sep 17 00:00:00 2001 From: JIN Date: Fri, 26 Dec 2025 18:47:32 +0900 Subject: [PATCH 5/6] =?UTF-8?q?View=20=EB=B0=8F=20DI=20Container=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CalculatorProjectApp.swift | 2 +- .../DIContainer/AppDIContainer.swift | 19 ++++++++ .../Views/CalculatorView.swift | 45 +++++++++++++++++++ .../Components/CalculatorButtonView.swift | 38 ++++++++++++++++ .../Views/Components/DisplayView.swift | 26 +++++++++++ 5 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 CalculatorProject/CalculatorProject/DIContainer/AppDIContainer.swift create mode 100644 CalculatorProject/CalculatorProject/Views/CalculatorView.swift create mode 100644 CalculatorProject/CalculatorProject/Views/Components/CalculatorButtonView.swift create mode 100644 CalculatorProject/CalculatorProject/Views/Components/DisplayView.swift diff --git a/CalculatorProject/CalculatorProject/CalculatorProjectApp.swift b/CalculatorProject/CalculatorProject/CalculatorProjectApp.swift index 6efa3e4..f8e2621 100644 --- a/CalculatorProject/CalculatorProject/CalculatorProjectApp.swift +++ b/CalculatorProject/CalculatorProject/CalculatorProjectApp.swift @@ -11,7 +11,7 @@ import SwiftUI struct CalculatorProjectApp: App { var body: some Scene { WindowGroup { - ContentView() + CalculatorView() } } } diff --git a/CalculatorProject/CalculatorProject/DIContainer/AppDIContainer.swift b/CalculatorProject/CalculatorProject/DIContainer/AppDIContainer.swift new file mode 100644 index 0000000..f697609 --- /dev/null +++ b/CalculatorProject/CalculatorProject/DIContainer/AppDIContainer.swift @@ -0,0 +1,19 @@ +// +// AppDIContainer.swift +// CalculatorProject +// +// Created by JIN on 12/26/25. +// + +import Foundation + +final class AppDIContainer { + static let shared = AppDIContainer() + + private init() {} + + func makeCalculatorViewModel() -> CalculatorViewModel { + let calculator = Calculator() + return CalculatorViewModel(calculator: calculator) + } +} diff --git a/CalculatorProject/CalculatorProject/Views/CalculatorView.swift b/CalculatorProject/CalculatorProject/Views/CalculatorView.swift new file mode 100644 index 0000000..72229b3 --- /dev/null +++ b/CalculatorProject/CalculatorProject/Views/CalculatorView.swift @@ -0,0 +1,45 @@ +// +// CalculatorView.swift +// CalculatorProject +// +// Created by JIN on 12/26/25. +// + +import SwiftUI + +struct CalculatorView: View { + + @StateObject private var viewModel = AppDIContainer.shared.makeCalculatorViewModel() + + private let buttonRows: [[CalculatorButton]] = [ + [.clear, .add, .subtract, .multiply], + [.seven, .eight, .nine, .divide], + [.four, .five, .six, .equal], + [.one, .two, .three, .zero] + ] + + var body: some View { + ZStack { + Color.white.ignoresSafeArea() + VStack(spacing: 12) { + DisplayView(text: viewModel.displayValue) + .padding(.top, 30) + Spacer() + ForEach(buttonRows, id: \.self) { row in + HStack(spacing: 12) { + ForEach(row, id: \.self) { button in + CalculatorButtonView(button: button) { + viewModel.buttonPressed(button) + } + } + } + } + } + .padding() + } + } +} + +#Preview { + CalculatorView() +} diff --git a/CalculatorProject/CalculatorProject/Views/Components/CalculatorButtonView.swift b/CalculatorProject/CalculatorProject/Views/Components/CalculatorButtonView.swift new file mode 100644 index 0000000..b63df7d --- /dev/null +++ b/CalculatorProject/CalculatorProject/Views/Components/CalculatorButtonView.swift @@ -0,0 +1,38 @@ +// +// CalculatorButtonView.swift +// CalculatorProject +// +// Created by JIN on 12/26/25. +// + +import SwiftUI + +struct CalculatorButtonView: View { + let button: CalculatorButton + let action: () -> Void + + private var backgroundColor: Color { + switch button { + case .add, .subtract, .multiply, .divide, .equal, .clear: + return Color.blue + default: + return Color.gray + } + } + + private var foregroundColor: Color { + return .white + } + + var body: some View { + Button(action: action) { + Text(button.title) + .font(.system(size: 32, weight: .medium)) + .foregroundColor(foregroundColor) + .frame(width: 80, height: 80) + .background(backgroundColor) + .clipShape(Circle()) + } + } +} + diff --git a/CalculatorProject/CalculatorProject/Views/Components/DisplayView.swift b/CalculatorProject/CalculatorProject/Views/Components/DisplayView.swift new file mode 100644 index 0000000..5d345bb --- /dev/null +++ b/CalculatorProject/CalculatorProject/Views/Components/DisplayView.swift @@ -0,0 +1,26 @@ +// +// DisplayView.swift +// CalculatorProject +// +// Created by JIN on 12/26/25. +// + +import SwiftUI + +struct DisplayView: View { + let text: String + + var body: some View { + HStack { + Spacer() + Text(text) + .font(.system(size: 64, weight: .light)) + .foregroundColor(.black) + .lineLimit(1) + .minimumScaleFactor(0.5) + .padding(.horizontal, 24) + } + .frame(maxWidth: .infinity, alignment: .trailing) + .frame(height: 100) + } +} From fa2168d7b3c44655046d60b6e0a06c8eb9283520 Mon Sep 17 00:00:00 2001 From: JIN Date: Fri, 26 Dec 2025 18:48:55 +0900 Subject: [PATCH 6/6] =?UTF-8?q?=ED=94=84=EB=A1=9C=EC=A0=9D=ED=8A=B8=20?= =?UTF-8?q?=EB=A7=88=EB=AC=B4=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CalculatorProjectUITests.swift | 11 +---------- .../CalculatorProjectUITestsLaunchTests.swift | 4 ---- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/CalculatorProject/CalculatorProjectUITests/CalculatorProjectUITests.swift b/CalculatorProject/CalculatorProjectUITests/CalculatorProjectUITests.swift index 550fa5d..bba74c6 100644 --- a/CalculatorProject/CalculatorProjectUITests/CalculatorProjectUITests.swift +++ b/CalculatorProject/CalculatorProjectUITests/CalculatorProjectUITests.swift @@ -10,30 +10,21 @@ import XCTest final class CalculatorProjectUITests: XCTestCase { override func setUpWithError() throws { - // Put setup code here. This method is called before the invocation of each test method in the class. - - // In UI tests it is usually best to stop immediately when a failure occurs. continueAfterFailure = false - - // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. } override func tearDownWithError() throws { - // Put teardown code here. This method is called after the invocation of each test method in the class. + } @MainActor func testExample() throws { - // UI tests must launch the application that they test. let app = XCUIApplication() app.launch() - - // Use XCTAssert and related functions to verify your tests produce the correct results. } @MainActor func testLaunchPerformance() throws { - // This measures how long it takes to launch your application. measure(metrics: [XCTApplicationLaunchMetric()]) { XCUIApplication().launch() } diff --git a/CalculatorProject/CalculatorProjectUITests/CalculatorProjectUITestsLaunchTests.swift b/CalculatorProject/CalculatorProjectUITests/CalculatorProjectUITestsLaunchTests.swift index 5bdb433..163ce4e 100644 --- a/CalculatorProject/CalculatorProjectUITests/CalculatorProjectUITestsLaunchTests.swift +++ b/CalculatorProject/CalculatorProjectUITests/CalculatorProjectUITestsLaunchTests.swift @@ -21,10 +21,6 @@ final class CalculatorProjectUITestsLaunchTests: XCTestCase { func testLaunch() throws { let app = XCUIApplication() app.launch() - - // Insert steps here to perform after app launch but before taking a screenshot, - // such as logging into a test account or navigating somewhere in the app - let attachment = XCTAttachment(screenshot: app.screenshot()) attachment.name = "Launch Screen" attachment.lifetime = .keepAlways