├── .gitignore ├── README.md ├── Supporting Files └── Info.plist ├── XCTestPlayground.swift ├── XCTestPlayground.xcodeproj ├── project.pbxproj └── xcshareddata │ └── xcschemes │ └── XCTestPlayground.xcscheme ├── XCTestPlayground.xcworkspace └── contents.xcworkspacedata ├── XCTestPlaygroundExample.playground ├── Contents.swift └── contents.xcplayground └── screenshot.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xcuserstate 23 | 24 | ## Obj-C/Swift specific 25 | *.hmap 26 | *.ipa 27 | *.dSYM.zip 28 | *.dSYM 29 | 30 | ## Playgrounds 31 | timeline.xctimeline 32 | playground.xcworkspace 33 | 34 | # Swift Package Manager 35 | # 36 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 37 | # Packages/ 38 | .build/ 39 | 40 | # CocoaPods 41 | # 42 | # We recommend against adding the Pods directory to your .gitignore. However 43 | # you should judge for yourself, the pros and cons are mentioned at: 44 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 45 | # 46 | # Pods/ 47 | 48 | # Carthage 49 | # 50 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 51 | # Carthage/Checkouts 52 | 53 | Carthage/Build 54 | 55 | # fastlane 56 | # 57 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 58 | # screenshots whenever they are needed. 59 | # For more information about the recommended setup visit: 60 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 61 | 62 | fastlane/report.xml 63 | fastlane/Preview.html 64 | fastlane/screenshots 65 | fastlane/test_output -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # XCTestPlayground 2 | 3 | This repository contains a simple implementation of most `XCTAssert` macros to use in a Playground. 4 | 5 | With the Playground feature that display the result of an executed line, it will show the assert result like this: 6 | ![screenshot](screenshot.png) 7 | 8 | I use this to do TDD directly inside a Playground and then move the code as-is inside my test files. 9 | 10 | It contains a `XCTestCase` base class that, when instantiated, will run all methods with names beginning with "test", to mimic XCTestCase behaviour and make moving the code to your Xcode project easier. 11 | 12 | ## How to install it in an existing playground 13 | 14 | Simply add the `XCTestPlayground.swift` file to your Playground `Sources` folder. 15 | 16 | ## Using it directly 17 | 18 | The repo contains a fully configured Xcode workspace containing a playground importing `XCTestPlayground`. 19 | All you have to do is: 20 | 21 | 1. clone the repo 22 | 2. build the framework on a 64-bit target (e.g. iPhone 5s simulator) 23 | 3. go and play in the `XCTestPlaygroundExample` playground! 🎉 24 | 25 | ## Swift version 26 | 27 | Xcode 9 has been released and since the playgrounds in this version uses swift 4 tools intended to be used inside them should use this version. 28 | Nevertheless, if you want to use `XCTestPlayground` with previous versions of Xcode, you can still checkout the last commit using the Swift 2.2 version: af05981c214a3a5ac1fa7b298787d517100db868 29 | -------------------------------------------------------------------------------- /Supporting Files/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 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /XCTestPlayground.swift: -------------------------------------------------------------------------------- 1 | // Playground Tests 2 | 3 | import Foundation 4 | 5 | public let defaultMessage = "" 6 | 7 | /// Emits a test failure if the general `Boolean` expression passed 8 | /// to it evaluates to `false`. 9 | /// 10 | /// - Requires: This and all other XCTAssert* functions must be called from 11 | /// within a test method, as passed to `XCTMain`. 12 | /// Assertion failures that occur outside of a test method will *not* be 13 | /// reported as failures. 14 | /// 15 | /// - Parameter expression: A boolean test. If it evaluates to `false`, the 16 | /// assertion fails and emits a test failure. 17 | /// - Parameter message: An optional message to use in the failure if the 18 | /// assertion fails. If no message is supplied a default message is used. 19 | /// 20 | /// For example 21 | /// 22 | /// ```swift 23 | /// class TestCase: XCTestCase { 24 | /// func testAssertions() { 25 | /// XCTAssertEqual(1, 2) 26 | /// XCTAssertEqual([1, 2], [2, 3]) 27 | /// XCTAssertGreaterThanOrEqual(1, 2) 28 | /// XCTAssertTrue(true) 29 | /// } 30 | /// } 31 | /// ``` 32 | /// 33 | public func XCTAssert( 34 | _ expression: @autoclosure () -> Bool, 35 | _ message: String = defaultMessage 36 | ) -> String { 37 | return returnTestResult(expression(), message: message) 38 | } 39 | 40 | public func XCTAssertEqual( 41 | _ expression1: @autoclosure () -> T?, 42 | _ expression2: @autoclosure () -> T?, 43 | _ message: String = defaultMessage 44 | ) -> String { 45 | return returnTestResult( 46 | expression1() == expression2(), 47 | message: "\(message) - expected: \(expression2() as Optional), actual: \(expression1() as Optional)") 48 | } 49 | 50 | public func XCTAssertEqual( 51 | _ expression1: @autoclosure () -> ArraySlice, 52 | _ expression2: @autoclosure () -> ArraySlice, 53 | _ message: String = defaultMessage 54 | ) -> String { 55 | return returnTestResult( 56 | expression1() == expression2(), 57 | message: "\(message) - expected: \(expression2()), actual: \(expression1())") 58 | } 59 | 60 | public func XCTAssertEqual( 61 | _ expression1: @autoclosure () -> ContiguousArray, 62 | _ expression2: @autoclosure () -> ContiguousArray, 63 | _ message: String = defaultMessage 64 | ) -> String { 65 | return returnTestResult( 66 | expression1() == expression2(), 67 | message: "\(message) - expected: \(expression2()), actual: \(expression1())") 68 | } 69 | 70 | public func XCTAssertEqual( 71 | _ expression1: @autoclosure () -> [T], 72 | _ expression2: @autoclosure () -> [T], 73 | _ message: String = defaultMessage 74 | ) -> String { 75 | return returnTestResult( 76 | expression1() == expression2(), 77 | message: "\(message) - expected: \(expression2()), actual: \(expression1())") 78 | } 79 | 80 | public func XCTAssertEqual( 81 | _ expression1: @autoclosure () -> [T : U], 82 | _ expression2: @autoclosure () -> [T : U], 83 | _ message: String = defaultMessage 84 | ) -> String { 85 | return returnTestResult( 86 | expression1() == expression2(), 87 | message: "\(message) - expected: \(expression2()), actual: \(expression1())") 88 | } 89 | 90 | public func XCTAssertFalse( 91 | _ expression: @autoclosure () -> Bool, 92 | _ message: String = defaultMessage 93 | ) -> String { 94 | return returnTestResult(!expression(), message: message) 95 | } 96 | 97 | public func XCTAssertGreaterThan( 98 | _ expression1: @autoclosure () -> T, 99 | _ expression2: @autoclosure () -> T, 100 | _ message: String = defaultMessage 101 | ) -> String { 102 | return returnTestResult( 103 | expression1() > expression2(), 104 | message: "\(message) - actual: \(expression1()) > \(expression2())") 105 | } 106 | 107 | public func XCTAssertGreaterThanOrEqual( 108 | _ expression1: @autoclosure () -> T, 109 | _ expression2: @autoclosure () -> T, 110 | _ message: String = defaultMessage 111 | ) -> String { 112 | return returnTestResult( 113 | expression1() >= expression2(), 114 | message: "\(message) - actual: \(expression1()) >= \(expression2())") 115 | } 116 | 117 | public func XCTAssertLessThan( 118 | _ expression1: @autoclosure () -> T, 119 | _ expression2: @autoclosure () -> T, 120 | _ message: String = defaultMessage 121 | ) -> String { 122 | return returnTestResult( 123 | expression1() < expression2(), 124 | message: "\(message) - actual: \(expression1()) < \(expression2())") 125 | } 126 | 127 | public func XCTAssertLessThanOrEqual( 128 | _ expression1: @autoclosure () -> T, 129 | _ expression2: @autoclosure () -> T, 130 | _ message: String = defaultMessage 131 | ) -> String { 132 | return returnTestResult( 133 | expression1() <= expression2(), 134 | message: "\(message) - actual: \(expression1()) <= \(expression2())") 135 | } 136 | 137 | public func XCTAssertNil( 138 | _ expression: @autoclosure () -> Any?, 139 | _ message: String = "" 140 | ) -> String { 141 | var result = true 142 | if let _ = expression() { result = false } 143 | return returnTestResult( 144 | result, 145 | message: "\(message) - expected: nil, actual: \(expression() as Optional)") 146 | } 147 | 148 | public func XCTAssertNotEqual( 149 | _ expression1: @autoclosure () -> T?, 150 | _ expression2: @autoclosure () -> T?, 151 | _ message: String = defaultMessage 152 | ) -> String { 153 | return returnTestResult( 154 | expression1() != expression2(), 155 | message: "\(message) - expected: \(expression1() as Optional) =! \(expression2() as Optional)") 156 | } 157 | 158 | public func XCTAssertNotEqual( 159 | _ expression1: @autoclosure () -> ContiguousArray, 160 | _ expression2: @autoclosure () -> ContiguousArray, 161 | _ message: String = defaultMessage 162 | ) -> String { 163 | return returnTestResult( 164 | expression1() != expression2(), 165 | message: "\(message) - expected: \(expression1()) != \(expression2())") 166 | } 167 | 168 | public func XCTAssertNotEqual( 169 | _ expression1: @autoclosure () -> ArraySlice, 170 | _ expression2: @autoclosure () -> ArraySlice, 171 | _ message: String = defaultMessage 172 | ) -> String { 173 | return returnTestResult( 174 | expression1() != expression2(), 175 | message: "\(message) - expected: \(expression1()) != \(expression2())") 176 | } 177 | 178 | public func XCTAssertNotEqual( 179 | _ expression1: @autoclosure () -> [T], 180 | _ expression2: @autoclosure () -> [T], 181 | _ message: String = defaultMessage 182 | ) -> String { 183 | return returnTestResult( 184 | expression1() != expression2(), 185 | message: "\(message) - expected: \(expression1()) != \(expression2())") 186 | } 187 | 188 | public func XCTAssertNotEqual( 189 | _ expression1: @autoclosure () -> [T : U], 190 | _ expression2: @autoclosure () -> [T : U], 191 | _ message: String = defaultMessage 192 | ) -> String { 193 | return returnTestResult( 194 | expression1() != expression2(), 195 | message: "\(message) - expected: \(expression1()) != \(expression2())") 196 | } 197 | 198 | public func XCTAssertNotNil( 199 | _ expression: @autoclosure () -> Any?, 200 | _ message: String = "" 201 | ) -> String { 202 | var result = false 203 | if let _ = expression() { result = true } 204 | return returnTestResult(result, message: message) 205 | } 206 | 207 | public func XCTAssertTrue( 208 | _ expression: @autoclosure () -> Bool, 209 | _ message: String = defaultMessage 210 | ) -> String { 211 | return returnTestResult(expression(), message: message) 212 | } 213 | 214 | public func XCTFail(_ message: String = "") -> String { 215 | return failMessage(message) 216 | } 217 | 218 | func returnTestResult(_ result: Bool, message: String) -> String { 219 | return result ? okMessage() : failMessage(message) 220 | } 221 | 222 | func okMessage() -> String { return "✅" } 223 | 224 | func failMessage(_ message: String) -> String { return "❌" + message } 225 | 226 | // This class was based on GitHub gist: 227 | // https://gist.github.com/croath/a9358dac0530d91e9e2b 228 | 229 | open class XCTestCase: NSObject { 230 | 231 | public override init(){ 232 | super.init() 233 | self.runTestMethods() 234 | } 235 | 236 | open class func setUp() {} 237 | open func setUp() {} 238 | 239 | open class func tearDown() {} 240 | open func tearDown() {} 241 | 242 | override open var description: String { return "" } 243 | 244 | private func runTestMethods() { 245 | type(of:self).setUp() 246 | defer { 247 | type(of:self).tearDown() 248 | } 249 | var mc: CUnsignedInt = 0 250 | 251 | guard var mlist = class_copyMethodList(type(of:self).classForCoder(), &mc) else { 252 | return 253 | } 254 | (0 ..< mc).forEach { _ in 255 | let m = method_getName(mlist.pointee) 256 | if String(describing: m).hasPrefix("test") { 257 | self.setUp() 258 | self.performSelector( 259 | onMainThread: m, 260 | with: nil, 261 | waitUntilDone: true) 262 | self.tearDown() 263 | } 264 | mlist = mlist.successor() 265 | } 266 | } 267 | } 268 | -------------------------------------------------------------------------------- /XCTestPlayground.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | FE3CAD201CEE59DE0058C6B4 /* XCTestPlayground.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE3CAD1F1CEE59DE0058C6B4 /* XCTestPlayground.swift */; }; 11 | /* End PBXBuildFile section */ 12 | 13 | /* Begin PBXFileReference section */ 14 | FE3CAD141CEE59530058C6B4 /* XCTestPlayground.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = XCTestPlayground.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 15 | FE3CAD191CEE59530058C6B4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = "../Supporting Files/Info.plist"; sourceTree = ""; }; 16 | FE3CAD1F1CEE59DE0058C6B4 /* XCTestPlayground.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XCTestPlayground.swift; sourceTree = ""; }; 17 | /* End PBXFileReference section */ 18 | 19 | /* Begin PBXFrameworksBuildPhase section */ 20 | FE3CAD101CEE59530058C6B4 /* Frameworks */ = { 21 | isa = PBXFrameworksBuildPhase; 22 | buildActionMask = 2147483647; 23 | files = ( 24 | ); 25 | runOnlyForDeploymentPostprocessing = 0; 26 | }; 27 | /* End PBXFrameworksBuildPhase section */ 28 | 29 | /* Begin PBXGroup section */ 30 | FE3CAD0A1CEE59530058C6B4 = { 31 | isa = PBXGroup; 32 | children = ( 33 | FE3CAD1F1CEE59DE0058C6B4 /* XCTestPlayground.swift */, 34 | FE3CAD161CEE59530058C6B4 /* Supporting FIles */, 35 | FE3CAD151CEE59530058C6B4 /* Products */, 36 | ); 37 | sourceTree = ""; 38 | }; 39 | FE3CAD151CEE59530058C6B4 /* Products */ = { 40 | isa = PBXGroup; 41 | children = ( 42 | FE3CAD141CEE59530058C6B4 /* XCTestPlayground.framework */, 43 | ); 44 | name = Products; 45 | sourceTree = ""; 46 | }; 47 | FE3CAD161CEE59530058C6B4 /* Supporting FIles */ = { 48 | isa = PBXGroup; 49 | children = ( 50 | FE3CAD191CEE59530058C6B4 /* Info.plist */, 51 | ); 52 | name = "Supporting FIles"; 53 | path = "Supporting Files"; 54 | sourceTree = ""; 55 | }; 56 | /* End PBXGroup section */ 57 | 58 | /* Begin PBXHeadersBuildPhase section */ 59 | FE3CAD111CEE59530058C6B4 /* Headers */ = { 60 | isa = PBXHeadersBuildPhase; 61 | buildActionMask = 2147483647; 62 | files = ( 63 | ); 64 | runOnlyForDeploymentPostprocessing = 0; 65 | }; 66 | /* End PBXHeadersBuildPhase section */ 67 | 68 | /* Begin PBXNativeTarget section */ 69 | FE3CAD131CEE59530058C6B4 /* XCTestPlayground */ = { 70 | isa = PBXNativeTarget; 71 | buildConfigurationList = FE3CAD1C1CEE59530058C6B4 /* Build configuration list for PBXNativeTarget "XCTestPlayground" */; 72 | buildPhases = ( 73 | FE3CAD0F1CEE59530058C6B4 /* Sources */, 74 | FE3CAD101CEE59530058C6B4 /* Frameworks */, 75 | FE3CAD111CEE59530058C6B4 /* Headers */, 76 | FE3CAD121CEE59530058C6B4 /* Resources */, 77 | ); 78 | buildRules = ( 79 | ); 80 | dependencies = ( 81 | ); 82 | name = XCTestPlayground; 83 | productName = XCTestPlayground; 84 | productReference = FE3CAD141CEE59530058C6B4 /* XCTestPlayground.framework */; 85 | productType = "com.apple.product-type.framework"; 86 | }; 87 | /* End PBXNativeTarget section */ 88 | 89 | /* Begin PBXProject section */ 90 | FE3CAD0B1CEE59530058C6B4 /* Project object */ = { 91 | isa = PBXProject; 92 | attributes = { 93 | LastUpgradeCheck = 0910; 94 | ORGANIZATIONNAME = Liquidsoul; 95 | TargetAttributes = { 96 | FE3CAD131CEE59530058C6B4 = { 97 | CreatedOnToolsVersion = 7.3.1; 98 | LastSwiftMigration = 0900; 99 | }; 100 | }; 101 | }; 102 | buildConfigurationList = FE3CAD0E1CEE59530058C6B4 /* Build configuration list for PBXProject "XCTestPlayground" */; 103 | compatibilityVersion = "Xcode 3.2"; 104 | developmentRegion = English; 105 | hasScannedForEncodings = 0; 106 | knownRegions = ( 107 | en, 108 | ); 109 | mainGroup = FE3CAD0A1CEE59530058C6B4; 110 | productRefGroup = FE3CAD151CEE59530058C6B4 /* Products */; 111 | projectDirPath = ""; 112 | projectRoot = ""; 113 | targets = ( 114 | FE3CAD131CEE59530058C6B4 /* XCTestPlayground */, 115 | ); 116 | }; 117 | /* End PBXProject section */ 118 | 119 | /* Begin PBXResourcesBuildPhase section */ 120 | FE3CAD121CEE59530058C6B4 /* Resources */ = { 121 | isa = PBXResourcesBuildPhase; 122 | buildActionMask = 2147483647; 123 | files = ( 124 | ); 125 | runOnlyForDeploymentPostprocessing = 0; 126 | }; 127 | /* End PBXResourcesBuildPhase section */ 128 | 129 | /* Begin PBXSourcesBuildPhase section */ 130 | FE3CAD0F1CEE59530058C6B4 /* Sources */ = { 131 | isa = PBXSourcesBuildPhase; 132 | buildActionMask = 2147483647; 133 | files = ( 134 | FE3CAD201CEE59DE0058C6B4 /* XCTestPlayground.swift in Sources */, 135 | ); 136 | runOnlyForDeploymentPostprocessing = 0; 137 | }; 138 | /* End PBXSourcesBuildPhase section */ 139 | 140 | /* Begin XCBuildConfiguration section */ 141 | FE3CAD1A1CEE59530058C6B4 /* Debug */ = { 142 | isa = XCBuildConfiguration; 143 | buildSettings = { 144 | ALWAYS_SEARCH_USER_PATHS = NO; 145 | CLANG_ANALYZER_NONNULL = YES; 146 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 147 | CLANG_CXX_LIBRARY = "libc++"; 148 | CLANG_ENABLE_MODULES = YES; 149 | CLANG_ENABLE_OBJC_ARC = YES; 150 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 151 | CLANG_WARN_BOOL_CONVERSION = YES; 152 | CLANG_WARN_COMMA = YES; 153 | CLANG_WARN_CONSTANT_CONVERSION = YES; 154 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 155 | CLANG_WARN_EMPTY_BODY = YES; 156 | CLANG_WARN_ENUM_CONVERSION = YES; 157 | CLANG_WARN_INFINITE_RECURSION = YES; 158 | CLANG_WARN_INT_CONVERSION = YES; 159 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 160 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 161 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 162 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 163 | CLANG_WARN_STRICT_PROTOTYPES = YES; 164 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 165 | CLANG_WARN_UNREACHABLE_CODE = YES; 166 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 167 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 168 | COPY_PHASE_STRIP = NO; 169 | CURRENT_PROJECT_VERSION = 1; 170 | DEBUG_INFORMATION_FORMAT = dwarf; 171 | ENABLE_STRICT_OBJC_MSGSEND = YES; 172 | ENABLE_TESTABILITY = YES; 173 | GCC_C_LANGUAGE_STANDARD = gnu99; 174 | GCC_DYNAMIC_NO_PIC = NO; 175 | GCC_NO_COMMON_BLOCKS = YES; 176 | GCC_OPTIMIZATION_LEVEL = 0; 177 | GCC_PREPROCESSOR_DEFINITIONS = ( 178 | "DEBUG=1", 179 | "$(inherited)", 180 | ); 181 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 182 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 183 | GCC_WARN_UNDECLARED_SELECTOR = YES; 184 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 185 | GCC_WARN_UNUSED_FUNCTION = YES; 186 | GCC_WARN_UNUSED_VARIABLE = YES; 187 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 188 | MTL_ENABLE_DEBUG_INFO = YES; 189 | ONLY_ACTIVE_ARCH = YES; 190 | SDKROOT = iphoneos; 191 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 192 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 193 | TARGETED_DEVICE_FAMILY = "1,2"; 194 | VERSIONING_SYSTEM = "apple-generic"; 195 | VERSION_INFO_PREFIX = ""; 196 | }; 197 | name = Debug; 198 | }; 199 | FE3CAD1B1CEE59530058C6B4 /* Release */ = { 200 | isa = XCBuildConfiguration; 201 | buildSettings = { 202 | ALWAYS_SEARCH_USER_PATHS = NO; 203 | CLANG_ANALYZER_NONNULL = YES; 204 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 205 | CLANG_CXX_LIBRARY = "libc++"; 206 | CLANG_ENABLE_MODULES = YES; 207 | CLANG_ENABLE_OBJC_ARC = YES; 208 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 209 | CLANG_WARN_BOOL_CONVERSION = YES; 210 | CLANG_WARN_COMMA = YES; 211 | CLANG_WARN_CONSTANT_CONVERSION = YES; 212 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 213 | CLANG_WARN_EMPTY_BODY = YES; 214 | CLANG_WARN_ENUM_CONVERSION = YES; 215 | CLANG_WARN_INFINITE_RECURSION = YES; 216 | CLANG_WARN_INT_CONVERSION = YES; 217 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 218 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 219 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 220 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 221 | CLANG_WARN_STRICT_PROTOTYPES = YES; 222 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 223 | CLANG_WARN_UNREACHABLE_CODE = YES; 224 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 225 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 226 | COPY_PHASE_STRIP = NO; 227 | CURRENT_PROJECT_VERSION = 1; 228 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 229 | ENABLE_NS_ASSERTIONS = NO; 230 | ENABLE_STRICT_OBJC_MSGSEND = YES; 231 | GCC_C_LANGUAGE_STANDARD = gnu99; 232 | GCC_NO_COMMON_BLOCKS = YES; 233 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 234 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 235 | GCC_WARN_UNDECLARED_SELECTOR = YES; 236 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 237 | GCC_WARN_UNUSED_FUNCTION = YES; 238 | GCC_WARN_UNUSED_VARIABLE = YES; 239 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 240 | MTL_ENABLE_DEBUG_INFO = NO; 241 | SDKROOT = iphoneos; 242 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 243 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 244 | TARGETED_DEVICE_FAMILY = "1,2"; 245 | VALIDATE_PRODUCT = YES; 246 | VERSIONING_SYSTEM = "apple-generic"; 247 | VERSION_INFO_PREFIX = ""; 248 | }; 249 | name = Release; 250 | }; 251 | FE3CAD1D1CEE59530058C6B4 /* Debug */ = { 252 | isa = XCBuildConfiguration; 253 | buildSettings = { 254 | CLANG_ENABLE_MODULES = YES; 255 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 256 | DEFINES_MODULE = YES; 257 | DYLIB_COMPATIBILITY_VERSION = 1; 258 | DYLIB_CURRENT_VERSION = 1; 259 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 260 | INFOPLIST_FILE = "Supporting FIles/Info.plist"; 261 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 262 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 263 | PRODUCT_BUNDLE_IDENTIFIER = fr.liquidsoul.XCTestPlayground; 264 | PRODUCT_NAME = "$(TARGET_NAME)"; 265 | SKIP_INSTALL = YES; 266 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 267 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 268 | SWIFT_VERSION = 4.0; 269 | }; 270 | name = Debug; 271 | }; 272 | FE3CAD1E1CEE59530058C6B4 /* Release */ = { 273 | isa = XCBuildConfiguration; 274 | buildSettings = { 275 | CLANG_ENABLE_MODULES = YES; 276 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 277 | DEFINES_MODULE = YES; 278 | DYLIB_COMPATIBILITY_VERSION = 1; 279 | DYLIB_CURRENT_VERSION = 1; 280 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 281 | INFOPLIST_FILE = "Supporting FIles/Info.plist"; 282 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 283 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 284 | PRODUCT_BUNDLE_IDENTIFIER = fr.liquidsoul.XCTestPlayground; 285 | PRODUCT_NAME = "$(TARGET_NAME)"; 286 | SKIP_INSTALL = YES; 287 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 288 | SWIFT_VERSION = 4.0; 289 | }; 290 | name = Release; 291 | }; 292 | /* End XCBuildConfiguration section */ 293 | 294 | /* Begin XCConfigurationList section */ 295 | FE3CAD0E1CEE59530058C6B4 /* Build configuration list for PBXProject "XCTestPlayground" */ = { 296 | isa = XCConfigurationList; 297 | buildConfigurations = ( 298 | FE3CAD1A1CEE59530058C6B4 /* Debug */, 299 | FE3CAD1B1CEE59530058C6B4 /* Release */, 300 | ); 301 | defaultConfigurationIsVisible = 0; 302 | defaultConfigurationName = Release; 303 | }; 304 | FE3CAD1C1CEE59530058C6B4 /* Build configuration list for PBXNativeTarget "XCTestPlayground" */ = { 305 | isa = XCConfigurationList; 306 | buildConfigurations = ( 307 | FE3CAD1D1CEE59530058C6B4 /* Debug */, 308 | FE3CAD1E1CEE59530058C6B4 /* Release */, 309 | ); 310 | defaultConfigurationIsVisible = 0; 311 | defaultConfigurationName = Release; 312 | }; 313 | /* End XCConfigurationList section */ 314 | }; 315 | rootObject = FE3CAD0B1CEE59530058C6B4 /* Project object */; 316 | } 317 | -------------------------------------------------------------------------------- /XCTestPlayground.xcodeproj/xcshareddata/xcschemes/XCTestPlayground.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 35 | 36 | 47 | 48 | 54 | 55 | 56 | 57 | 58 | 59 | 65 | 66 | 72 | 73 | 74 | 75 | 77 | 78 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /XCTestPlayground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /XCTestPlaygroundExample.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: A simple example on how to use `XCTestPlayground`. 2 | //: 3 | //: Note that you **need** to build the framework first using a 64-bit target (iPhone 5s and above) before you can use it here. 4 | 5 | import Foundation 6 | import XCTestPlayground 7 | 8 | class TestCase: XCTestCase { 9 | @objc func testAssertions() { 10 | XCTAssertEqual(1, 2) 11 | XCTAssertEqual([1, 2], [2, 3]) 12 | XCTAssertGreaterThanOrEqual(1, 2) 13 | XCTAssertTrue(true) 14 | } 15 | } 16 | 17 | TestCase() 18 | -------------------------------------------------------------------------------- /XCTestPlaygroundExample.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Liquidsoul/XCTestPlayground/a2eb3620a62a99f443c82b3b84500ef3ee322dd0/screenshot.png --------------------------------------------------------------------------------