├── .gitignore ├── .gitmodules ├── CatchingFire.podspec ├── CatchingFire.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── CatchingFire.xcscmblueprint └── xcshareddata │ └── xcschemes │ ├── CatchingFire OS X.xcscheme │ ├── CatchingFire iOS.xcscheme │ └── CatchingFire.xcscheme ├── LICENSE ├── README.md ├── src ├── CatchingFire.h ├── CatchingFire.swift └── Info.plist └── test ├── CatchingFireTests.swift ├── ExampleTests.swift └── Info.plist /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | 20 | # CocoaPods 21 | # 22 | # We recommend against adding the Pods directory to your .gitignore. However 23 | # you should judge for yourself, the pros and cons are mentioned at: 24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 25 | # 26 | # Pods/ 27 | 28 | # Carthage 29 | # 30 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 31 | # Carthage/Checkouts 32 | 33 | Carthage/Build 34 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "xcconfigs"] 2 | path = xcconfigs 3 | url = git@github.com:mrackwitz/xcconfigs.git 4 | -------------------------------------------------------------------------------- /CatchingFire.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'CatchingFire' 3 | 4 | project = Xcodeproj::Project.open('CatchingFire.xcodeproj') 5 | target = project.targets.first 6 | version = target.build_settings('Debug')['CURRENT_PROJECT_VERSION'] 7 | 8 | s.version = version 9 | 10 | s.summary = 'XCTest-style expecters to test Swift error-handling' 11 | s.description = <<-eos 12 | CatchingFire is a Swift test framework, which helps making expectations against the error 13 | handling of your code. It integrates seamlessly with the expecters provided by `XCTest`. 14 | eos 15 | s.homepage = 'https://github.com/mrackwitz/CatchingFire' 16 | s.social_media_url = 'https://twitter.com/mrackwitz' 17 | s.author = { 'Marius Rackwitz' => 'git@mariusrackwitz.de' } 18 | s.license = 'MIT License' 19 | s.source = { :git => 'https://github.com/mrackwitz/CatchingFire.git', :tag => s.version.to_s } 20 | s.source_files = 'src/CatchingFire.swift' 21 | s.frameworks = 'XCTest' 22 | s.pod_target_xcconfig = { 23 | "FRAMEWORK_SEARCH_PATHS" => "$(inherited) '$(PLATFORM_DIR)/Developer/Library/Frameworks'" 24 | } 25 | s.ios.deployment_target = '8.0' 26 | s.osx.deployment_target = '10.9' 27 | end 28 | -------------------------------------------------------------------------------- /CatchingFire.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXAggregateTarget section */ 10 | 2932A0FF1B52B45700A71171 /* CatchingFire iOS */ = { 11 | isa = PBXAggregateTarget; 12 | buildConfigurationList = 2932A1021B52B45700A71171 /* Build configuration list for PBXAggregateTarget "CatchingFire iOS" */; 13 | buildPhases = ( 14 | 2932A10C1B52BD0D00A71171 /* Build Framework */, 15 | ); 16 | dependencies = ( 17 | ); 18 | name = "CatchingFire iOS"; 19 | productName = "CatchingFire iOS"; 20 | }; 21 | 2932A1051B52B6AE00A71171 /* CatchingFire OS X */ = { 22 | isa = PBXAggregateTarget; 23 | buildConfigurationList = 2932A1081B52B6AE00A71171 /* Build configuration list for PBXAggregateTarget "CatchingFire OS X" */; 24 | buildPhases = ( 25 | 2932A10B1B52BB8200A71171 /* Build Framework */, 26 | ); 27 | dependencies = ( 28 | ); 29 | name = "CatchingFire OS X"; 30 | productName = "CatchingFire iOS"; 31 | }; 32 | /* End PBXAggregateTarget section */ 33 | 34 | /* Begin PBXBuildFile section */ 35 | 29673D031B4C381300EC2043 /* CatchingFire.h in Headers */ = {isa = PBXBuildFile; fileRef = 29673D021B4C381300EC2043 /* CatchingFire.h */; settings = {ATTRIBUTES = (Public, ); }; }; 36 | 29673D0A1B4C381300EC2043 /* CatchingFire.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 29673CFF1B4C381300EC2043 /* CatchingFire.framework */; }; 37 | 29673D0F1B4C381300EC2043 /* CatchingFireTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29673D0E1B4C381300EC2043 /* CatchingFireTests.swift */; }; 38 | 29673D1A1B4C382200EC2043 /* CatchingFire.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29673D191B4C382200EC2043 /* CatchingFire.swift */; }; 39 | 29A2CEFC1B4EA3D10084D2DB /* ExampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29A2CEFB1B4EA3D10084D2DB /* ExampleTests.swift */; }; 40 | /* End PBXBuildFile section */ 41 | 42 | /* Begin PBXContainerItemProxy section */ 43 | 29673D0B1B4C381300EC2043 /* PBXContainerItemProxy */ = { 44 | isa = PBXContainerItemProxy; 45 | containerPortal = 29673CF61B4C381300EC2043 /* Project object */; 46 | proxyType = 1; 47 | remoteGlobalIDString = 29673CFE1B4C381300EC2043; 48 | remoteInfo = CatchingFire; 49 | }; 50 | /* End PBXContainerItemProxy section */ 51 | 52 | /* Begin PBXFileReference section */ 53 | 2932A0FB1B52ABE800A71171 /* UniversalFramework_Base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = UniversalFramework_Base.xcconfig; sourceTree = ""; }; 54 | 2932A0FC1B52ABE800A71171 /* UniversalFramework_Framework.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = UniversalFramework_Framework.xcconfig; sourceTree = ""; }; 55 | 2932A0FD1B52ABE800A71171 /* UniversalFramework_Test.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = UniversalFramework_Test.xcconfig; sourceTree = ""; }; 56 | 2932A10D1B52CB0800A71171 /* CatchingFire.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; indentWidth = 2; path = CatchingFire.podspec; sourceTree = ""; tabWidth = 2; }; 57 | 29673CFF1B4C381300EC2043 /* CatchingFire.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CatchingFire.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 58 | 29673D021B4C381300EC2043 /* CatchingFire.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CatchingFire.h; sourceTree = ""; }; 59 | 29673D041B4C381300EC2043 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 60 | 29673D091B4C381300EC2043 /* CatchingFireTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CatchingFireTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 61 | 29673D0E1B4C381300EC2043 /* CatchingFireTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CatchingFireTests.swift; sourceTree = ""; }; 62 | 29673D101B4C381300EC2043 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 63 | 29673D191B4C382200EC2043 /* CatchingFire.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CatchingFire.swift; sourceTree = ""; }; 64 | 29A2CEFB1B4EA3D10084D2DB /* ExampleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExampleTests.swift; sourceTree = ""; }; 65 | /* End PBXFileReference section */ 66 | 67 | /* Begin PBXFrameworksBuildPhase section */ 68 | 29673CFB1B4C381300EC2043 /* Frameworks */ = { 69 | isa = PBXFrameworksBuildPhase; 70 | buildActionMask = 2147483647; 71 | files = ( 72 | ); 73 | runOnlyForDeploymentPostprocessing = 0; 74 | }; 75 | 29673D061B4C381300EC2043 /* Frameworks */ = { 76 | isa = PBXFrameworksBuildPhase; 77 | buildActionMask = 2147483647; 78 | files = ( 79 | 29673D0A1B4C381300EC2043 /* CatchingFire.framework in Frameworks */, 80 | ); 81 | runOnlyForDeploymentPostprocessing = 0; 82 | }; 83 | /* End PBXFrameworksBuildPhase section */ 84 | 85 | /* Begin PBXGroup section */ 86 | 2932A0F81B52ABE800A71171 /* xcconfigs */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | 2932A0FB1B52ABE800A71171 /* UniversalFramework_Base.xcconfig */, 90 | 2932A0FC1B52ABE800A71171 /* UniversalFramework_Framework.xcconfig */, 91 | 2932A0FD1B52ABE800A71171 /* UniversalFramework_Test.xcconfig */, 92 | ); 93 | path = xcconfigs; 94 | sourceTree = ""; 95 | }; 96 | 29673CF51B4C381300EC2043 = { 97 | isa = PBXGroup; 98 | children = ( 99 | 2932A10D1B52CB0800A71171 /* CatchingFire.podspec */, 100 | 29673D011B4C381300EC2043 /* CatchingFire */, 101 | 29673D0D1B4C381300EC2043 /* CatchingFireTests */, 102 | 2932A0F81B52ABE800A71171 /* xcconfigs */, 103 | 29673D001B4C381300EC2043 /* Products */, 104 | ); 105 | sourceTree = ""; 106 | }; 107 | 29673D001B4C381300EC2043 /* Products */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | 29673CFF1B4C381300EC2043 /* CatchingFire.framework */, 111 | 29673D091B4C381300EC2043 /* CatchingFireTests.xctest */, 112 | ); 113 | name = Products; 114 | sourceTree = ""; 115 | }; 116 | 29673D011B4C381300EC2043 /* CatchingFire */ = { 117 | isa = PBXGroup; 118 | children = ( 119 | 29673D021B4C381300EC2043 /* CatchingFire.h */, 120 | 29673D191B4C382200EC2043 /* CatchingFire.swift */, 121 | 29673D041B4C381300EC2043 /* Info.plist */, 122 | ); 123 | name = CatchingFire; 124 | path = src; 125 | sourceTree = ""; 126 | }; 127 | 29673D0D1B4C381300EC2043 /* CatchingFireTests */ = { 128 | isa = PBXGroup; 129 | children = ( 130 | 29673D0E1B4C381300EC2043 /* CatchingFireTests.swift */, 131 | 29A2CEFB1B4EA3D10084D2DB /* ExampleTests.swift */, 132 | 29673D101B4C381300EC2043 /* Info.plist */, 133 | ); 134 | name = CatchingFireTests; 135 | path = test; 136 | sourceTree = ""; 137 | }; 138 | /* End PBXGroup section */ 139 | 140 | /* Begin PBXHeadersBuildPhase section */ 141 | 29673CFC1B4C381300EC2043 /* Headers */ = { 142 | isa = PBXHeadersBuildPhase; 143 | buildActionMask = 2147483647; 144 | files = ( 145 | 29673D031B4C381300EC2043 /* CatchingFire.h in Headers */, 146 | ); 147 | runOnlyForDeploymentPostprocessing = 0; 148 | }; 149 | /* End PBXHeadersBuildPhase section */ 150 | 151 | /* Begin PBXNativeTarget section */ 152 | 29673CFE1B4C381300EC2043 /* CatchingFire */ = { 153 | isa = PBXNativeTarget; 154 | buildConfigurationList = 29673D131B4C381300EC2043 /* Build configuration list for PBXNativeTarget "CatchingFire" */; 155 | buildPhases = ( 156 | 2932A0FE1B52ADFE00A71171 /* ShellScript */, 157 | 29673CFA1B4C381300EC2043 /* Sources */, 158 | 29673CFB1B4C381300EC2043 /* Frameworks */, 159 | 29673CFC1B4C381300EC2043 /* Headers */, 160 | 29673CFD1B4C381300EC2043 /* Resources */, 161 | ); 162 | buildRules = ( 163 | ); 164 | dependencies = ( 165 | ); 166 | name = CatchingFire; 167 | productName = CatchingFire; 168 | productReference = 29673CFF1B4C381300EC2043 /* CatchingFire.framework */; 169 | productType = "com.apple.product-type.framework"; 170 | }; 171 | 29673D081B4C381300EC2043 /* CatchingFireTests */ = { 172 | isa = PBXNativeTarget; 173 | buildConfigurationList = 29673D161B4C381300EC2043 /* Build configuration list for PBXNativeTarget "CatchingFireTests" */; 174 | buildPhases = ( 175 | 29673D051B4C381300EC2043 /* Sources */, 176 | 29673D061B4C381300EC2043 /* Frameworks */, 177 | 29673D071B4C381300EC2043 /* Resources */, 178 | ); 179 | buildRules = ( 180 | ); 181 | dependencies = ( 182 | 29673D0C1B4C381300EC2043 /* PBXTargetDependency */, 183 | ); 184 | name = CatchingFireTests; 185 | productName = CatchingFireTests; 186 | productReference = 29673D091B4C381300EC2043 /* CatchingFireTests.xctest */; 187 | productType = "com.apple.product-type.bundle.unit-test"; 188 | }; 189 | /* End PBXNativeTarget section */ 190 | 191 | /* Begin PBXProject section */ 192 | 29673CF61B4C381300EC2043 /* Project object */ = { 193 | isa = PBXProject; 194 | attributes = { 195 | LastSwiftUpdateCheck = 0700; 196 | LastUpgradeCheck = 0700; 197 | ORGANIZATIONNAME = "Marius Rackwitz"; 198 | TargetAttributes = { 199 | 2932A0FF1B52B45700A71171 = { 200 | CreatedOnToolsVersion = 7.0; 201 | }; 202 | 29673CFE1B4C381300EC2043 = { 203 | CreatedOnToolsVersion = 7.0; 204 | }; 205 | 29673D081B4C381300EC2043 = { 206 | CreatedOnToolsVersion = 7.0; 207 | }; 208 | }; 209 | }; 210 | buildConfigurationList = 29673CF91B4C381300EC2043 /* Build configuration list for PBXProject "CatchingFire" */; 211 | compatibilityVersion = "Xcode 3.2"; 212 | developmentRegion = English; 213 | hasScannedForEncodings = 0; 214 | knownRegions = ( 215 | en, 216 | ); 217 | mainGroup = 29673CF51B4C381300EC2043; 218 | productRefGroup = 29673D001B4C381300EC2043 /* Products */; 219 | projectDirPath = ""; 220 | projectRoot = ""; 221 | targets = ( 222 | 29673CFE1B4C381300EC2043 /* CatchingFire */, 223 | 29673D081B4C381300EC2043 /* CatchingFireTests */, 224 | 2932A0FF1B52B45700A71171 /* CatchingFire iOS */, 225 | 2932A1051B52B6AE00A71171 /* CatchingFire OS X */, 226 | ); 227 | }; 228 | /* End PBXProject section */ 229 | 230 | /* Begin PBXResourcesBuildPhase section */ 231 | 29673CFD1B4C381300EC2043 /* Resources */ = { 232 | isa = PBXResourcesBuildPhase; 233 | buildActionMask = 2147483647; 234 | files = ( 235 | ); 236 | runOnlyForDeploymentPostprocessing = 0; 237 | }; 238 | 29673D071B4C381300EC2043 /* Resources */ = { 239 | isa = PBXResourcesBuildPhase; 240 | buildActionMask = 2147483647; 241 | files = ( 242 | ); 243 | runOnlyForDeploymentPostprocessing = 0; 244 | }; 245 | /* End PBXResourcesBuildPhase section */ 246 | 247 | /* Begin PBXShellScriptBuildPhase section */ 248 | 2932A0FE1B52ADFE00A71171 /* ShellScript */ = { 249 | isa = PBXShellScriptBuildPhase; 250 | buildActionMask = 2147483647; 251 | files = ( 252 | ); 253 | inputPaths = ( 254 | ); 255 | outputPaths = ( 256 | ); 257 | runOnlyForDeploymentPostprocessing = 0; 258 | shellPath = /bin/sh; 259 | shellScript = "exit 0"; 260 | }; 261 | 2932A10B1B52BB8200A71171 /* Build Framework */ = { 262 | isa = PBXShellScriptBuildPhase; 263 | buildActionMask = 2147483647; 264 | files = ( 265 | ); 266 | inputPaths = ( 267 | ); 268 | name = "Build Framework"; 269 | outputPaths = ( 270 | ); 271 | runOnlyForDeploymentPostprocessing = 0; 272 | shellPath = /bin/sh; 273 | shellScript = "xcodebuild build -sdk macosx"; 274 | showEnvVarsInLog = 0; 275 | }; 276 | 2932A10C1B52BD0D00A71171 /* Build Framework */ = { 277 | isa = PBXShellScriptBuildPhase; 278 | buildActionMask = 2147483647; 279 | files = ( 280 | ); 281 | inputPaths = ( 282 | ); 283 | name = "Build Framework"; 284 | outputPaths = ( 285 | ); 286 | runOnlyForDeploymentPostprocessing = 0; 287 | shellPath = /bin/sh; 288 | shellScript = "xcodebuild build -sdk iphoneos"; 289 | showEnvVarsInLog = 0; 290 | }; 291 | /* End PBXShellScriptBuildPhase section */ 292 | 293 | /* Begin PBXSourcesBuildPhase section */ 294 | 29673CFA1B4C381300EC2043 /* Sources */ = { 295 | isa = PBXSourcesBuildPhase; 296 | buildActionMask = 2147483647; 297 | files = ( 298 | 29673D1A1B4C382200EC2043 /* CatchingFire.swift in Sources */, 299 | ); 300 | runOnlyForDeploymentPostprocessing = 0; 301 | }; 302 | 29673D051B4C381300EC2043 /* Sources */ = { 303 | isa = PBXSourcesBuildPhase; 304 | buildActionMask = 2147483647; 305 | files = ( 306 | 29A2CEFC1B4EA3D10084D2DB /* ExampleTests.swift in Sources */, 307 | 29673D0F1B4C381300EC2043 /* CatchingFireTests.swift in Sources */, 308 | ); 309 | runOnlyForDeploymentPostprocessing = 0; 310 | }; 311 | /* End PBXSourcesBuildPhase section */ 312 | 313 | /* Begin PBXTargetDependency section */ 314 | 29673D0C1B4C381300EC2043 /* PBXTargetDependency */ = { 315 | isa = PBXTargetDependency; 316 | target = 29673CFE1B4C381300EC2043 /* CatchingFire */; 317 | targetProxy = 29673D0B1B4C381300EC2043 /* PBXContainerItemProxy */; 318 | }; 319 | /* End PBXTargetDependency section */ 320 | 321 | /* Begin XCBuildConfiguration section */ 322 | 2932A1001B52B45700A71171 /* Debug */ = { 323 | isa = XCBuildConfiguration; 324 | buildSettings = { 325 | PRODUCT_NAME = "$(TARGET_NAME)"; 326 | }; 327 | name = Debug; 328 | }; 329 | 2932A1011B52B45700A71171 /* Release */ = { 330 | isa = XCBuildConfiguration; 331 | buildSettings = { 332 | PRODUCT_NAME = "$(TARGET_NAME)"; 333 | }; 334 | name = Release; 335 | }; 336 | 2932A1091B52B6AE00A71171 /* Debug */ = { 337 | isa = XCBuildConfiguration; 338 | buildSettings = { 339 | PRODUCT_NAME = "$(TARGET_NAME)"; 340 | }; 341 | name = Debug; 342 | }; 343 | 2932A10A1B52B6AE00A71171 /* Release */ = { 344 | isa = XCBuildConfiguration; 345 | buildSettings = { 346 | PRODUCT_NAME = "$(TARGET_NAME)"; 347 | }; 348 | name = Release; 349 | }; 350 | 29673D111B4C381300EC2043 /* Debug */ = { 351 | isa = XCBuildConfiguration; 352 | baseConfigurationReference = 2932A0FB1B52ABE800A71171 /* UniversalFramework_Base.xcconfig */; 353 | buildSettings = { 354 | ALWAYS_SEARCH_USER_PATHS = NO; 355 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 356 | CLANG_CXX_LIBRARY = "libc++"; 357 | CLANG_ENABLE_MODULES = YES; 358 | CLANG_ENABLE_OBJC_ARC = YES; 359 | CLANG_WARN_BOOL_CONVERSION = YES; 360 | CLANG_WARN_CONSTANT_CONVERSION = YES; 361 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 362 | CLANG_WARN_EMPTY_BODY = YES; 363 | CLANG_WARN_ENUM_CONVERSION = YES; 364 | CLANG_WARN_INT_CONVERSION = YES; 365 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 366 | CLANG_WARN_UNREACHABLE_CODE = YES; 367 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 368 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 369 | COPY_PHASE_STRIP = NO; 370 | CURRENT_PROJECT_VERSION = 1; 371 | DEBUG_INFORMATION_FORMAT = dwarf; 372 | ENABLE_STRICT_OBJC_MSGSEND = YES; 373 | ENABLE_TESTABILITY = YES; 374 | GCC_C_LANGUAGE_STANDARD = gnu99; 375 | GCC_NO_COMMON_BLOCKS = YES; 376 | GCC_OPTIMIZATION_LEVEL = 0; 377 | GCC_PREPROCESSOR_DEFINITIONS = ( 378 | "DEBUG=1", 379 | "$(inherited)", 380 | ); 381 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 382 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 383 | GCC_WARN_UNDECLARED_SELECTOR = YES; 384 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 385 | GCC_WARN_UNUSED_FUNCTION = YES; 386 | GCC_WARN_UNUSED_VARIABLE = YES; 387 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 388 | MTL_ENABLE_DEBUG_INFO = YES; 389 | ONLY_ACTIVE_ARCH = YES; 390 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 391 | VERSIONING_SYSTEM = "apple-generic"; 392 | VERSION_INFO_PREFIX = ""; 393 | }; 394 | name = Debug; 395 | }; 396 | 29673D121B4C381300EC2043 /* Release */ = { 397 | isa = XCBuildConfiguration; 398 | baseConfigurationReference = 2932A0FB1B52ABE800A71171 /* UniversalFramework_Base.xcconfig */; 399 | buildSettings = { 400 | ALWAYS_SEARCH_USER_PATHS = NO; 401 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 402 | CLANG_CXX_LIBRARY = "libc++"; 403 | CLANG_ENABLE_MODULES = YES; 404 | CLANG_ENABLE_OBJC_ARC = YES; 405 | CLANG_WARN_BOOL_CONVERSION = YES; 406 | CLANG_WARN_CONSTANT_CONVERSION = YES; 407 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 408 | CLANG_WARN_EMPTY_BODY = YES; 409 | CLANG_WARN_ENUM_CONVERSION = YES; 410 | CLANG_WARN_INT_CONVERSION = YES; 411 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 412 | CLANG_WARN_UNREACHABLE_CODE = YES; 413 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 414 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 415 | COPY_PHASE_STRIP = NO; 416 | CURRENT_PROJECT_VERSION = 1; 417 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 418 | ENABLE_NS_ASSERTIONS = NO; 419 | ENABLE_STRICT_OBJC_MSGSEND = YES; 420 | GCC_C_LANGUAGE_STANDARD = gnu99; 421 | GCC_NO_COMMON_BLOCKS = YES; 422 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 423 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 424 | GCC_WARN_UNDECLARED_SELECTOR = YES; 425 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 426 | GCC_WARN_UNUSED_FUNCTION = YES; 427 | GCC_WARN_UNUSED_VARIABLE = YES; 428 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 429 | MTL_ENABLE_DEBUG_INFO = NO; 430 | VALIDATE_PRODUCT = YES; 431 | VERSIONING_SYSTEM = "apple-generic"; 432 | VERSION_INFO_PREFIX = ""; 433 | }; 434 | name = Release; 435 | }; 436 | 29673D141B4C381300EC2043 /* Debug */ = { 437 | isa = XCBuildConfiguration; 438 | baseConfigurationReference = 2932A0FC1B52ABE800A71171 /* UniversalFramework_Framework.xcconfig */; 439 | buildSettings = { 440 | CLANG_ENABLE_MODULES = YES; 441 | CURRENT_PROJECT_VERSION = 0.2.0; 442 | DEFINES_MODULE = YES; 443 | DYLIB_COMPATIBILITY_VERSION = 1; 444 | DYLIB_CURRENT_VERSION = "$(CURRENT_PROJECT_VERSION)"; 445 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 446 | FRAMEWORK_SEARCH_PATHS = ( 447 | "$(PLATFORM_DIR)/Developer/Library/Frameworks", 448 | "$(inherited)", 449 | ); 450 | INFOPLIST_FILE = src/Info.plist; 451 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 452 | PRODUCT_BUNDLE_IDENTIFIER = de.mariusrackwitz.CatchingFire; 453 | PRODUCT_NAME = "$(TARGET_NAME)"; 454 | SKIP_INSTALL = YES; 455 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 456 | }; 457 | name = Debug; 458 | }; 459 | 29673D151B4C381300EC2043 /* Release */ = { 460 | isa = XCBuildConfiguration; 461 | baseConfigurationReference = 2932A0FC1B52ABE800A71171 /* UniversalFramework_Framework.xcconfig */; 462 | buildSettings = { 463 | CLANG_ENABLE_MODULES = YES; 464 | CURRENT_PROJECT_VERSION = 0.2.0; 465 | DEFINES_MODULE = YES; 466 | DYLIB_COMPATIBILITY_VERSION = 1; 467 | DYLIB_CURRENT_VERSION = "$(CURRENT_PROJECT_VERSION)"; 468 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 469 | FRAMEWORK_SEARCH_PATHS = ( 470 | "$(PLATFORM_DIR)/Developer/Library/Frameworks", 471 | "$(inherited)", 472 | ); 473 | INFOPLIST_FILE = src/Info.plist; 474 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 475 | PRODUCT_BUNDLE_IDENTIFIER = de.mariusrackwitz.CatchingFire; 476 | PRODUCT_NAME = "$(TARGET_NAME)"; 477 | SKIP_INSTALL = YES; 478 | }; 479 | name = Release; 480 | }; 481 | 29673D171B4C381300EC2043 /* Debug */ = { 482 | isa = XCBuildConfiguration; 483 | baseConfigurationReference = 2932A0FD1B52ABE800A71171 /* UniversalFramework_Test.xcconfig */; 484 | buildSettings = { 485 | INFOPLIST_FILE = test/Info.plist; 486 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 487 | PRODUCT_BUNDLE_IDENTIFIER = de.mariusrackwitz.CatchingFireTests; 488 | PRODUCT_NAME = "$(TARGET_NAME)"; 489 | }; 490 | name = Debug; 491 | }; 492 | 29673D181B4C381300EC2043 /* Release */ = { 493 | isa = XCBuildConfiguration; 494 | baseConfigurationReference = 2932A0FD1B52ABE800A71171 /* UniversalFramework_Test.xcconfig */; 495 | buildSettings = { 496 | INFOPLIST_FILE = test/Info.plist; 497 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 498 | PRODUCT_BUNDLE_IDENTIFIER = de.mariusrackwitz.CatchingFireTests; 499 | PRODUCT_NAME = "$(TARGET_NAME)"; 500 | }; 501 | name = Release; 502 | }; 503 | /* End XCBuildConfiguration section */ 504 | 505 | /* Begin XCConfigurationList section */ 506 | 2932A1021B52B45700A71171 /* Build configuration list for PBXAggregateTarget "CatchingFire iOS" */ = { 507 | isa = XCConfigurationList; 508 | buildConfigurations = ( 509 | 2932A1001B52B45700A71171 /* Debug */, 510 | 2932A1011B52B45700A71171 /* Release */, 511 | ); 512 | defaultConfigurationIsVisible = 0; 513 | defaultConfigurationName = Release; 514 | }; 515 | 2932A1081B52B6AE00A71171 /* Build configuration list for PBXAggregateTarget "CatchingFire OS X" */ = { 516 | isa = XCConfigurationList; 517 | buildConfigurations = ( 518 | 2932A1091B52B6AE00A71171 /* Debug */, 519 | 2932A10A1B52B6AE00A71171 /* Release */, 520 | ); 521 | defaultConfigurationIsVisible = 0; 522 | defaultConfigurationName = Release; 523 | }; 524 | 29673CF91B4C381300EC2043 /* Build configuration list for PBXProject "CatchingFire" */ = { 525 | isa = XCConfigurationList; 526 | buildConfigurations = ( 527 | 29673D111B4C381300EC2043 /* Debug */, 528 | 29673D121B4C381300EC2043 /* Release */, 529 | ); 530 | defaultConfigurationIsVisible = 0; 531 | defaultConfigurationName = Release; 532 | }; 533 | 29673D131B4C381300EC2043 /* Build configuration list for PBXNativeTarget "CatchingFire" */ = { 534 | isa = XCConfigurationList; 535 | buildConfigurations = ( 536 | 29673D141B4C381300EC2043 /* Debug */, 537 | 29673D151B4C381300EC2043 /* Release */, 538 | ); 539 | defaultConfigurationIsVisible = 0; 540 | defaultConfigurationName = Release; 541 | }; 542 | 29673D161B4C381300EC2043 /* Build configuration list for PBXNativeTarget "CatchingFireTests" */ = { 543 | isa = XCConfigurationList; 544 | buildConfigurations = ( 545 | 29673D171B4C381300EC2043 /* Debug */, 546 | 29673D181B4C381300EC2043 /* Release */, 547 | ); 548 | defaultConfigurationIsVisible = 0; 549 | defaultConfigurationName = Release; 550 | }; 551 | /* End XCConfigurationList section */ 552 | }; 553 | rootObject = 29673CF61B4C381300EC2043 /* Project object */; 554 | } 555 | -------------------------------------------------------------------------------- /CatchingFire.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CatchingFire.xcodeproj/project.xcworkspace/xcshareddata/CatchingFire.xcscmblueprint: -------------------------------------------------------------------------------- 1 | { 2 | "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "8206996771CC8CDEEF1F2D189BD099CD6BAF811A", 3 | "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : { 4 | 5 | }, 6 | "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : { 7 | "8206996771CC8CDEEF1F2D189BD099CD6BAF811A" : 0, 8 | "2DDF1D4E528EDA8D8E5AF503BA5680A30604BD70" : 0 9 | }, 10 | "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "D27A5EEC-BEDC-4806-9D91-D0C8A67FC9CE", 11 | "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : { 12 | "8206996771CC8CDEEF1F2D189BD099CD6BAF811A" : "CatchingFire\/", 13 | "2DDF1D4E528EDA8D8E5AF503BA5680A30604BD70" : "CatchingFire\/xcconfigs\/" 14 | }, 15 | "DVTSourceControlWorkspaceBlueprintNameKey" : "CatchingFire", 16 | "DVTSourceControlWorkspaceBlueprintVersion" : 203, 17 | "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "CatchingFire.xcodeproj", 18 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [ 19 | { 20 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "github.com:mrackwitz\/xcconfigs.git", 21 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", 22 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "2DDF1D4E528EDA8D8E5AF503BA5680A30604BD70" 23 | }, 24 | { 25 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "github.com:mrackwitz\/CatchingFire.git", 26 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", 27 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "8206996771CC8CDEEF1F2D189BD099CD6BAF811A" 28 | } 29 | ] 30 | } -------------------------------------------------------------------------------- /CatchingFire.xcodeproj/xcshareddata/xcschemes/CatchingFire OS X.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /CatchingFire.xcodeproj/xcshareddata/xcschemes/CatchingFire iOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /CatchingFire.xcodeproj/xcshareddata/xcschemes/CatchingFire.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 65 | 71 | 72 | 73 | 74 | 75 | 76 | 82 | 83 | 89 | 90 | 91 | 92 | 94 | 95 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Marius Rackwitz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CatchingFire 2 | 3 | [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://github.com/mrackwitz/CatchingFire/blob/master/LICENSE) 4 | [![CocoaPods](https://img.shields.io/cocoapods/v/CatchingFire.svg?style=flat)](https://github.com/mrackwitz/CatchingFire) 5 | 6 | CatchingFire is a Swift test framework, which helps making expectations against the error handling of your code. It provides for this purpose two higher-order functions, which take throwing functions and check whether the given closure throws or not. It integrates seamlessly with the expecters provided by `XCTest`. 7 | 8 | ## Usage 9 | 10 | ### AssertNoThrow 11 | 12 | `AssertNoThrow` allows you to write safe tests for the happy path of failable functions. 13 | It helps you to avoid the `try!` operator in tests. 14 | 15 | If you want to test a function, which may fail in general, you may think of using `try`. 16 | But this would mean that you have to declare your test method as throwing, which causes that 17 | XCTest doesn't execute the test anymore. 18 | 19 | So in consequence, you would usually need to write: 20 | 21 | ```swift 22 | XCTAssertEqual(try! fib(x), 21) 23 | ``` 24 | 25 | If the expression fails, your whole test suite doesn't execute further and aborts immediately, 26 | which is very undesirable, especially on CI, but also for your workflow when you use TDD. 27 | 28 | Instead you can write now: 29 | 30 | ```swift 31 | AssertNoThrow { 32 | XCTAssertEqual(try fib(x), 21) 33 | } 34 | ``` 35 | 36 | Or alternatively: 37 | 38 | ```swift 39 | AssertNoThrow(try fib(x)).map { (y: Int) in 40 | XCTAssertEqual(y, 21) 41 | } 42 | ``` 43 | 44 | If the expression fails, your test fails. 45 | 46 | ### AssertThrow 47 | 48 | `AssertThrow` allows to easily write exhaustive tests for the exception paths of failable functions. 49 | It helps you to avoid writing the same boilerplate code over and over again for tests. 50 | 51 | If you want to test a function, that it fails for given arguments, you would usually need 52 | to write: 53 | 54 | ```swift 55 | do { 56 | try fib(-1) 57 | XCTFail("Expected to fail, but did not failed!") 58 | } catch Error.ArgumentMayNotBeNegative { 59 | // succeed silently 60 | } catch error { 61 | XCTFail("Failed with a different error than expected!") 62 | } 63 | ``` 64 | 65 | Instead you can write now: 66 | 67 | ```swift 68 | AssertThrow(Error.ArgumentMayNotBeNegative) { 69 | try fib(-1) 70 | } 71 | ``` 72 | 73 | If the expression or closure doesn't throw the expected error, your test fails. 74 | 75 | 76 | ## Installation 77 | 78 | CatchingFire is available through [CocoaPods](http://cocoapods.org). To install 79 | it, simply add it to your test target in your Podfile: 80 | 81 | ```ruby 82 | use_frameworks! 83 | target "AppTest" do 84 | pod 'CatchingFire' 85 | end 86 | ``` 87 | 88 | 89 | ## Author 90 | 91 | Marius Rackwitz, git@mariusrackwitz.de 92 | Find me on Twitter as [@mrackwitz](https://twitter.com/mrackwitz). 93 | 94 | 95 | ## License 96 | 97 | Version is available under the MIT license. See the LICENSE file for more info. 98 | -------------------------------------------------------------------------------- /src/CatchingFire.h: -------------------------------------------------------------------------------- 1 | // 2 | // CatchingFire.h 3 | // CatchingFire 4 | // 5 | // Created by Marius Rackwitz on 7.7.15. 6 | // Copyright © 2015 Marius Rackwitz. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | 11 | //! Project version number for CatchingFire. 12 | FOUNDATION_EXPORT double CatchingFireVersionNumber; 13 | 14 | //! Project version string for CatchingFire. 15 | FOUNDATION_EXPORT const unsigned char CatchingFireVersionString[]; 16 | -------------------------------------------------------------------------------- /src/CatchingFire.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CatchingFire.swift 3 | // CatchingFire 4 | // 5 | // Created by Marius Rackwitz on 7.7.15. 6 | // Copyright © 2015 Marius Rackwitz. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | 12 | /// This allows you to write safe tests for the happy path of failable functions. 13 | /// It helps you to avoid the `try!` operator in tests. 14 | /// 15 | /// If you want to test a function, which may fail in general, you may think of using `try`. 16 | /// But this would mean that you have to declare your test method as throwing, which causes that 17 | /// XCTest doesn't execute the test anymore. 18 | /// 19 | /// So in consequence, you would usually need to write: 20 | /// 21 | /// XCTAssertEqual(try! fib(x), 21) 22 | /// 23 | /// If the expression fails, your whole test suite doesn't execute further and aborts immediately, 24 | /// which is very undesirable, especially on CI, but also for your workflow when you use TDD. 25 | /// 26 | /// Instead you can write now: 27 | /// 28 | /// AssertNoThrow { 29 | /// XCTAssertEqual(try fib(x), 21) 30 | /// } 31 | /// 32 | /// Or alternatively: 33 | /// 34 | /// AssertNoThrow(try fib(x)).map { (y: Int) in 35 | /// XCTAssertEqual(y, 21) 36 | /// } 37 | /// 38 | /// If the expression fails, your test fails. 39 | /// 40 | public func AssertNoThrow(@autoclosure closure: () throws -> R) -> R? { 41 | var result: R? 42 | AssertNoThrow() { 43 | result = try closure() 44 | } 45 | return result 46 | } 47 | 48 | public func AssertNoThrow(@noescape closure: () throws -> ()) { 49 | do { 50 | try closure() 51 | } catch let error { 52 | XCTFail("Caught unexpected error <\(error)>.") 53 | } 54 | } 55 | 56 | 57 | /// This allows to easily write exhaustive tests for the exception paths of failable functions. 58 | /// It helps you to avoid writing the same boilerplate code over and over again for tests. 59 | /// 60 | /// If you want to test a function, that it fails for given arguments, you would usually need 61 | /// to write: 62 | /// 63 | /// do { 64 | /// try fib(-1) 65 | /// XCTFail("Expected to fail, but did not failed!") 66 | /// } catch Error.ArgumentMayNotBeNegative { 67 | /// // succeed silently 68 | /// } catch error { 69 | /// XCTFail("Failed with a different error than expected!") 70 | /// } 71 | /// 72 | /// Instead you can write now: 73 | /// 74 | /// AssertThrows(Error.ArgumentMayNotBeNegative) { 75 | /// try fib(-1) 76 | /// } 77 | /// 78 | /// If the expression or closure doesn't throw the expected error, your test fails. 79 | /// 80 | public func AssertThrows(expectedError: E, @autoclosure _ closure: () throws -> R) -> () { 81 | AssertThrows(expectedError) { try closure() } 82 | } 83 | 84 | public func AssertThrows(expectedError: E, @noescape _ closure: () throws -> ()) -> () { 85 | do { 86 | try closure() 87 | XCTFail("Expected to catch <\(expectedError)>, " 88 | + "but no error was thrown.") 89 | } catch expectedError { 90 | return // that's what we expected 91 | } catch { 92 | XCTFail("Caught error <\(error)>, " 93 | + "but not of the expected type and value " 94 | + "<\(expectedError)>.") 95 | } 96 | } 97 | 98 | public func AssertThrows(expectedError: E, @autoclosure _ closure: () throws -> R) -> () { 99 | AssertThrows(expectedError) { try closure() } 100 | } 101 | 102 | public func AssertThrows(expectedError: E, @noescape _ closure: () throws -> ()) -> () { 103 | do { 104 | try closure() 105 | XCTFail("Expected to catch <\(expectedError)>, " 106 | + "but no error was thrown.") 107 | } catch let error as E { 108 | XCTAssertEqual(error, expectedError, 109 | "Caught error <\(error)> is of the expected type <\(E.self)>, " 110 | + "but not the expected case <\(expectedError)>.") 111 | } catch { 112 | XCTFail("Caught error <\(error)>, " 113 | + "but not of the expected type and value " 114 | + "<\(expectedError)>.") 115 | } 116 | } 117 | 118 | /// Implement pattern matching for ErrorTypes 119 | internal func ~=(lhs: ErrorType, rhs: ErrorType) -> Bool { 120 | return lhs._domain == rhs._domain 121 | && rhs._code == rhs._code 122 | } 123 | 124 | /// Helper struct to catch errors thrown by others, which aren't publicly exposed. 125 | /// 126 | /// Note: 127 | /// Don't use this when a given ErrorType implementation exists. 128 | /// If you want to use that to test errors thrown in your own framework, you should 129 | /// consider to adopt an enumeration-based approach first in the framework code itself and expose 130 | /// them instead as part of the public API. Even if you have some internal error cases, you can 131 | //// put them in a separate enum and import your framework as `@testable` in your tests without 132 | /// affecting the public API, if that matters. 133 | /// 134 | public struct Error : ErrorType { 135 | public let domain: String 136 | public let code: Int 137 | 138 | public var _domain: String { 139 | return domain 140 | } 141 | public var _code: Int { 142 | return code 143 | } 144 | } 145 | 146 | /// Extend our Error type to conform `Equatable`. 147 | extension Error : Equatable {} 148 | 149 | /// Implement the `==` operator as required by protocol `Equatable`. 150 | public func ==(lhs: Error, rhs: Error) -> Bool { 151 | return lhs._domain == rhs._domain 152 | && lhs._code == rhs._code 153 | } 154 | 155 | /// Implement pattern matching for Error & ErrorType 156 | public func ~=(lhs: Error, rhs: ErrorType) -> Bool { 157 | return lhs._domain == rhs._domain 158 | && rhs._code == rhs._code 159 | } 160 | -------------------------------------------------------------------------------- /src/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | $(CURRENT_PROJECT_VERSION) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /test/CatchingFireTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CatchingFireTests.swift 3 | // CatchingFireTests 4 | // 5 | // Created by Marius Rackwitz on 7.7.15. 6 | // Copyright © 2015 Marius Rackwitz. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import CatchingFire 11 | 12 | enum Error : ErrorType { 13 | case MayNotBeZero 14 | } 15 | 16 | func failsWithZero(x: Int) throws -> () { 17 | guard x != 0 else { 18 | throw Error.MayNotBeZero 19 | } 20 | } 21 | 22 | func idButFailsWithZero(x: Int) throws -> Int { 23 | guard x != 0 else { 24 | throw Error.MayNotBeZero 25 | } 26 | return x 27 | } 28 | 29 | class CatchingFireTests: XCTestCase { 30 | 31 | func testVoidDoNotThrow() { 32 | AssertNoThrow(try failsWithZero(1)) 33 | AssertNoThrow { 34 | try failsWithZero(1) 35 | } 36 | } 37 | 38 | func testVoidThrow() { 39 | AssertThrows(Error.MayNotBeZero, try failsWithZero(0)) 40 | AssertThrows(Error.MayNotBeZero) { 41 | try failsWithZero(0) 42 | } 43 | } 44 | 45 | func testNonVoidDoNotThrow() { 46 | AssertNoThrow(try idButFailsWithZero(1)) 47 | AssertNoThrow { 48 | let x = try idButFailsWithZero(1) 49 | XCTAssertEqual(x, 1) 50 | } 51 | AssertNoThrow(try idButFailsWithZero(1)).map { (x: Int) in 52 | XCTAssertEqual(x, 1) 53 | } 54 | } 55 | 56 | func testNonVoidThrow() { 57 | AssertThrows(Error.MayNotBeZero, try idButFailsWithZero(0)) 58 | AssertThrows(Error.MayNotBeZero) { 59 | try idButFailsWithZero(0) 60 | } 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /test/ExampleTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ExampleTests.swift 3 | // CatchingFire 4 | // 5 | // Created by Marius Rackwitz on 9.7.15. 6 | // Copyright © 2015 Marius Rackwitz. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import CatchingFire 11 | 12 | 13 | enum BombError: ErrorType { 14 | case WrongWire 15 | case TimeElapsed 16 | } 17 | let 🔥 = BombError.TimeElapsed 18 | 19 | let 🕚 = 11 20 | let 🕛 = 12 21 | 22 | class Trigger { 23 | var alarmTime: Int 24 | private var enabled: Bool = true 25 | 26 | init(alarmTime: Int) { 27 | self.alarmTime = alarmTime 28 | } 29 | 30 | func cutRedWire() throws { 31 | throw BombError.WrongWire 32 | } 33 | 34 | func cutBlueWire() throws { 35 | self.enabled = false 36 | } 37 | 38 | func enable() { 39 | self.enabled = true 40 | } 41 | } 42 | 43 | func 💣(time: Int) throws -> Trigger { 44 | struct Internals { 45 | static var trigger = Trigger(alarmTime: 🕛) 46 | } 47 | let trigger = Internals.trigger 48 | if trigger.enabled && time >= trigger.alarmTime { 49 | throw 🔥 50 | } 51 | return trigger 52 | } 53 | 54 | 55 | class ExampleTests : XCTestCase { 56 | 57 | override func setUp() { 58 | let trigger = try! 💣(🕚) 59 | trigger.enable() 60 | } 61 | 62 | func testDisarm() { 63 | AssertNoThrow { 64 | let trigger = try 💣(🕚) 65 | try trigger.cutBlueWire() 66 | } 67 | AssertNoThrow(try 💣(🕛)) 68 | } 69 | 70 | func testDoNotDisarm() { 71 | AssertNoThrow(try 💣(🕚)) 72 | AssertThrows(🔥, try 💣(🕛)) 73 | } 74 | 75 | func testFailToDisarm() { 76 | AssertThrows(BombError.WrongWire) { 77 | let trigger = try 💣(🕚) 78 | try trigger.cutRedWire() 79 | } 80 | } 81 | 82 | func testIsArmedInitially() { 83 | XCTAssertTrue(AssertNoThrow(try 💣(🕚))?.enabled == true) 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /test/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | --------------------------------------------------------------------------------