├── .gitignore ├── .gitmodules ├── .travis.yml ├── CONTRIBUTING.md ├── LICENSE ├── Quick Templates └── Quick Spec Class.xctemplate │ ├── Objective-C │ └── ___FILEBASENAME___.m │ ├── Swift │ └── ___FILEBASENAME___.swift │ ├── TemplateIcon.icns │ └── TemplateInfo.plist ├── Quick.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ ├── Quick-OSX.xcscheme │ └── Quick-iOS.xcscheme ├── Quick ├── Callsite.swift ├── Configuration │ ├── Configuration.swift │ ├── QuickConfiguration.h │ └── QuickConfiguration.m ├── DSL │ ├── DSL.swift │ ├── QCKDSL.h │ ├── QCKDSL.m │ └── World+DSL.swift ├── Example.swift ├── ExampleGroup.swift ├── ExampleMetadata.swift ├── Failure.swift ├── Hooks │ ├── Closures.swift │ ├── ExampleHooks.swift │ └── SuiteHooks.swift ├── Info.plist ├── NSException+Callsite.swift ├── NSString+QCKSelectorName.h ├── NSString+QCKSelectorName.m ├── Quick.h ├── QuickSpec.h ├── QuickSpec.m ├── World+Singleton.swift └── World.swift ├── QuickTests ├── ExampleMetadataFunctionalTests.swift ├── Fixtures │ ├── FunctionalTests_SharedExamplesTests_SharedExamples.swift │ ├── Person.swift │ └── Poet.swift ├── FunctionalTests+ObjC.m ├── FunctionalTests.swift ├── FunctionalTests │ ├── AfterEachTests.swift │ ├── AfterSuiteTests.swift │ ├── BeforeEachTests.swift │ ├── BeforeSuiteTests.swift │ ├── Configuration │ │ ├── AfterEach │ │ │ ├── Configuration+AfterEach.swift │ │ │ └── Configuration+AfterEachTests.swift │ │ └── BeforeEach │ │ │ ├── Configuration+BeforeEach.swift │ │ │ └── Configuration+BeforeEachTests.swift │ ├── FailureTests+ObjC.m │ ├── ItTests.swift │ ├── PendingTests.swift │ ├── SharedExamples+BeforeEachTests.swift │ └── SharedExamplesTests.swift ├── Helpers │ ├── QCKSpecRunner.h │ ├── QCKSpecRunner.m │ ├── QuickTestsBridgingHeader.h │ └── XCTestObservationCenter.h ├── Info.plist └── QuickConfigurationTests.m ├── README.md └── Rakefile /.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 | # Mac OS X 29 | .DS_Store 30 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Externals/Nimble"] 2 | path = Externals/Nimble 3 | url = https://github.com/github/Nimble.git 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | 3 | before_install: git submodule update --init --recursive 4 | script: "rake test:ios" 5 | 6 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | - [Welcome to Quick!](#welcome-to-quick!) 5 | - [Reporting Bugs](#reporting-bugs) 6 | - [Building the Project](#building-the-project) 7 | - [Pull Requests](#pull-requests) 8 | - [Style Conventions](#style-conventions) 9 | - [Core Members](#core-members) 10 | - [Code of Conduct](#code-of-conduct) 11 | 12 | 13 | 14 | # Welcome to Quick! 15 | 16 | We're building a BDD framework for a new generation of Swift and 17 | Objective-C developers. 18 | 19 | Quick should be easy to use and easy to maintain. Let's keep things 20 | simple and well-tested. 21 | 22 | **tl;dr:** If you've added a file to the project, make sure it's 23 | included in both the OS X and iOS targets. 24 | 25 | ## Reporting Bugs 26 | 27 | Nothing is off-limits. If you're having a problem, we want to hear about 28 | it. 29 | 30 | - See a crash? File an issue. 31 | - Code isn't compiling, but you don't know why? Sounds like you should 32 | submit a new issue, bud. 33 | - Went to the kitchen, only to forget why you went in the first place? 34 | Better submit an issue. 35 | 36 | ## Building the Project 37 | 38 | - Use `Quick.xcodeproj` to work on Quick. 39 | 40 | ## Pull Requests 41 | 42 | - Nothing is trivial. Submit pull requests for anything: typos, 43 | whitespace, you name it. 44 | - Not all pull requests will be merged, but all will be acknowledged. If 45 | no one has provided feedback on your request, ping one of the owners 46 | by name. 47 | - Make sure your pull request includes any necessary updates to the 48 | README or other documentation. 49 | - Be sure the unit tests for both the OS X and iOS targets of both Quick 50 | and Nimble pass before submitting your pull request. You can run all 51 | the OS X unit tests using `rake test` (hopefully this will support iOS 52 | soon, see: https://github.com/Quick/Quick/issues/25). 53 | - If you've added a file to the project, make sure it's included in both 54 | the OS X and iOS targets. 55 | 56 | ### Style Conventions 57 | 58 | - Indent using 4 spaces. 59 | - Keep lines 100 characters or shorter. Break long statements into 60 | shorter ones over multiple lines. 61 | - In Objective-C, use `#pragma mark -` to mark public, internal, 62 | protocol, and superclass methods. See `QuickSpec.m` for an example. 63 | 64 | ## Core Members 65 | 66 | If a few of your pull requests have been merged, and you'd like a 67 | controlling stake in the project, file an issue asking for write access 68 | to the repository. 69 | 70 | ### Code of Conduct 71 | 72 | Your conduct as a core member is your own responsibility, but here are 73 | some "ground rules": 74 | 75 | - Feel free to push whatever you want to master, and (if you have 76 | ownership permissions) to create any repositories you'd like. 77 | 78 | Ideally, however, all changes should be submitted as GitHub pull 79 | requests. No one should merge their own pull request, unless no 80 | other core members respond for at least a few days. 81 | 82 | If you'd like to create a new repository, it'd be nice if you created 83 | a GitHub issue and gathered some feedback first. 84 | 85 | - It'd be awesome if you could review, provide feedback on, and close 86 | issues or pull requests submitted to the project. Please provide kind, 87 | constructive feedback. Please don't be sarcastic or snarky. 88 | 89 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2014, Quick Team 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Quick Templates/Quick Spec Class.xctemplate/Objective-C/___FILEBASENAME___.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | QuickSpecBegin(___FILEBASENAMEASIDENTIFIER___) 5 | 6 | QuickSpecEnd 7 | -------------------------------------------------------------------------------- /Quick Templates/Quick Spec Class.xctemplate/Swift/___FILEBASENAME___.swift: -------------------------------------------------------------------------------- 1 | import Quick 2 | import Nimble 3 | 4 | class ___FILEBASENAMEASIDENTIFIER___: QuickSpec { 5 | override func spec() { 6 | 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Quick Templates/Quick Spec Class.xctemplate/TemplateIcon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/Quick/1029e8173a37fe8eb3ac2a8f048c976a8c63555b/Quick Templates/Quick Spec Class.xctemplate/TemplateIcon.icns -------------------------------------------------------------------------------- /Quick Templates/Quick Spec Class.xctemplate/TemplateInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Kind 6 | Xcode.IDEKit.TextSubstitutionFileTemplateKind 7 | Description 8 | A class implementing a Quick spec. 9 | Summary 10 | A class implementing a Quick spec 11 | SortOrder 12 | 1 13 | BuildableType 14 | Test 15 | DefaultCompletionName 16 | Spec 17 | Options 18 | 19 | 20 | Description 21 | Name of the Quick spec class 22 | Identifier 23 | productName 24 | Name 25 | Spec Name: 26 | NotPersisted 27 | 28 | Required 29 | 30 | Type 31 | text 32 | 33 | 34 | AllowedTypes 35 | 36 | Swift 37 | 38 | public.swift-source 39 | 40 | Objective-C 41 | 42 | public.objective-c-source 43 | public.objective-c-plus-plus-source 44 | 45 | 46 | Default 47 | Swift 48 | Description 49 | The implementation language 50 | Identifier 51 | languageChoice 52 | MainTemplateFiles 53 | 54 | Objective-C 55 | ___FILEBASENAME___.m 56 | Swift 57 | ___FILEBASENAME___.swift 58 | 59 | Name 60 | Language: 61 | Required 62 | Yes 63 | Type 64 | popup 65 | Values 66 | 67 | Swift 68 | Objective-C 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /Quick.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1F6BB86819693204009F1DBB /* FunctionalTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAEB6BCB194387D700289F44 /* FunctionalTests.swift */; }; 11 | 1F6BB86A1969BF75009F1DBB /* FunctionalTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAEB6BCB194387D700289F44 /* FunctionalTests.swift */; }; 12 | 34512A391948223C007D457A /* FunctionalTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 34512A381948223C007D457A /* FunctionalTests+ObjC.m */; }; 13 | 34512A3A1948223C007D457A /* FunctionalTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 34512A381948223C007D457A /* FunctionalTests+ObjC.m */; }; 14 | 34F375A719515CA700CE1B99 /* Callsite.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F3759C19515CA700CE1B99 /* Callsite.swift */; }; 15 | 34F375A819515CA700CE1B99 /* Callsite.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F3759C19515CA700CE1B99 /* Callsite.swift */; }; 16 | 34F375AB19515CA700CE1B99 /* Example.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F3759E19515CA700CE1B99 /* Example.swift */; }; 17 | 34F375AC19515CA700CE1B99 /* Example.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F3759E19515CA700CE1B99 /* Example.swift */; }; 18 | 34F375AD19515CA700CE1B99 /* ExampleGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F3759F19515CA700CE1B99 /* ExampleGroup.swift */; }; 19 | 34F375AE19515CA700CE1B99 /* ExampleGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F3759F19515CA700CE1B99 /* ExampleGroup.swift */; }; 20 | 34F375AF19515CA700CE1B99 /* NSString+QCKSelectorName.h in Headers */ = {isa = PBXBuildFile; fileRef = 34F375A019515CA700CE1B99 /* NSString+QCKSelectorName.h */; }; 21 | 34F375B019515CA700CE1B99 /* NSString+QCKSelectorName.h in Headers */ = {isa = PBXBuildFile; fileRef = 34F375A019515CA700CE1B99 /* NSString+QCKSelectorName.h */; }; 22 | 34F375B119515CA700CE1B99 /* NSString+QCKSelectorName.m in Sources */ = {isa = PBXBuildFile; fileRef = 34F375A119515CA700CE1B99 /* NSString+QCKSelectorName.m */; }; 23 | 34F375B219515CA700CE1B99 /* NSString+QCKSelectorName.m in Sources */ = {isa = PBXBuildFile; fileRef = 34F375A119515CA700CE1B99 /* NSString+QCKSelectorName.m */; }; 24 | 34F375B719515CA700CE1B99 /* QuickSpec.h in Headers */ = {isa = PBXBuildFile; fileRef = 34F375A419515CA700CE1B99 /* QuickSpec.h */; settings = {ATTRIBUTES = (Public, ); }; }; 25 | 34F375B819515CA700CE1B99 /* QuickSpec.h in Headers */ = {isa = PBXBuildFile; fileRef = 34F375A419515CA700CE1B99 /* QuickSpec.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26 | 34F375B919515CA700CE1B99 /* QuickSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 34F375A519515CA700CE1B99 /* QuickSpec.m */; }; 27 | 34F375BA19515CA700CE1B99 /* QuickSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 34F375A519515CA700CE1B99 /* QuickSpec.m */; }; 28 | 34F375BB19515CA700CE1B99 /* World.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F375A619515CA700CE1B99 /* World.swift */; }; 29 | 34F375BC19515CA700CE1B99 /* World.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F375A619515CA700CE1B99 /* World.swift */; }; 30 | 5A5D118719473F2100F6D13D /* Quick.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A5D117C19473F2100F6D13D /* Quick.framework */; }; 31 | 5A5D11A7194740E000F6D13D /* Quick.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB6B931943873100289F44 /* Quick.h */; settings = {ATTRIBUTES = (Public, ); }; }; 32 | 5A5D11AC1947412800F6D13D /* Person.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAEB6BCE194387D700289F44 /* Person.swift */; }; 33 | 5A5D11AD1947412800F6D13D /* Poet.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAEB6BCF194387D700289F44 /* Poet.swift */; }; 34 | 5AFC5949195ED5B900D3E0A2 /* Failure.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AFC5948195ED5B900D3E0A2 /* Failure.swift */; }; 35 | 5AFC594A195ED5B900D3E0A2 /* Failure.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AFC5948195ED5B900D3E0A2 /* Failure.swift */; }; 36 | 5AFC5960195EEDA900D3E0A2 /* NSException+Callsite.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AFC595F195EEDA900D3E0A2 /* NSException+Callsite.swift */; }; 37 | 5AFC5961195EEDA900D3E0A2 /* NSException+Callsite.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AFC595F195EEDA900D3E0A2 /* NSException+Callsite.swift */; }; 38 | AAACAAD919532C4E00B492A8 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AADBF9A819521298005E1714 /* XCTest.framework */; }; 39 | AADBF9AC195213AD005E1714 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AADBF9A919521298005E1714 /* XCTest.framework */; }; 40 | DA02C91919A8073100093156 /* ExampleMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA02C91819A8073100093156 /* ExampleMetadata.swift */; }; 41 | DA02C91A19A8073100093156 /* ExampleMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA02C91819A8073100093156 /* ExampleMetadata.swift */; }; 42 | DA05D61019F73A3800771050 /* AfterEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA05D60F19F73A3800771050 /* AfterEachTests.swift */; }; 43 | DA05D61119F73A3800771050 /* AfterEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA05D60F19F73A3800771050 /* AfterEachTests.swift */; }; 44 | DA169E4819FF5DF100619816 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA169E4719FF5DF100619816 /* Configuration.swift */; }; 45 | DA169E4919FF5DF100619816 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA169E4719FF5DF100619816 /* Configuration.swift */; }; 46 | DA3124E619FCAEE8002858A7 /* DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA3124E219FCAEE8002858A7 /* DSL.swift */; }; 47 | DA3124E719FCAEE8002858A7 /* DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA3124E219FCAEE8002858A7 /* DSL.swift */; }; 48 | DA3124E819FCAEE8002858A7 /* QCKDSL.h in Headers */ = {isa = PBXBuildFile; fileRef = DA3124E319FCAEE8002858A7 /* QCKDSL.h */; settings = {ATTRIBUTES = (Public, ); }; }; 49 | DA3124E919FCAEE8002858A7 /* QCKDSL.h in Headers */ = {isa = PBXBuildFile; fileRef = DA3124E319FCAEE8002858A7 /* QCKDSL.h */; settings = {ATTRIBUTES = (Public, ); }; }; 50 | DA3124EA19FCAEE8002858A7 /* QCKDSL.m in Sources */ = {isa = PBXBuildFile; fileRef = DA3124E419FCAEE8002858A7 /* QCKDSL.m */; }; 51 | DA3124EB19FCAEE8002858A7 /* QCKDSL.m in Sources */ = {isa = PBXBuildFile; fileRef = DA3124E419FCAEE8002858A7 /* QCKDSL.m */; }; 52 | DA3124EC19FCAEE8002858A7 /* World+DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA3124E519FCAEE8002858A7 /* World+DSL.swift */; }; 53 | DA3124ED19FCAEE8002858A7 /* World+DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA3124E519FCAEE8002858A7 /* World+DSL.swift */; }; 54 | DA408BE219FF5599005DF92A /* Closures.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA408BDF19FF5599005DF92A /* Closures.swift */; }; 55 | DA408BE319FF5599005DF92A /* Closures.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA408BDF19FF5599005DF92A /* Closures.swift */; }; 56 | DA408BE419FF5599005DF92A /* ExampleHooks.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA408BE019FF5599005DF92A /* ExampleHooks.swift */; }; 57 | DA408BE519FF5599005DF92A /* ExampleHooks.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA408BE019FF5599005DF92A /* ExampleHooks.swift */; }; 58 | DA408BE619FF5599005DF92A /* SuiteHooks.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA408BE119FF5599005DF92A /* SuiteHooks.swift */; }; 59 | DA408BE719FF5599005DF92A /* SuiteHooks.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA408BE119FF5599005DF92A /* SuiteHooks.swift */; }; 60 | DA54728219FC2B5700332193 /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA54727F19FC2B4400332193 /* Nimble.framework */; }; 61 | DA54728319FC2B5C00332193 /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA54727B19FC2B4400332193 /* Nimble.framework */; }; 62 | DA7AE6F119FC493F000AFDCE /* ItTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA7AE6F019FC493F000AFDCE /* ItTests.swift */; }; 63 | DA7AE6F219FC493F000AFDCE /* ItTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA7AE6F019FC493F000AFDCE /* ItTests.swift */; }; 64 | DA8C00211A01E4B900CE58A6 /* QuickConfigurationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8C00201A01E4B900CE58A6 /* QuickConfigurationTests.m */; }; 65 | DA8C00221A01E4B900CE58A6 /* QuickConfigurationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8C00201A01E4B900CE58A6 /* QuickConfigurationTests.m */; }; 66 | DA8F919919F31680006F6675 /* QCKSpecRunner.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8F919619F31680006F6675 /* QCKSpecRunner.m */; }; 67 | DA8F919A19F31680006F6675 /* QCKSpecRunner.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8F919619F31680006F6675 /* QCKSpecRunner.m */; }; 68 | DA8F919D19F31921006F6675 /* FailureTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8F919C19F31921006F6675 /* FailureTests+ObjC.m */; }; 69 | DA8F919E19F31921006F6675 /* FailureTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8F919C19F31921006F6675 /* FailureTests+ObjC.m */; }; 70 | DA8F91A519F3208B006F6675 /* BeforeSuiteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA8F91A419F3208B006F6675 /* BeforeSuiteTests.swift */; }; 71 | DA8F91A619F3208B006F6675 /* BeforeSuiteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA8F91A419F3208B006F6675 /* BeforeSuiteTests.swift */; }; 72 | DA8F91A819F32556006F6675 /* AfterSuiteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA8F91A719F32556006F6675 /* AfterSuiteTests.swift */; }; 73 | DA8F91A919F32556006F6675 /* AfterSuiteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA8F91A719F32556006F6675 /* AfterSuiteTests.swift */; }; 74 | DA8F91AB19F3299E006F6675 /* SharedExamplesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA8F91AA19F3299E006F6675 /* SharedExamplesTests.swift */; }; 75 | DA8F91AC19F3299E006F6675 /* SharedExamplesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA8F91AA19F3299E006F6675 /* SharedExamplesTests.swift */; }; 76 | DA8F91AE19F32CE2006F6675 /* FunctionalTests_SharedExamplesTests_SharedExamples.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA8F91AD19F32CE2006F6675 /* FunctionalTests_SharedExamplesTests_SharedExamples.swift */; }; 77 | DA8F91AF19F32CE2006F6675 /* FunctionalTests_SharedExamplesTests_SharedExamples.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA8F91AD19F32CE2006F6675 /* FunctionalTests_SharedExamplesTests_SharedExamples.swift */; }; 78 | DAA63EA319F7637300CD0A3B /* PendingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAA63EA219F7637300CD0A3B /* PendingTests.swift */; }; 79 | DAA63EA419F7637300CD0A3B /* PendingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAA63EA219F7637300CD0A3B /* PendingTests.swift */; }; 80 | DAA7C0D719F777EB0093D1D9 /* BeforeEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA87078219F48775008C04AC /* BeforeEachTests.swift */; }; 81 | DAB0136F19FC4315006AFBEE /* SharedExamples+BeforeEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAB0136E19FC4315006AFBEE /* SharedExamples+BeforeEachTests.swift */; }; 82 | DAB0137019FC4315006AFBEE /* SharedExamples+BeforeEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAB0136E19FC4315006AFBEE /* SharedExamples+BeforeEachTests.swift */; }; 83 | DAB067E919F7801C00F970AC /* BeforeEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA87078219F48775008C04AC /* BeforeEachTests.swift */; }; 84 | DAE714F019FF65D3005905B8 /* Configuration+BeforeEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAE714EF19FF65D3005905B8 /* Configuration+BeforeEachTests.swift */; }; 85 | DAE714F119FF65D3005905B8 /* Configuration+BeforeEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAE714EF19FF65D3005905B8 /* Configuration+BeforeEachTests.swift */; }; 86 | DAE714F319FF65E7005905B8 /* Configuration+BeforeEach.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAE714F219FF65E7005905B8 /* Configuration+BeforeEach.swift */; }; 87 | DAE714F419FF65E7005905B8 /* Configuration+BeforeEach.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAE714F219FF65E7005905B8 /* Configuration+BeforeEach.swift */; }; 88 | DAE714F719FF6812005905B8 /* Configuration+AfterEach.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAE714F619FF6812005905B8 /* Configuration+AfterEach.swift */; }; 89 | DAE714F819FF6812005905B8 /* Configuration+AfterEach.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAE714F619FF6812005905B8 /* Configuration+AfterEach.swift */; }; 90 | DAE714FA19FF682A005905B8 /* Configuration+AfterEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAE714F919FF682A005905B8 /* Configuration+AfterEachTests.swift */; }; 91 | DAE714FB19FF682A005905B8 /* Configuration+AfterEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAE714F919FF682A005905B8 /* Configuration+AfterEachTests.swift */; }; 92 | DAE714FE19FF6A62005905B8 /* QuickConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = DAE714FC19FF6A62005905B8 /* QuickConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; }; 93 | DAE714FF19FF6A62005905B8 /* QuickConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = DAE714FC19FF6A62005905B8 /* QuickConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; }; 94 | DAE7150019FF6A62005905B8 /* QuickConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = DAE714FD19FF6A62005905B8 /* QuickConfiguration.m */; }; 95 | DAE7150119FF6A62005905B8 /* QuickConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = DAE714FD19FF6A62005905B8 /* QuickConfiguration.m */; }; 96 | DAEB6B941943873100289F44 /* Quick.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB6B931943873100289F44 /* Quick.h */; settings = {ATTRIBUTES = (Public, ); }; }; 97 | DAEB6B9A1943873100289F44 /* Quick.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DAEB6B8E1943873100289F44 /* Quick.framework */; }; 98 | DAEB6BD4194387D700289F44 /* Person.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAEB6BCE194387D700289F44 /* Person.swift */; }; 99 | DAEB6BD5194387D700289F44 /* Poet.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAEB6BCF194387D700289F44 /* Poet.swift */; }; 100 | DAECD76319AC4039003EFF14 /* ExampleMetadataFunctionalTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAECD76219AC4039003EFF14 /* ExampleMetadataFunctionalTests.swift */; }; 101 | DAECD76419AC4039003EFF14 /* ExampleMetadataFunctionalTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAECD76219AC4039003EFF14 /* ExampleMetadataFunctionalTests.swift */; }; 102 | DAEE632A19FF4EE30089F850 /* World+Singleton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAEE632919FF4EE30089F850 /* World+Singleton.swift */; }; 103 | DAEE632B19FF4EE30089F850 /* World+Singleton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAEE632919FF4EE30089F850 /* World+Singleton.swift */; }; 104 | /* End PBXBuildFile section */ 105 | 106 | /* Begin PBXContainerItemProxy section */ 107 | 047655511949F4CB00B288BB /* PBXContainerItemProxy */ = { 108 | isa = PBXContainerItemProxy; 109 | containerPortal = DAEB6B851943873100289F44 /* Project object */; 110 | proxyType = 1; 111 | remoteGlobalIDString = DAEB6B8D1943873100289F44; 112 | remoteInfo = Quick; 113 | }; 114 | 047655531949F4CB00B288BB /* PBXContainerItemProxy */ = { 115 | isa = PBXContainerItemProxy; 116 | containerPortal = DAEB6B851943873100289F44 /* Project object */; 117 | proxyType = 1; 118 | remoteGlobalIDString = DAEB6B8D1943873100289F44; 119 | remoteInfo = Quick; 120 | }; 121 | 04765555194A327000B288BB /* PBXContainerItemProxy */ = { 122 | isa = PBXContainerItemProxy; 123 | containerPortal = DAEB6B851943873100289F44 /* Project object */; 124 | proxyType = 1; 125 | remoteGlobalIDString = DAEB6B8D1943873100289F44; 126 | remoteInfo = Quick; 127 | }; 128 | 04DC97E4194B4A6000CE00B6 /* PBXContainerItemProxy */ = { 129 | isa = PBXContainerItemProxy; 130 | containerPortal = DAEB6B851943873100289F44 /* Project object */; 131 | proxyType = 1; 132 | remoteGlobalIDString = DAEB6B8D1943873100289F44; 133 | remoteInfo = Quick; 134 | }; 135 | 04DC97E6194B4A6000CE00B6 /* PBXContainerItemProxy */ = { 136 | isa = PBXContainerItemProxy; 137 | containerPortal = DAEB6B851943873100289F44 /* Project object */; 138 | proxyType = 1; 139 | remoteGlobalIDString = DAEB6B8D1943873100289F44; 140 | remoteInfo = Quick; 141 | }; 142 | 04DC97E8194B4B7E00CE00B6 /* PBXContainerItemProxy */ = { 143 | isa = PBXContainerItemProxy; 144 | containerPortal = DAEB6B851943873100289F44 /* Project object */; 145 | proxyType = 1; 146 | remoteGlobalIDString = 5A5D117B19473F2100F6D13D; 147 | remoteInfo = "Quick-iOS"; 148 | }; 149 | 04DC97EA194B4B9B00CE00B6 /* PBXContainerItemProxy */ = { 150 | isa = PBXContainerItemProxy; 151 | containerPortal = DAEB6B851943873100289F44 /* Project object */; 152 | proxyType = 1; 153 | remoteGlobalIDString = 5A5D117B19473F2100F6D13D; 154 | remoteInfo = "Quick-iOS"; 155 | }; 156 | 04DC97F0194B82DB00CE00B6 /* PBXContainerItemProxy */ = { 157 | isa = PBXContainerItemProxy; 158 | containerPortal = DAEB6B851943873100289F44 /* Project object */; 159 | proxyType = 1; 160 | remoteGlobalIDString = DAEB6B8D1943873100289F44; 161 | remoteInfo = Quick; 162 | }; 163 | 04DC97F2194B82DE00CE00B6 /* PBXContainerItemProxy */ = { 164 | isa = PBXContainerItemProxy; 165 | containerPortal = DAEB6B851943873100289F44 /* Project object */; 166 | proxyType = 1; 167 | remoteGlobalIDString = 5A5D117B19473F2100F6D13D; 168 | remoteInfo = "Quick-iOS"; 169 | }; 170 | 04DC97F6194B831200CE00B6 /* PBXContainerItemProxy */ = { 171 | isa = PBXContainerItemProxy; 172 | containerPortal = DAEB6B851943873100289F44 /* Project object */; 173 | proxyType = 1; 174 | remoteGlobalIDString = 5A5D117B19473F2100F6D13D; 175 | remoteInfo = "Quick-iOS"; 176 | }; 177 | 04DC97F8194B834000CE00B6 /* PBXContainerItemProxy */ = { 178 | isa = PBXContainerItemProxy; 179 | containerPortal = DAEB6B851943873100289F44 /* Project object */; 180 | proxyType = 1; 181 | remoteGlobalIDString = DAEB6B8D1943873100289F44; 182 | remoteInfo = Quick; 183 | }; 184 | 04DC97FA194B834100CE00B6 /* PBXContainerItemProxy */ = { 185 | isa = PBXContainerItemProxy; 186 | containerPortal = DAEB6B851943873100289F44 /* Project object */; 187 | proxyType = 1; 188 | remoteGlobalIDString = 5A5D117B19473F2100F6D13D; 189 | remoteInfo = "Quick-iOS"; 190 | }; 191 | 04DC97FC194B834B00CE00B6 /* PBXContainerItemProxy */ = { 192 | isa = PBXContainerItemProxy; 193 | containerPortal = DAEB6B851943873100289F44 /* Project object */; 194 | proxyType = 1; 195 | remoteGlobalIDString = DAEB6B8D1943873100289F44; 196 | remoteInfo = Quick; 197 | }; 198 | 04DC97FE194B835E00CE00B6 /* PBXContainerItemProxy */ = { 199 | isa = PBXContainerItemProxy; 200 | containerPortal = DAEB6B851943873100289F44 /* Project object */; 201 | proxyType = 1; 202 | remoteGlobalIDString = 5A5D117B19473F2100F6D13D; 203 | remoteInfo = "Quick-iOS"; 204 | }; 205 | 04DC9800194B836100CE00B6 /* PBXContainerItemProxy */ = { 206 | isa = PBXContainerItemProxy; 207 | containerPortal = DAEB6B851943873100289F44 /* Project object */; 208 | proxyType = 1; 209 | remoteGlobalIDString = DAEB6B8D1943873100289F44; 210 | remoteInfo = Quick; 211 | }; 212 | 04DC9802194B836300CE00B6 /* PBXContainerItemProxy */ = { 213 | isa = PBXContainerItemProxy; 214 | containerPortal = DAEB6B851943873100289F44 /* Project object */; 215 | proxyType = 1; 216 | remoteGlobalIDString = 5A5D117B19473F2100F6D13D; 217 | remoteInfo = "Quick-iOS"; 218 | }; 219 | 04DC9804194B838400CE00B6 /* PBXContainerItemProxy */ = { 220 | isa = PBXContainerItemProxy; 221 | containerPortal = DAEB6B851943873100289F44 /* Project object */; 222 | proxyType = 1; 223 | remoteGlobalIDString = DAEB6B8D1943873100289F44; 224 | remoteInfo = Quick; 225 | }; 226 | 04DC9806194B838700CE00B6 /* PBXContainerItemProxy */ = { 227 | isa = PBXContainerItemProxy; 228 | containerPortal = DAEB6B851943873100289F44 /* Project object */; 229 | proxyType = 1; 230 | remoteGlobalIDString = 5A5D117B19473F2100F6D13D; 231 | remoteInfo = "Quick-iOS"; 232 | }; 233 | 04DC9808194B838B00CE00B6 /* PBXContainerItemProxy */ = { 234 | isa = PBXContainerItemProxy; 235 | containerPortal = DAEB6B851943873100289F44 /* Project object */; 236 | proxyType = 1; 237 | remoteGlobalIDString = DAEB6B8D1943873100289F44; 238 | remoteInfo = Quick; 239 | }; 240 | 1F5F97901A06DA4500C684A1 /* PBXContainerItemProxy */ = { 241 | isa = PBXContainerItemProxy; 242 | containerPortal = DA54727319FC2B4400332193 /* Nimble.xcodeproj */; 243 | proxyType = 1; 244 | remoteGlobalIDString = 1F1A74281940169200FFFC47; 245 | remoteInfo = "Nimble-iOS"; 246 | }; 247 | 1F5F97961A06DA4D00C684A1 /* PBXContainerItemProxy */ = { 248 | isa = PBXContainerItemProxy; 249 | containerPortal = DA54727319FC2B4400332193 /* Nimble.xcodeproj */; 250 | proxyType = 1; 251 | remoteGlobalIDString = 1F925EAC195C0D6300ED456B; 252 | remoteInfo = "Nimble-OSX"; 253 | }; 254 | 5A5D118819473F2100F6D13D /* PBXContainerItemProxy */ = { 255 | isa = PBXContainerItemProxy; 256 | containerPortal = DAEB6B851943873100289F44 /* Project object */; 257 | proxyType = 1; 258 | remoteGlobalIDString = 5A5D117B19473F2100F6D13D; 259 | remoteInfo = "Quick-iOS"; 260 | }; 261 | 5A5D11EF194741B500F6D13D /* PBXContainerItemProxy */ = { 262 | isa = PBXContainerItemProxy; 263 | containerPortal = DAEB6B851943873100289F44 /* Project object */; 264 | proxyType = 1; 265 | remoteGlobalIDString = 5A5D117B19473F2100F6D13D; 266 | remoteInfo = "Quick-iOS"; 267 | }; 268 | 5A5D11F1194741B500F6D13D /* PBXContainerItemProxy */ = { 269 | isa = PBXContainerItemProxy; 270 | containerPortal = DAEB6B851943873100289F44 /* Project object */; 271 | proxyType = 1; 272 | remoteGlobalIDString = 5A5D117B19473F2100F6D13D; 273 | remoteInfo = "Quick-iOS"; 274 | }; 275 | 93625F381951DDC8006B1FE1 /* PBXContainerItemProxy */ = { 276 | isa = PBXContainerItemProxy; 277 | containerPortal = DAEB6B851943873100289F44 /* Project object */; 278 | proxyType = 1; 279 | remoteGlobalIDString = DAEB6B8D1943873100289F44; 280 | remoteInfo = Quick; 281 | }; 282 | DA54727A19FC2B4400332193 /* PBXContainerItemProxy */ = { 283 | isa = PBXContainerItemProxy; 284 | containerPortal = DA54727319FC2B4400332193 /* Nimble.xcodeproj */; 285 | proxyType = 2; 286 | remoteGlobalIDString = 1F1A74291940169200FFFC47; 287 | remoteInfo = "Nimble-iOS"; 288 | }; 289 | DA54727C19FC2B4400332193 /* PBXContainerItemProxy */ = { 290 | isa = PBXContainerItemProxy; 291 | containerPortal = DA54727319FC2B4400332193 /* Nimble.xcodeproj */; 292 | proxyType = 2; 293 | remoteGlobalIDString = 1F1A74341940169200FFFC47; 294 | remoteInfo = "Nimble-iOSTests"; 295 | }; 296 | DA54727E19FC2B4400332193 /* PBXContainerItemProxy */ = { 297 | isa = PBXContainerItemProxy; 298 | containerPortal = DA54727319FC2B4400332193 /* Nimble.xcodeproj */; 299 | proxyType = 2; 300 | remoteGlobalIDString = 1F925EAD195C0D6300ED456B; 301 | remoteInfo = "Nimble-OSX"; 302 | }; 303 | DA54728019FC2B4400332193 /* PBXContainerItemProxy */ = { 304 | isa = PBXContainerItemProxy; 305 | containerPortal = DA54727319FC2B4400332193 /* Nimble.xcodeproj */; 306 | proxyType = 2; 307 | remoteGlobalIDString = 1F925EB7195C0D6300ED456B; 308 | remoteInfo = "Nimble-OSXTests"; 309 | }; 310 | DAEB6B9B1943873100289F44 /* PBXContainerItemProxy */ = { 311 | isa = PBXContainerItemProxy; 312 | containerPortal = DAEB6B851943873100289F44 /* Project object */; 313 | proxyType = 1; 314 | remoteGlobalIDString = DAEB6B8D1943873100289F44; 315 | remoteInfo = Quick; 316 | }; 317 | /* End PBXContainerItemProxy section */ 318 | 319 | /* Begin PBXFileReference section */ 320 | 34512A381948223C007D457A /* FunctionalTests+ObjC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "FunctionalTests+ObjC.m"; sourceTree = ""; }; 321 | 34F3759C19515CA700CE1B99 /* Callsite.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Callsite.swift; sourceTree = ""; }; 322 | 34F3759E19515CA700CE1B99 /* Example.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Example.swift; sourceTree = ""; }; 323 | 34F3759F19515CA700CE1B99 /* ExampleGroup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExampleGroup.swift; sourceTree = ""; }; 324 | 34F375A019515CA700CE1B99 /* NSString+QCKSelectorName.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+QCKSelectorName.h"; sourceTree = ""; }; 325 | 34F375A119515CA700CE1B99 /* NSString+QCKSelectorName.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+QCKSelectorName.m"; sourceTree = ""; }; 326 | 34F375A419515CA700CE1B99 /* QuickSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QuickSpec.h; sourceTree = ""; }; 327 | 34F375A519515CA700CE1B99 /* QuickSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QuickSpec.m; sourceTree = ""; }; 328 | 34F375A619515CA700CE1B99 /* World.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = World.swift; sourceTree = ""; }; 329 | 5A5D117C19473F2100F6D13D /* Quick.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Quick.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 330 | 5A5D118619473F2100F6D13D /* Quick-iOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Quick-iOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 331 | 5AFC5948195ED5B900D3E0A2 /* Failure.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Failure.swift; sourceTree = ""; }; 332 | 5AFC595F195EEDA900D3E0A2 /* NSException+Callsite.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSException+Callsite.swift"; sourceTree = ""; }; 333 | AADBF9A819521298005E1714 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/MacOSX.platform/Developer/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 334 | AADBF9A919521298005E1714 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/iPhoneSimulator.platform/Developer/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 335 | DA02C91819A8073100093156 /* ExampleMetadata.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExampleMetadata.swift; sourceTree = ""; }; 336 | DA05D60F19F73A3800771050 /* AfterEachTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AfterEachTests.swift; sourceTree = ""; }; 337 | DA169E4719FF5DF100619816 /* Configuration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Configuration.swift; sourceTree = ""; }; 338 | DA3124E219FCAEE8002858A7 /* DSL.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DSL.swift; sourceTree = ""; }; 339 | DA3124E319FCAEE8002858A7 /* QCKDSL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QCKDSL.h; sourceTree = ""; }; 340 | DA3124E419FCAEE8002858A7 /* QCKDSL.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QCKDSL.m; sourceTree = ""; }; 341 | DA3124E519FCAEE8002858A7 /* World+DSL.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "World+DSL.swift"; sourceTree = ""; }; 342 | DA408BDF19FF5599005DF92A /* Closures.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Closures.swift; sourceTree = ""; }; 343 | DA408BE019FF5599005DF92A /* ExampleHooks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExampleHooks.swift; sourceTree = ""; }; 344 | DA408BE119FF5599005DF92A /* SuiteHooks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SuiteHooks.swift; sourceTree = ""; }; 345 | DA54727319FC2B4400332193 /* Nimble.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Nimble.xcodeproj; path = Externals/Nimble/Nimble.xcodeproj; sourceTree = SOURCE_ROOT; }; 346 | DA7AE6F019FC493F000AFDCE /* ItTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ItTests.swift; sourceTree = ""; }; 347 | DA87078219F48775008C04AC /* BeforeEachTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeforeEachTests.swift; sourceTree = ""; }; 348 | DA8C00201A01E4B900CE58A6 /* QuickConfigurationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QuickConfigurationTests.m; sourceTree = ""; }; 349 | DA8F919519F31680006F6675 /* QCKSpecRunner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QCKSpecRunner.h; sourceTree = ""; }; 350 | DA8F919619F31680006F6675 /* QCKSpecRunner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QCKSpecRunner.m; sourceTree = ""; }; 351 | DA8F919719F31680006F6675 /* QuickTestsBridgingHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QuickTestsBridgingHeader.h; sourceTree = ""; }; 352 | DA8F919819F31680006F6675 /* XCTestObservationCenter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XCTestObservationCenter.h; sourceTree = ""; }; 353 | DA8F919C19F31921006F6675 /* FailureTests+ObjC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "FailureTests+ObjC.m"; sourceTree = ""; }; 354 | DA8F91A419F3208B006F6675 /* BeforeSuiteTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeforeSuiteTests.swift; sourceTree = ""; }; 355 | DA8F91A719F32556006F6675 /* AfterSuiteTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AfterSuiteTests.swift; sourceTree = ""; }; 356 | DA8F91AA19F3299E006F6675 /* SharedExamplesTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SharedExamplesTests.swift; sourceTree = ""; }; 357 | DA8F91AD19F32CE2006F6675 /* FunctionalTests_SharedExamplesTests_SharedExamples.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FunctionalTests_SharedExamplesTests_SharedExamples.swift; sourceTree = ""; }; 358 | DAA63EA219F7637300CD0A3B /* PendingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PendingTests.swift; sourceTree = ""; }; 359 | DAB0136E19FC4315006AFBEE /* SharedExamples+BeforeEachTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SharedExamples+BeforeEachTests.swift"; sourceTree = ""; }; 360 | DAE714EF19FF65D3005905B8 /* Configuration+BeforeEachTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Configuration+BeforeEachTests.swift"; sourceTree = ""; }; 361 | DAE714F219FF65E7005905B8 /* Configuration+BeforeEach.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Configuration+BeforeEach.swift"; sourceTree = ""; }; 362 | DAE714F619FF6812005905B8 /* Configuration+AfterEach.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Configuration+AfterEach.swift"; sourceTree = ""; }; 363 | DAE714F919FF682A005905B8 /* Configuration+AfterEachTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Configuration+AfterEachTests.swift"; sourceTree = ""; }; 364 | DAE714FC19FF6A62005905B8 /* QuickConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QuickConfiguration.h; sourceTree = ""; }; 365 | DAE714FD19FF6A62005905B8 /* QuickConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QuickConfiguration.m; sourceTree = ""; }; 366 | DAEB6B8E1943873100289F44 /* Quick.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Quick.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 367 | DAEB6B921943873100289F44 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 368 | DAEB6B931943873100289F44 /* Quick.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Quick.h; sourceTree = ""; }; 369 | DAEB6B991943873100289F44 /* Quick-OSXTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Quick-OSXTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 370 | DAEB6B9F1943873100289F44 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 371 | DAEB6BCB194387D700289F44 /* FunctionalTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FunctionalTests.swift; sourceTree = ""; }; 372 | DAEB6BCE194387D700289F44 /* Person.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Person.swift; sourceTree = ""; }; 373 | DAEB6BCF194387D700289F44 /* Poet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Poet.swift; sourceTree = ""; }; 374 | DAECD76219AC4039003EFF14 /* ExampleMetadataFunctionalTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExampleMetadataFunctionalTests.swift; sourceTree = ""; }; 375 | DAEE632919FF4EE30089F850 /* World+Singleton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "World+Singleton.swift"; sourceTree = ""; }; 376 | /* End PBXFileReference section */ 377 | 378 | /* Begin PBXFrameworksBuildPhase section */ 379 | 5A5D117819473F2100F6D13D /* Frameworks */ = { 380 | isa = PBXFrameworksBuildPhase; 381 | buildActionMask = 2147483647; 382 | files = ( 383 | AADBF9AC195213AD005E1714 /* XCTest.framework in Frameworks */, 384 | ); 385 | runOnlyForDeploymentPostprocessing = 0; 386 | }; 387 | 5A5D118319473F2100F6D13D /* Frameworks */ = { 388 | isa = PBXFrameworksBuildPhase; 389 | buildActionMask = 2147483647; 390 | files = ( 391 | DA54728319FC2B5C00332193 /* Nimble.framework in Frameworks */, 392 | 5A5D118719473F2100F6D13D /* Quick.framework in Frameworks */, 393 | ); 394 | runOnlyForDeploymentPostprocessing = 0; 395 | }; 396 | DAEB6B8A1943873100289F44 /* Frameworks */ = { 397 | isa = PBXFrameworksBuildPhase; 398 | buildActionMask = 2147483647; 399 | files = ( 400 | AAACAAD919532C4E00B492A8 /* XCTest.framework in Frameworks */, 401 | ); 402 | runOnlyForDeploymentPostprocessing = 0; 403 | }; 404 | DAEB6B961943873100289F44 /* Frameworks */ = { 405 | isa = PBXFrameworksBuildPhase; 406 | buildActionMask = 2147483647; 407 | files = ( 408 | DA54728219FC2B5700332193 /* Nimble.framework in Frameworks */, 409 | DAEB6B9A1943873100289F44 /* Quick.framework in Frameworks */, 410 | ); 411 | runOnlyForDeploymentPostprocessing = 0; 412 | }; 413 | /* End PBXFrameworksBuildPhase section */ 414 | 415 | /* Begin PBXGroup section */ 416 | DA169E4619FF5DF100619816 /* Configuration */ = { 417 | isa = PBXGroup; 418 | children = ( 419 | DAE714FC19FF6A62005905B8 /* QuickConfiguration.h */, 420 | DAE714FD19FF6A62005905B8 /* QuickConfiguration.m */, 421 | DA169E4719FF5DF100619816 /* Configuration.swift */, 422 | ); 423 | path = Configuration; 424 | sourceTree = ""; 425 | }; 426 | DA3124E119FCAEE8002858A7 /* DSL */ = { 427 | isa = PBXGroup; 428 | children = ( 429 | DA3124E519FCAEE8002858A7 /* World+DSL.swift */, 430 | DA3124E219FCAEE8002858A7 /* DSL.swift */, 431 | DA3124E319FCAEE8002858A7 /* QCKDSL.h */, 432 | DA3124E419FCAEE8002858A7 /* QCKDSL.m */, 433 | ); 434 | path = DSL; 435 | sourceTree = ""; 436 | }; 437 | DA408BDE19FF5599005DF92A /* Hooks */ = { 438 | isa = PBXGroup; 439 | children = ( 440 | DA408BDF19FF5599005DF92A /* Closures.swift */, 441 | DA408BE019FF5599005DF92A /* ExampleHooks.swift */, 442 | DA408BE119FF5599005DF92A /* SuiteHooks.swift */, 443 | ); 444 | path = Hooks; 445 | sourceTree = ""; 446 | }; 447 | DA54727419FC2B4400332193 /* Products */ = { 448 | isa = PBXGroup; 449 | children = ( 450 | DA54727B19FC2B4400332193 /* Nimble.framework */, 451 | DA54727D19FC2B4400332193 /* NimbleTests.xctest */, 452 | DA54727F19FC2B4400332193 /* Nimble.framework */, 453 | DA54728119FC2B4400332193 /* Nimble-OSXTests.xctest */, 454 | ); 455 | name = Products; 456 | sourceTree = ""; 457 | }; 458 | DA8F919419F31680006F6675 /* Helpers */ = { 459 | isa = PBXGroup; 460 | children = ( 461 | DA8F919719F31680006F6675 /* QuickTestsBridgingHeader.h */, 462 | DA8F919519F31680006F6675 /* QCKSpecRunner.h */, 463 | DA8F919619F31680006F6675 /* QCKSpecRunner.m */, 464 | DA8F919819F31680006F6675 /* XCTestObservationCenter.h */, 465 | ); 466 | path = Helpers; 467 | sourceTree = ""; 468 | }; 469 | DA8F919B19F3189D006F6675 /* FunctionalTests */ = { 470 | isa = PBXGroup; 471 | children = ( 472 | DAE714E919FF65A6005905B8 /* Configuration */, 473 | DA7AE6F019FC493F000AFDCE /* ItTests.swift */, 474 | DA8F919C19F31921006F6675 /* FailureTests+ObjC.m */, 475 | DA87078219F48775008C04AC /* BeforeEachTests.swift */, 476 | DA05D60F19F73A3800771050 /* AfterEachTests.swift */, 477 | DAA63EA219F7637300CD0A3B /* PendingTests.swift */, 478 | DA8F91A419F3208B006F6675 /* BeforeSuiteTests.swift */, 479 | DA8F91A719F32556006F6675 /* AfterSuiteTests.swift */, 480 | DA8F91AA19F3299E006F6675 /* SharedExamplesTests.swift */, 481 | DAB0136E19FC4315006AFBEE /* SharedExamples+BeforeEachTests.swift */, 482 | ); 483 | path = FunctionalTests; 484 | sourceTree = ""; 485 | }; 486 | DAE714E919FF65A6005905B8 /* Configuration */ = { 487 | isa = PBXGroup; 488 | children = ( 489 | DAE714F519FF67FF005905B8 /* AfterEach */, 490 | DAE714EA19FF65A6005905B8 /* BeforeEach */, 491 | ); 492 | path = Configuration; 493 | sourceTree = ""; 494 | }; 495 | DAE714EA19FF65A6005905B8 /* BeforeEach */ = { 496 | isa = PBXGroup; 497 | children = ( 498 | DAE714F219FF65E7005905B8 /* Configuration+BeforeEach.swift */, 499 | DAE714EF19FF65D3005905B8 /* Configuration+BeforeEachTests.swift */, 500 | ); 501 | path = BeforeEach; 502 | sourceTree = ""; 503 | }; 504 | DAE714F519FF67FF005905B8 /* AfterEach */ = { 505 | isa = PBXGroup; 506 | children = ( 507 | DAE714F619FF6812005905B8 /* Configuration+AfterEach.swift */, 508 | DAE714F919FF682A005905B8 /* Configuration+AfterEachTests.swift */, 509 | ); 510 | path = AfterEach; 511 | sourceTree = ""; 512 | }; 513 | DAEB6B841943873100289F44 = { 514 | isa = PBXGroup; 515 | children = ( 516 | DAEB6B901943873100289F44 /* Quick */, 517 | DAEB6B9D1943873100289F44 /* QuickTests */, 518 | DAEB6B8F1943873100289F44 /* Products */, 519 | AADBF9A819521298005E1714 /* XCTest.framework */, 520 | AADBF9A919521298005E1714 /* XCTest.framework */, 521 | ); 522 | sourceTree = ""; 523 | }; 524 | DAEB6B8F1943873100289F44 /* Products */ = { 525 | isa = PBXGroup; 526 | children = ( 527 | DAEB6B8E1943873100289F44 /* Quick.framework */, 528 | DAEB6B991943873100289F44 /* Quick-OSXTests.xctest */, 529 | 5A5D117C19473F2100F6D13D /* Quick.framework */, 530 | 5A5D118619473F2100F6D13D /* Quick-iOSTests.xctest */, 531 | ); 532 | name = Products; 533 | sourceTree = ""; 534 | }; 535 | DAEB6B901943873100289F44 /* Quick */ = { 536 | isa = PBXGroup; 537 | children = ( 538 | DA169E4619FF5DF100619816 /* Configuration */, 539 | DA3124E119FCAEE8002858A7 /* DSL */, 540 | DA408BDE19FF5599005DF92A /* Hooks */, 541 | DAEB6B931943873100289F44 /* Quick.h */, 542 | 34F375A619515CA700CE1B99 /* World.swift */, 543 | DAEE632919FF4EE30089F850 /* World+Singleton.swift */, 544 | 34F3759E19515CA700CE1B99 /* Example.swift */, 545 | DA02C91819A8073100093156 /* ExampleMetadata.swift */, 546 | 34F3759F19515CA700CE1B99 /* ExampleGroup.swift */, 547 | 34F3759C19515CA700CE1B99 /* Callsite.swift */, 548 | 5AFC5948195ED5B900D3E0A2 /* Failure.swift */, 549 | 34F375A419515CA700CE1B99 /* QuickSpec.h */, 550 | 34F375A519515CA700CE1B99 /* QuickSpec.m */, 551 | 34F375A019515CA700CE1B99 /* NSString+QCKSelectorName.h */, 552 | 34F375A119515CA700CE1B99 /* NSString+QCKSelectorName.m */, 553 | 5AFC595F195EEDA900D3E0A2 /* NSException+Callsite.swift */, 554 | DAEB6B911943873100289F44 /* Supporting Files */, 555 | ); 556 | path = Quick; 557 | sourceTree = ""; 558 | }; 559 | DAEB6B911943873100289F44 /* Supporting Files */ = { 560 | isa = PBXGroup; 561 | children = ( 562 | DAEB6B921943873100289F44 /* Info.plist */, 563 | ); 564 | name = "Supporting Files"; 565 | sourceTree = ""; 566 | }; 567 | DAEB6B9D1943873100289F44 /* QuickTests */ = { 568 | isa = PBXGroup; 569 | children = ( 570 | DA54727319FC2B4400332193 /* Nimble.xcodeproj */, 571 | DA8F919419F31680006F6675 /* Helpers */, 572 | DA8F919B19F3189D006F6675 /* FunctionalTests */, 573 | DAEB6BCB194387D700289F44 /* FunctionalTests.swift */, 574 | 34512A381948223C007D457A /* FunctionalTests+ObjC.m */, 575 | DAECD76219AC4039003EFF14 /* ExampleMetadataFunctionalTests.swift */, 576 | DA8C00201A01E4B900CE58A6 /* QuickConfigurationTests.m */, 577 | DAEB6BCD194387D700289F44 /* Fixtures */, 578 | DAEB6B9E1943873100289F44 /* Supporting Files */, 579 | ); 580 | path = QuickTests; 581 | sourceTree = ""; 582 | }; 583 | DAEB6B9E1943873100289F44 /* Supporting Files */ = { 584 | isa = PBXGroup; 585 | children = ( 586 | DAEB6B9F1943873100289F44 /* Info.plist */, 587 | ); 588 | name = "Supporting Files"; 589 | sourceTree = ""; 590 | }; 591 | DAEB6BCD194387D700289F44 /* Fixtures */ = { 592 | isa = PBXGroup; 593 | children = ( 594 | DAEB6BCE194387D700289F44 /* Person.swift */, 595 | DAEB6BCF194387D700289F44 /* Poet.swift */, 596 | DA8F91AD19F32CE2006F6675 /* FunctionalTests_SharedExamplesTests_SharedExamples.swift */, 597 | ); 598 | path = Fixtures; 599 | sourceTree = ""; 600 | }; 601 | /* End PBXGroup section */ 602 | 603 | /* Begin PBXHeadersBuildPhase section */ 604 | 5A5D117919473F2100F6D13D /* Headers */ = { 605 | isa = PBXHeadersBuildPhase; 606 | buildActionMask = 2147483647; 607 | files = ( 608 | 34F375B019515CA700CE1B99 /* NSString+QCKSelectorName.h in Headers */, 609 | DAE714FF19FF6A62005905B8 /* QuickConfiguration.h in Headers */, 610 | DA3124E919FCAEE8002858A7 /* QCKDSL.h in Headers */, 611 | 34F375B819515CA700CE1B99 /* QuickSpec.h in Headers */, 612 | 5A5D11A7194740E000F6D13D /* Quick.h in Headers */, 613 | ); 614 | runOnlyForDeploymentPostprocessing = 0; 615 | }; 616 | DAEB6B8B1943873100289F44 /* Headers */ = { 617 | isa = PBXHeadersBuildPhase; 618 | buildActionMask = 2147483647; 619 | files = ( 620 | 34F375AF19515CA700CE1B99 /* NSString+QCKSelectorName.h in Headers */, 621 | DAE714FE19FF6A62005905B8 /* QuickConfiguration.h in Headers */, 622 | DA3124E819FCAEE8002858A7 /* QCKDSL.h in Headers */, 623 | 34F375B719515CA700CE1B99 /* QuickSpec.h in Headers */, 624 | DAEB6B941943873100289F44 /* Quick.h in Headers */, 625 | ); 626 | runOnlyForDeploymentPostprocessing = 0; 627 | }; 628 | /* End PBXHeadersBuildPhase section */ 629 | 630 | /* Begin PBXNativeTarget section */ 631 | 5A5D117B19473F2100F6D13D /* Quick-iOS */ = { 632 | isa = PBXNativeTarget; 633 | buildConfigurationList = 5A5D119319473F2100F6D13D /* Build configuration list for PBXNativeTarget "Quick-iOS" */; 634 | buildPhases = ( 635 | 5A5D117719473F2100F6D13D /* Sources */, 636 | 5A5D117819473F2100F6D13D /* Frameworks */, 637 | 5A5D117919473F2100F6D13D /* Headers */, 638 | 5A5D117A19473F2100F6D13D /* Resources */, 639 | ); 640 | buildRules = ( 641 | ); 642 | dependencies = ( 643 | ); 644 | name = "Quick-iOS"; 645 | productName = "Quick-iOS"; 646 | productReference = 5A5D117C19473F2100F6D13D /* Quick.framework */; 647 | productType = "com.apple.product-type.framework"; 648 | }; 649 | 5A5D118519473F2100F6D13D /* Quick-iOSTests */ = { 650 | isa = PBXNativeTarget; 651 | buildConfigurationList = 5A5D119419473F2100F6D13D /* Build configuration list for PBXNativeTarget "Quick-iOSTests" */; 652 | buildPhases = ( 653 | 5A5D118219473F2100F6D13D /* Sources */, 654 | 5A5D118319473F2100F6D13D /* Frameworks */, 655 | 5A5D118419473F2100F6D13D /* Resources */, 656 | ); 657 | buildRules = ( 658 | ); 659 | dependencies = ( 660 | 1F5F97911A06DA4500C684A1 /* PBXTargetDependency */, 661 | 5A5D118919473F2100F6D13D /* PBXTargetDependency */, 662 | 5A5D11F0194741B500F6D13D /* PBXTargetDependency */, 663 | 5A5D11F2194741B500F6D13D /* PBXTargetDependency */, 664 | 04DC97E9194B4B7E00CE00B6 /* PBXTargetDependency */, 665 | 04DC97EB194B4B9B00CE00B6 /* PBXTargetDependency */, 666 | 04DC97F3194B82DE00CE00B6 /* PBXTargetDependency */, 667 | 04DC97F7194B831200CE00B6 /* PBXTargetDependency */, 668 | 04DC97FB194B834100CE00B6 /* PBXTargetDependency */, 669 | 04DC97FF194B835E00CE00B6 /* PBXTargetDependency */, 670 | 04DC9803194B836300CE00B6 /* PBXTargetDependency */, 671 | 04DC9807194B838700CE00B6 /* PBXTargetDependency */, 672 | ); 673 | name = "Quick-iOSTests"; 674 | productName = "Quick-iOSTests"; 675 | productReference = 5A5D118619473F2100F6D13D /* Quick-iOSTests.xctest */; 676 | productType = "com.apple.product-type.bundle.unit-test"; 677 | }; 678 | DAEB6B8D1943873100289F44 /* Quick-OSX */ = { 679 | isa = PBXNativeTarget; 680 | buildConfigurationList = DAEB6BA41943873200289F44 /* Build configuration list for PBXNativeTarget "Quick-OSX" */; 681 | buildPhases = ( 682 | DAEB6B891943873100289F44 /* Sources */, 683 | DAEB6B8A1943873100289F44 /* Frameworks */, 684 | DAEB6B8B1943873100289F44 /* Headers */, 685 | DAEB6B8C1943873100289F44 /* Resources */, 686 | ); 687 | buildRules = ( 688 | ); 689 | dependencies = ( 690 | ); 691 | name = "Quick-OSX"; 692 | productName = Quick; 693 | productReference = DAEB6B8E1943873100289F44 /* Quick.framework */; 694 | productType = "com.apple.product-type.framework"; 695 | }; 696 | DAEB6B981943873100289F44 /* Quick-OSXTests */ = { 697 | isa = PBXNativeTarget; 698 | buildConfigurationList = DAEB6BA71943873200289F44 /* Build configuration list for PBXNativeTarget "Quick-OSXTests" */; 699 | buildPhases = ( 700 | DAEB6B951943873100289F44 /* Sources */, 701 | DAEB6B961943873100289F44 /* Frameworks */, 702 | DAEB6B971943873100289F44 /* Resources */, 703 | ); 704 | buildRules = ( 705 | ); 706 | dependencies = ( 707 | 1F5F97971A06DA4D00C684A1 /* PBXTargetDependency */, 708 | DAEB6B9C1943873100289F44 /* PBXTargetDependency */, 709 | 047655521949F4CB00B288BB /* PBXTargetDependency */, 710 | 047655541949F4CB00B288BB /* PBXTargetDependency */, 711 | 04765556194A327000B288BB /* PBXTargetDependency */, 712 | 04DC97E5194B4A6000CE00B6 /* PBXTargetDependency */, 713 | 04DC97E7194B4A6000CE00B6 /* PBXTargetDependency */, 714 | 04DC97F1194B82DB00CE00B6 /* PBXTargetDependency */, 715 | 04DC97F9194B834000CE00B6 /* PBXTargetDependency */, 716 | 04DC97FD194B834B00CE00B6 /* PBXTargetDependency */, 717 | 04DC9801194B836100CE00B6 /* PBXTargetDependency */, 718 | 04DC9805194B838400CE00B6 /* PBXTargetDependency */, 719 | 04DC9809194B838B00CE00B6 /* PBXTargetDependency */, 720 | 93625F391951DDC8006B1FE1 /* PBXTargetDependency */, 721 | ); 722 | name = "Quick-OSXTests"; 723 | productName = QuickTests; 724 | productReference = DAEB6B991943873100289F44 /* Quick-OSXTests.xctest */; 725 | productType = "com.apple.product-type.bundle.unit-test"; 726 | }; 727 | /* End PBXNativeTarget section */ 728 | 729 | /* Begin PBXProject section */ 730 | DAEB6B851943873100289F44 /* Project object */ = { 731 | isa = PBXProject; 732 | attributes = { 733 | LastUpgradeCheck = 0600; 734 | ORGANIZATIONNAME = "Brian Ivan Gesiak"; 735 | TargetAttributes = { 736 | 5A5D117B19473F2100F6D13D = { 737 | CreatedOnToolsVersion = 6.0; 738 | }; 739 | 5A5D118519473F2100F6D13D = { 740 | CreatedOnToolsVersion = 6.0; 741 | TestTargetID = 5A5D117B19473F2100F6D13D; 742 | }; 743 | DAEB6B8D1943873100289F44 = { 744 | CreatedOnToolsVersion = 6.0; 745 | }; 746 | DAEB6B981943873100289F44 = { 747 | CreatedOnToolsVersion = 6.0; 748 | TestTargetID = DAEB6B8D1943873100289F44; 749 | }; 750 | }; 751 | }; 752 | buildConfigurationList = DAEB6B881943873100289F44 /* Build configuration list for PBXProject "Quick" */; 753 | compatibilityVersion = "Xcode 3.2"; 754 | developmentRegion = English; 755 | hasScannedForEncodings = 0; 756 | knownRegions = ( 757 | en, 758 | ); 759 | mainGroup = DAEB6B841943873100289F44; 760 | productRefGroup = DAEB6B8F1943873100289F44 /* Products */; 761 | projectDirPath = ""; 762 | projectReferences = ( 763 | { 764 | ProductGroup = DA54727419FC2B4400332193 /* Products */; 765 | ProjectRef = DA54727319FC2B4400332193 /* Nimble.xcodeproj */; 766 | }, 767 | ); 768 | projectRoot = ""; 769 | targets = ( 770 | DAEB6B8D1943873100289F44 /* Quick-OSX */, 771 | DAEB6B981943873100289F44 /* Quick-OSXTests */, 772 | 5A5D117B19473F2100F6D13D /* Quick-iOS */, 773 | 5A5D118519473F2100F6D13D /* Quick-iOSTests */, 774 | ); 775 | }; 776 | /* End PBXProject section */ 777 | 778 | /* Begin PBXReferenceProxy section */ 779 | DA54727B19FC2B4400332193 /* Nimble.framework */ = { 780 | isa = PBXReferenceProxy; 781 | fileType = wrapper.framework; 782 | path = Nimble.framework; 783 | remoteRef = DA54727A19FC2B4400332193 /* PBXContainerItemProxy */; 784 | sourceTree = BUILT_PRODUCTS_DIR; 785 | }; 786 | DA54727D19FC2B4400332193 /* NimbleTests.xctest */ = { 787 | isa = PBXReferenceProxy; 788 | fileType = wrapper.cfbundle; 789 | path = NimbleTests.xctest; 790 | remoteRef = DA54727C19FC2B4400332193 /* PBXContainerItemProxy */; 791 | sourceTree = BUILT_PRODUCTS_DIR; 792 | }; 793 | DA54727F19FC2B4400332193 /* Nimble.framework */ = { 794 | isa = PBXReferenceProxy; 795 | fileType = wrapper.framework; 796 | path = Nimble.framework; 797 | remoteRef = DA54727E19FC2B4400332193 /* PBXContainerItemProxy */; 798 | sourceTree = BUILT_PRODUCTS_DIR; 799 | }; 800 | DA54728119FC2B4400332193 /* Nimble-OSXTests.xctest */ = { 801 | isa = PBXReferenceProxy; 802 | fileType = wrapper.cfbundle; 803 | path = "Nimble-OSXTests.xctest"; 804 | remoteRef = DA54728019FC2B4400332193 /* PBXContainerItemProxy */; 805 | sourceTree = BUILT_PRODUCTS_DIR; 806 | }; 807 | /* End PBXReferenceProxy section */ 808 | 809 | /* Begin PBXResourcesBuildPhase section */ 810 | 5A5D117A19473F2100F6D13D /* Resources */ = { 811 | isa = PBXResourcesBuildPhase; 812 | buildActionMask = 2147483647; 813 | files = ( 814 | ); 815 | runOnlyForDeploymentPostprocessing = 0; 816 | }; 817 | 5A5D118419473F2100F6D13D /* Resources */ = { 818 | isa = PBXResourcesBuildPhase; 819 | buildActionMask = 2147483647; 820 | files = ( 821 | ); 822 | runOnlyForDeploymentPostprocessing = 0; 823 | }; 824 | DAEB6B8C1943873100289F44 /* Resources */ = { 825 | isa = PBXResourcesBuildPhase; 826 | buildActionMask = 2147483647; 827 | files = ( 828 | ); 829 | runOnlyForDeploymentPostprocessing = 0; 830 | }; 831 | DAEB6B971943873100289F44 /* Resources */ = { 832 | isa = PBXResourcesBuildPhase; 833 | buildActionMask = 2147483647; 834 | files = ( 835 | ); 836 | runOnlyForDeploymentPostprocessing = 0; 837 | }; 838 | /* End PBXResourcesBuildPhase section */ 839 | 840 | /* Begin PBXSourcesBuildPhase section */ 841 | 5A5D117719473F2100F6D13D /* Sources */ = { 842 | isa = PBXSourcesBuildPhase; 843 | buildActionMask = 2147483647; 844 | files = ( 845 | 34F375B219515CA700CE1B99 /* NSString+QCKSelectorName.m in Sources */, 846 | DA3124EB19FCAEE8002858A7 /* QCKDSL.m in Sources */, 847 | DA408BE319FF5599005DF92A /* Closures.swift in Sources */, 848 | DA02C91A19A8073100093156 /* ExampleMetadata.swift in Sources */, 849 | 5AFC5961195EEDA900D3E0A2 /* NSException+Callsite.swift in Sources */, 850 | DA408BE719FF5599005DF92A /* SuiteHooks.swift in Sources */, 851 | 5AFC594A195ED5B900D3E0A2 /* Failure.swift in Sources */, 852 | 34F375BA19515CA700CE1B99 /* QuickSpec.m in Sources */, 853 | DAE7150119FF6A62005905B8 /* QuickConfiguration.m in Sources */, 854 | 34F375A819515CA700CE1B99 /* Callsite.swift in Sources */, 855 | DAEE632B19FF4EE30089F850 /* World+Singleton.swift in Sources */, 856 | 34F375AE19515CA700CE1B99 /* ExampleGroup.swift in Sources */, 857 | 34F375BC19515CA700CE1B99 /* World.swift in Sources */, 858 | DA169E4919FF5DF100619816 /* Configuration.swift in Sources */, 859 | DA3124ED19FCAEE8002858A7 /* World+DSL.swift in Sources */, 860 | DA408BE519FF5599005DF92A /* ExampleHooks.swift in Sources */, 861 | 34F375AC19515CA700CE1B99 /* Example.swift in Sources */, 862 | DA3124E719FCAEE8002858A7 /* DSL.swift in Sources */, 863 | ); 864 | runOnlyForDeploymentPostprocessing = 0; 865 | }; 866 | 5A5D118219473F2100F6D13D /* Sources */ = { 867 | isa = PBXSourcesBuildPhase; 868 | buildActionMask = 2147483647; 869 | files = ( 870 | DAE714F819FF6812005905B8 /* Configuration+AfterEach.swift in Sources */, 871 | DAA7C0D719F777EB0093D1D9 /* BeforeEachTests.swift in Sources */, 872 | DA8F919A19F31680006F6675 /* QCKSpecRunner.m in Sources */, 873 | DAE714F119FF65D3005905B8 /* Configuration+BeforeEachTests.swift in Sources */, 874 | DA05D61119F73A3800771050 /* AfterEachTests.swift in Sources */, 875 | DAB0137019FC4315006AFBEE /* SharedExamples+BeforeEachTests.swift in Sources */, 876 | DA8F91A619F3208B006F6675 /* BeforeSuiteTests.swift in Sources */, 877 | DA8C00221A01E4B900CE58A6 /* QuickConfigurationTests.m in Sources */, 878 | 34512A3A1948223C007D457A /* FunctionalTests+ObjC.m in Sources */, 879 | DAA63EA419F7637300CD0A3B /* PendingTests.swift in Sources */, 880 | DA8F91AC19F3299E006F6675 /* SharedExamplesTests.swift in Sources */, 881 | DA7AE6F219FC493F000AFDCE /* ItTests.swift in Sources */, 882 | 5A5D11AC1947412800F6D13D /* Person.swift in Sources */, 883 | DA8F91AF19F32CE2006F6675 /* FunctionalTests_SharedExamplesTests_SharedExamples.swift in Sources */, 884 | DAECD76419AC4039003EFF14 /* ExampleMetadataFunctionalTests.swift in Sources */, 885 | DAE714FB19FF682A005905B8 /* Configuration+AfterEachTests.swift in Sources */, 886 | DA8F919E19F31921006F6675 /* FailureTests+ObjC.m in Sources */, 887 | DAE714F419FF65E7005905B8 /* Configuration+BeforeEach.swift in Sources */, 888 | DA8F91A919F32556006F6675 /* AfterSuiteTests.swift in Sources */, 889 | 1F6BB86819693204009F1DBB /* FunctionalTests.swift in Sources */, 890 | 5A5D11AD1947412800F6D13D /* Poet.swift in Sources */, 891 | ); 892 | runOnlyForDeploymentPostprocessing = 0; 893 | }; 894 | DAEB6B891943873100289F44 /* Sources */ = { 895 | isa = PBXSourcesBuildPhase; 896 | buildActionMask = 2147483647; 897 | files = ( 898 | 34F375B119515CA700CE1B99 /* NSString+QCKSelectorName.m in Sources */, 899 | DA3124EA19FCAEE8002858A7 /* QCKDSL.m in Sources */, 900 | DA408BE219FF5599005DF92A /* Closures.swift in Sources */, 901 | DA02C91919A8073100093156 /* ExampleMetadata.swift in Sources */, 902 | 5AFC5960195EEDA900D3E0A2 /* NSException+Callsite.swift in Sources */, 903 | DA408BE619FF5599005DF92A /* SuiteHooks.swift in Sources */, 904 | 5AFC5949195ED5B900D3E0A2 /* Failure.swift in Sources */, 905 | 34F375B919515CA700CE1B99 /* QuickSpec.m in Sources */, 906 | DAE7150019FF6A62005905B8 /* QuickConfiguration.m in Sources */, 907 | 34F375A719515CA700CE1B99 /* Callsite.swift in Sources */, 908 | DAEE632A19FF4EE30089F850 /* World+Singleton.swift in Sources */, 909 | 34F375AD19515CA700CE1B99 /* ExampleGroup.swift in Sources */, 910 | 34F375BB19515CA700CE1B99 /* World.swift in Sources */, 911 | DA169E4819FF5DF100619816 /* Configuration.swift in Sources */, 912 | DA3124EC19FCAEE8002858A7 /* World+DSL.swift in Sources */, 913 | DA408BE419FF5599005DF92A /* ExampleHooks.swift in Sources */, 914 | 34F375AB19515CA700CE1B99 /* Example.swift in Sources */, 915 | DA3124E619FCAEE8002858A7 /* DSL.swift in Sources */, 916 | ); 917 | runOnlyForDeploymentPostprocessing = 0; 918 | }; 919 | DAEB6B951943873100289F44 /* Sources */ = { 920 | isa = PBXSourcesBuildPhase; 921 | buildActionMask = 2147483647; 922 | files = ( 923 | DAE714F719FF6812005905B8 /* Configuration+AfterEach.swift in Sources */, 924 | DAB067E919F7801C00F970AC /* BeforeEachTests.swift in Sources */, 925 | DA8F919919F31680006F6675 /* QCKSpecRunner.m in Sources */, 926 | DAE714F019FF65D3005905B8 /* Configuration+BeforeEachTests.swift in Sources */, 927 | DA05D61019F73A3800771050 /* AfterEachTests.swift in Sources */, 928 | DAB0136F19FC4315006AFBEE /* SharedExamples+BeforeEachTests.swift in Sources */, 929 | DA8F91A519F3208B006F6675 /* BeforeSuiteTests.swift in Sources */, 930 | DA8C00211A01E4B900CE58A6 /* QuickConfigurationTests.m in Sources */, 931 | 34512A391948223C007D457A /* FunctionalTests+ObjC.m in Sources */, 932 | DAA63EA319F7637300CD0A3B /* PendingTests.swift in Sources */, 933 | DA8F91AB19F3299E006F6675 /* SharedExamplesTests.swift in Sources */, 934 | DA7AE6F119FC493F000AFDCE /* ItTests.swift in Sources */, 935 | DAEB6BD4194387D700289F44 /* Person.swift in Sources */, 936 | DA8F91AE19F32CE2006F6675 /* FunctionalTests_SharedExamplesTests_SharedExamples.swift in Sources */, 937 | DAECD76319AC4039003EFF14 /* ExampleMetadataFunctionalTests.swift in Sources */, 938 | DAE714FA19FF682A005905B8 /* Configuration+AfterEachTests.swift in Sources */, 939 | DA8F919D19F31921006F6675 /* FailureTests+ObjC.m in Sources */, 940 | DAE714F319FF65E7005905B8 /* Configuration+BeforeEach.swift in Sources */, 941 | DA8F91A819F32556006F6675 /* AfterSuiteTests.swift in Sources */, 942 | 1F6BB86A1969BF75009F1DBB /* FunctionalTests.swift in Sources */, 943 | DAEB6BD5194387D700289F44 /* Poet.swift in Sources */, 944 | ); 945 | runOnlyForDeploymentPostprocessing = 0; 946 | }; 947 | /* End PBXSourcesBuildPhase section */ 948 | 949 | /* Begin PBXTargetDependency section */ 950 | 047655521949F4CB00B288BB /* PBXTargetDependency */ = { 951 | isa = PBXTargetDependency; 952 | target = DAEB6B8D1943873100289F44 /* Quick-OSX */; 953 | targetProxy = 047655511949F4CB00B288BB /* PBXContainerItemProxy */; 954 | }; 955 | 047655541949F4CB00B288BB /* PBXTargetDependency */ = { 956 | isa = PBXTargetDependency; 957 | target = DAEB6B8D1943873100289F44 /* Quick-OSX */; 958 | targetProxy = 047655531949F4CB00B288BB /* PBXContainerItemProxy */; 959 | }; 960 | 04765556194A327000B288BB /* PBXTargetDependency */ = { 961 | isa = PBXTargetDependency; 962 | target = DAEB6B8D1943873100289F44 /* Quick-OSX */; 963 | targetProxy = 04765555194A327000B288BB /* PBXContainerItemProxy */; 964 | }; 965 | 04DC97E5194B4A6000CE00B6 /* PBXTargetDependency */ = { 966 | isa = PBXTargetDependency; 967 | target = DAEB6B8D1943873100289F44 /* Quick-OSX */; 968 | targetProxy = 04DC97E4194B4A6000CE00B6 /* PBXContainerItemProxy */; 969 | }; 970 | 04DC97E7194B4A6000CE00B6 /* PBXTargetDependency */ = { 971 | isa = PBXTargetDependency; 972 | target = DAEB6B8D1943873100289F44 /* Quick-OSX */; 973 | targetProxy = 04DC97E6194B4A6000CE00B6 /* PBXContainerItemProxy */; 974 | }; 975 | 04DC97E9194B4B7E00CE00B6 /* PBXTargetDependency */ = { 976 | isa = PBXTargetDependency; 977 | target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; 978 | targetProxy = 04DC97E8194B4B7E00CE00B6 /* PBXContainerItemProxy */; 979 | }; 980 | 04DC97EB194B4B9B00CE00B6 /* PBXTargetDependency */ = { 981 | isa = PBXTargetDependency; 982 | target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; 983 | targetProxy = 04DC97EA194B4B9B00CE00B6 /* PBXContainerItemProxy */; 984 | }; 985 | 04DC97F1194B82DB00CE00B6 /* PBXTargetDependency */ = { 986 | isa = PBXTargetDependency; 987 | target = DAEB6B8D1943873100289F44 /* Quick-OSX */; 988 | targetProxy = 04DC97F0194B82DB00CE00B6 /* PBXContainerItemProxy */; 989 | }; 990 | 04DC97F3194B82DE00CE00B6 /* PBXTargetDependency */ = { 991 | isa = PBXTargetDependency; 992 | target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; 993 | targetProxy = 04DC97F2194B82DE00CE00B6 /* PBXContainerItemProxy */; 994 | }; 995 | 04DC97F7194B831200CE00B6 /* PBXTargetDependency */ = { 996 | isa = PBXTargetDependency; 997 | target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; 998 | targetProxy = 04DC97F6194B831200CE00B6 /* PBXContainerItemProxy */; 999 | }; 1000 | 04DC97F9194B834000CE00B6 /* PBXTargetDependency */ = { 1001 | isa = PBXTargetDependency; 1002 | target = DAEB6B8D1943873100289F44 /* Quick-OSX */; 1003 | targetProxy = 04DC97F8194B834000CE00B6 /* PBXContainerItemProxy */; 1004 | }; 1005 | 04DC97FB194B834100CE00B6 /* PBXTargetDependency */ = { 1006 | isa = PBXTargetDependency; 1007 | target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; 1008 | targetProxy = 04DC97FA194B834100CE00B6 /* PBXContainerItemProxy */; 1009 | }; 1010 | 04DC97FD194B834B00CE00B6 /* PBXTargetDependency */ = { 1011 | isa = PBXTargetDependency; 1012 | target = DAEB6B8D1943873100289F44 /* Quick-OSX */; 1013 | targetProxy = 04DC97FC194B834B00CE00B6 /* PBXContainerItemProxy */; 1014 | }; 1015 | 04DC97FF194B835E00CE00B6 /* PBXTargetDependency */ = { 1016 | isa = PBXTargetDependency; 1017 | target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; 1018 | targetProxy = 04DC97FE194B835E00CE00B6 /* PBXContainerItemProxy */; 1019 | }; 1020 | 04DC9801194B836100CE00B6 /* PBXTargetDependency */ = { 1021 | isa = PBXTargetDependency; 1022 | target = DAEB6B8D1943873100289F44 /* Quick-OSX */; 1023 | targetProxy = 04DC9800194B836100CE00B6 /* PBXContainerItemProxy */; 1024 | }; 1025 | 04DC9803194B836300CE00B6 /* PBXTargetDependency */ = { 1026 | isa = PBXTargetDependency; 1027 | target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; 1028 | targetProxy = 04DC9802194B836300CE00B6 /* PBXContainerItemProxy */; 1029 | }; 1030 | 04DC9805194B838400CE00B6 /* PBXTargetDependency */ = { 1031 | isa = PBXTargetDependency; 1032 | target = DAEB6B8D1943873100289F44 /* Quick-OSX */; 1033 | targetProxy = 04DC9804194B838400CE00B6 /* PBXContainerItemProxy */; 1034 | }; 1035 | 04DC9807194B838700CE00B6 /* PBXTargetDependency */ = { 1036 | isa = PBXTargetDependency; 1037 | target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; 1038 | targetProxy = 04DC9806194B838700CE00B6 /* PBXContainerItemProxy */; 1039 | }; 1040 | 04DC9809194B838B00CE00B6 /* PBXTargetDependency */ = { 1041 | isa = PBXTargetDependency; 1042 | target = DAEB6B8D1943873100289F44 /* Quick-OSX */; 1043 | targetProxy = 04DC9808194B838B00CE00B6 /* PBXContainerItemProxy */; 1044 | }; 1045 | 1F5F97911A06DA4500C684A1 /* PBXTargetDependency */ = { 1046 | isa = PBXTargetDependency; 1047 | name = "Nimble-iOS"; 1048 | targetProxy = 1F5F97901A06DA4500C684A1 /* PBXContainerItemProxy */; 1049 | }; 1050 | 1F5F97971A06DA4D00C684A1 /* PBXTargetDependency */ = { 1051 | isa = PBXTargetDependency; 1052 | name = "Nimble-OSX"; 1053 | targetProxy = 1F5F97961A06DA4D00C684A1 /* PBXContainerItemProxy */; 1054 | }; 1055 | 5A5D118919473F2100F6D13D /* PBXTargetDependency */ = { 1056 | isa = PBXTargetDependency; 1057 | target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; 1058 | targetProxy = 5A5D118819473F2100F6D13D /* PBXContainerItemProxy */; 1059 | }; 1060 | 5A5D11F0194741B500F6D13D /* PBXTargetDependency */ = { 1061 | isa = PBXTargetDependency; 1062 | target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; 1063 | targetProxy = 5A5D11EF194741B500F6D13D /* PBXContainerItemProxy */; 1064 | }; 1065 | 5A5D11F2194741B500F6D13D /* PBXTargetDependency */ = { 1066 | isa = PBXTargetDependency; 1067 | target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; 1068 | targetProxy = 5A5D11F1194741B500F6D13D /* PBXContainerItemProxy */; 1069 | }; 1070 | 93625F391951DDC8006B1FE1 /* PBXTargetDependency */ = { 1071 | isa = PBXTargetDependency; 1072 | target = DAEB6B8D1943873100289F44 /* Quick-OSX */; 1073 | targetProxy = 93625F381951DDC8006B1FE1 /* PBXContainerItemProxy */; 1074 | }; 1075 | DAEB6B9C1943873100289F44 /* PBXTargetDependency */ = { 1076 | isa = PBXTargetDependency; 1077 | target = DAEB6B8D1943873100289F44 /* Quick-OSX */; 1078 | targetProxy = DAEB6B9B1943873100289F44 /* PBXContainerItemProxy */; 1079 | }; 1080 | /* End PBXTargetDependency section */ 1081 | 1082 | /* Begin XCBuildConfiguration section */ 1083 | 5A5D118F19473F2100F6D13D /* Debug */ = { 1084 | isa = XCBuildConfiguration; 1085 | buildSettings = { 1086 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 1087 | DEFINES_MODULE = YES; 1088 | DYLIB_COMPATIBILITY_VERSION = 1; 1089 | DYLIB_CURRENT_VERSION = 1; 1090 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 1091 | FRAMEWORK_SEARCH_PATHS = ( 1092 | "$(PLATFORM_DIR)/Developer/Library/Frameworks", 1093 | "$(SDKROOT)/Developer/Library/Frameworks", 1094 | "$(inherited)", 1095 | "$(DEVELOPER_FRAMEWORKS_DIR)", 1096 | "$(DEVELOPER_DIR)/Platforms/iPhoneSimulator.platform/Developer/Library/Frameworks", 1097 | ); 1098 | GCC_PREPROCESSOR_DEFINITIONS = ( 1099 | "DEBUG=1", 1100 | "$(inherited)", 1101 | ); 1102 | INFOPLIST_FILE = Quick/Info.plist; 1103 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 1104 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 1105 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 1106 | METAL_ENABLE_DEBUG_INFO = YES; 1107 | ONLY_ACTIVE_ARCH = NO; 1108 | PRODUCT_MODULE_NAME = Quick; 1109 | PRODUCT_NAME = Quick; 1110 | SDKROOT = iphoneos; 1111 | SKIP_INSTALL = YES; 1112 | TARGETED_DEVICE_FAMILY = "1,2"; 1113 | }; 1114 | name = Debug; 1115 | }; 1116 | 5A5D119019473F2100F6D13D /* Release */ = { 1117 | isa = XCBuildConfiguration; 1118 | buildSettings = { 1119 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 1120 | DEFINES_MODULE = YES; 1121 | DYLIB_COMPATIBILITY_VERSION = 1; 1122 | DYLIB_CURRENT_VERSION = 1; 1123 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 1124 | FRAMEWORK_SEARCH_PATHS = ( 1125 | "$(PLATFORM_DIR)/Developer/Library/Frameworks", 1126 | "$(SDKROOT)/Developer/Library/Frameworks", 1127 | "$(inherited)", 1128 | "$(DEVELOPER_FRAMEWORKS_DIR)", 1129 | "$(DEVELOPER_DIR)/Platforms/iPhoneSimulator.platform/Developer/Library/Frameworks", 1130 | ); 1131 | INFOPLIST_FILE = Quick/Info.plist; 1132 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 1133 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 1134 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 1135 | METAL_ENABLE_DEBUG_INFO = NO; 1136 | PRODUCT_MODULE_NAME = Quick; 1137 | PRODUCT_NAME = Quick; 1138 | SDKROOT = iphoneos; 1139 | SKIP_INSTALL = YES; 1140 | TARGETED_DEVICE_FAMILY = "1,2"; 1141 | VALIDATE_PRODUCT = YES; 1142 | }; 1143 | name = Release; 1144 | }; 1145 | 5A5D119119473F2100F6D13D /* Debug */ = { 1146 | isa = XCBuildConfiguration; 1147 | buildSettings = { 1148 | CLANG_ENABLE_MODULES = YES; 1149 | FRAMEWORK_SEARCH_PATHS = ( 1150 | "$(SDKROOT)/Developer/Library/Frameworks", 1151 | "$(inherited)", 1152 | ); 1153 | GCC_PREPROCESSOR_DEFINITIONS = ( 1154 | "DEBUG=1", 1155 | "$(inherited)", 1156 | ); 1157 | INFOPLIST_FILE = QuickTests/Info.plist; 1158 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 1159 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 1160 | METAL_ENABLE_DEBUG_INFO = YES; 1161 | PRODUCT_NAME = "$(TARGET_NAME)"; 1162 | SDKROOT = iphoneos; 1163 | SWIFT_OBJC_BRIDGING_HEADER = QuickTests/Helpers/QuickTestsBridgingHeader.h; 1164 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 1165 | }; 1166 | name = Debug; 1167 | }; 1168 | 5A5D119219473F2100F6D13D /* Release */ = { 1169 | isa = XCBuildConfiguration; 1170 | buildSettings = { 1171 | CLANG_ENABLE_MODULES = YES; 1172 | FRAMEWORK_SEARCH_PATHS = ( 1173 | "$(SDKROOT)/Developer/Library/Frameworks", 1174 | "$(inherited)", 1175 | ); 1176 | INFOPLIST_FILE = QuickTests/Info.plist; 1177 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 1178 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 1179 | METAL_ENABLE_DEBUG_INFO = NO; 1180 | PRODUCT_NAME = "$(TARGET_NAME)"; 1181 | SDKROOT = iphoneos; 1182 | SWIFT_OBJC_BRIDGING_HEADER = QuickTests/Helpers/QuickTestsBridgingHeader.h; 1183 | VALIDATE_PRODUCT = YES; 1184 | }; 1185 | name = Release; 1186 | }; 1187 | DAEB6BA21943873200289F44 /* Debug */ = { 1188 | isa = XCBuildConfiguration; 1189 | buildSettings = { 1190 | ALWAYS_SEARCH_USER_PATHS = NO; 1191 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 1192 | CLANG_CXX_LIBRARY = "libc++"; 1193 | CLANG_ENABLE_MODULES = YES; 1194 | CLANG_ENABLE_OBJC_ARC = YES; 1195 | CLANG_WARN_BOOL_CONVERSION = YES; 1196 | CLANG_WARN_CONSTANT_CONVERSION = YES; 1197 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 1198 | CLANG_WARN_EMPTY_BODY = YES; 1199 | CLANG_WARN_ENUM_CONVERSION = YES; 1200 | CLANG_WARN_INT_CONVERSION = YES; 1201 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 1202 | CLANG_WARN_UNREACHABLE_CODE = YES; 1203 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 1204 | COPY_PHASE_STRIP = NO; 1205 | CURRENT_PROJECT_VERSION = 1; 1206 | ENABLE_STRICT_OBJC_MSGSEND = YES; 1207 | GCC_C_LANGUAGE_STANDARD = gnu99; 1208 | GCC_DYNAMIC_NO_PIC = NO; 1209 | GCC_OPTIMIZATION_LEVEL = 0; 1210 | GCC_PREPROCESSOR_DEFINITIONS = ( 1211 | "DEBUG=1", 1212 | "$(inherited)", 1213 | ); 1214 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 1215 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 1216 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 1217 | GCC_WARN_UNDECLARED_SELECTOR = YES; 1218 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 1219 | GCC_WARN_UNUSED_FUNCTION = YES; 1220 | GCC_WARN_UNUSED_VARIABLE = YES; 1221 | MACOSX_DEPLOYMENT_TARGET = 10.9; 1222 | METAL_ENABLE_DEBUG_INFO = YES; 1223 | ONLY_ACTIVE_ARCH = YES; 1224 | SDKROOT = macosx; 1225 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 1226 | VERSIONING_SYSTEM = "apple-generic"; 1227 | VERSION_INFO_PREFIX = ""; 1228 | }; 1229 | name = Debug; 1230 | }; 1231 | DAEB6BA31943873200289F44 /* Release */ = { 1232 | isa = XCBuildConfiguration; 1233 | buildSettings = { 1234 | ALWAYS_SEARCH_USER_PATHS = NO; 1235 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 1236 | CLANG_CXX_LIBRARY = "libc++"; 1237 | CLANG_ENABLE_MODULES = YES; 1238 | CLANG_ENABLE_OBJC_ARC = YES; 1239 | CLANG_WARN_BOOL_CONVERSION = YES; 1240 | CLANG_WARN_CONSTANT_CONVERSION = YES; 1241 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 1242 | CLANG_WARN_EMPTY_BODY = YES; 1243 | CLANG_WARN_ENUM_CONVERSION = YES; 1244 | CLANG_WARN_INT_CONVERSION = YES; 1245 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 1246 | CLANG_WARN_UNREACHABLE_CODE = YES; 1247 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 1248 | COPY_PHASE_STRIP = YES; 1249 | CURRENT_PROJECT_VERSION = 1; 1250 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 1251 | ENABLE_NS_ASSERTIONS = NO; 1252 | ENABLE_STRICT_OBJC_MSGSEND = YES; 1253 | GCC_C_LANGUAGE_STANDARD = gnu99; 1254 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 1255 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 1256 | GCC_WARN_UNDECLARED_SELECTOR = YES; 1257 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 1258 | GCC_WARN_UNUSED_FUNCTION = YES; 1259 | GCC_WARN_UNUSED_VARIABLE = YES; 1260 | MACOSX_DEPLOYMENT_TARGET = 10.9; 1261 | METAL_ENABLE_DEBUG_INFO = NO; 1262 | SDKROOT = macosx; 1263 | VERSIONING_SYSTEM = "apple-generic"; 1264 | VERSION_INFO_PREFIX = ""; 1265 | }; 1266 | name = Release; 1267 | }; 1268 | DAEB6BA51943873200289F44 /* Debug */ = { 1269 | isa = XCBuildConfiguration; 1270 | buildSettings = { 1271 | COMBINE_HIDPI_IMAGES = YES; 1272 | DEFINES_MODULE = YES; 1273 | DYLIB_COMPATIBILITY_VERSION = 1; 1274 | DYLIB_CURRENT_VERSION = 1; 1275 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 1276 | FRAMEWORK_SEARCH_PATHS = ( 1277 | "$(inherited)", 1278 | "$(DEVELOPER_FRAMEWORKS_DIR)", 1279 | "$(DEVELOPER_DIR)/Platforms/MacOSX.platform/Developer/Library/Frameworks", 1280 | ); 1281 | FRAMEWORK_VERSION = A; 1282 | INFOPLIST_FILE = Quick/Info.plist; 1283 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 1284 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 1285 | PRODUCT_MODULE_NAME = Quick; 1286 | PRODUCT_NAME = Quick; 1287 | SKIP_INSTALL = YES; 1288 | VALID_ARCHS = x86_64; 1289 | }; 1290 | name = Debug; 1291 | }; 1292 | DAEB6BA61943873200289F44 /* Release */ = { 1293 | isa = XCBuildConfiguration; 1294 | buildSettings = { 1295 | COMBINE_HIDPI_IMAGES = YES; 1296 | DEFINES_MODULE = YES; 1297 | DYLIB_COMPATIBILITY_VERSION = 1; 1298 | DYLIB_CURRENT_VERSION = 1; 1299 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 1300 | FRAMEWORK_SEARCH_PATHS = ( 1301 | "$(inherited)", 1302 | "$(DEVELOPER_FRAMEWORKS_DIR)", 1303 | "$(DEVELOPER_DIR)/Platforms/MacOSX.platform/Developer/Library/Frameworks", 1304 | ); 1305 | FRAMEWORK_VERSION = A; 1306 | INFOPLIST_FILE = Quick/Info.plist; 1307 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 1308 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 1309 | PRODUCT_MODULE_NAME = Quick; 1310 | PRODUCT_NAME = Quick; 1311 | SKIP_INSTALL = YES; 1312 | VALID_ARCHS = x86_64; 1313 | }; 1314 | name = Release; 1315 | }; 1316 | DAEB6BA81943873200289F44 /* Debug */ = { 1317 | isa = XCBuildConfiguration; 1318 | buildSettings = { 1319 | CLANG_ENABLE_MODULES = YES; 1320 | COMBINE_HIDPI_IMAGES = YES; 1321 | FRAMEWORK_SEARCH_PATHS = ( 1322 | "$(DEVELOPER_FRAMEWORKS_DIR)", 1323 | "$(inherited)", 1324 | ); 1325 | GCC_PREPROCESSOR_DEFINITIONS = ( 1326 | "DEBUG=1", 1327 | "$(inherited)", 1328 | ); 1329 | INFOPLIST_FILE = QuickTests/Info.plist; 1330 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 1331 | METAL_ENABLE_DEBUG_INFO = YES; 1332 | PRODUCT_NAME = "$(TARGET_NAME)"; 1333 | SWIFT_OBJC_BRIDGING_HEADER = QuickTests/Helpers/QuickTestsBridgingHeader.h; 1334 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 1335 | }; 1336 | name = Debug; 1337 | }; 1338 | DAEB6BA91943873200289F44 /* Release */ = { 1339 | isa = XCBuildConfiguration; 1340 | buildSettings = { 1341 | CLANG_ENABLE_MODULES = YES; 1342 | COMBINE_HIDPI_IMAGES = YES; 1343 | FRAMEWORK_SEARCH_PATHS = ( 1344 | "$(DEVELOPER_FRAMEWORKS_DIR)", 1345 | "$(inherited)", 1346 | ); 1347 | INFOPLIST_FILE = QuickTests/Info.plist; 1348 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 1349 | METAL_ENABLE_DEBUG_INFO = NO; 1350 | PRODUCT_NAME = "$(TARGET_NAME)"; 1351 | SWIFT_OBJC_BRIDGING_HEADER = QuickTests/Helpers/QuickTestsBridgingHeader.h; 1352 | }; 1353 | name = Release; 1354 | }; 1355 | /* End XCBuildConfiguration section */ 1356 | 1357 | /* Begin XCConfigurationList section */ 1358 | 5A5D119319473F2100F6D13D /* Build configuration list for PBXNativeTarget "Quick-iOS" */ = { 1359 | isa = XCConfigurationList; 1360 | buildConfigurations = ( 1361 | 5A5D118F19473F2100F6D13D /* Debug */, 1362 | 5A5D119019473F2100F6D13D /* Release */, 1363 | ); 1364 | defaultConfigurationIsVisible = 0; 1365 | defaultConfigurationName = Release; 1366 | }; 1367 | 5A5D119419473F2100F6D13D /* Build configuration list for PBXNativeTarget "Quick-iOSTests" */ = { 1368 | isa = XCConfigurationList; 1369 | buildConfigurations = ( 1370 | 5A5D119119473F2100F6D13D /* Debug */, 1371 | 5A5D119219473F2100F6D13D /* Release */, 1372 | ); 1373 | defaultConfigurationIsVisible = 0; 1374 | defaultConfigurationName = Release; 1375 | }; 1376 | DAEB6B881943873100289F44 /* Build configuration list for PBXProject "Quick" */ = { 1377 | isa = XCConfigurationList; 1378 | buildConfigurations = ( 1379 | DAEB6BA21943873200289F44 /* Debug */, 1380 | DAEB6BA31943873200289F44 /* Release */, 1381 | ); 1382 | defaultConfigurationIsVisible = 0; 1383 | defaultConfigurationName = Release; 1384 | }; 1385 | DAEB6BA41943873200289F44 /* Build configuration list for PBXNativeTarget "Quick-OSX" */ = { 1386 | isa = XCConfigurationList; 1387 | buildConfigurations = ( 1388 | DAEB6BA51943873200289F44 /* Debug */, 1389 | DAEB6BA61943873200289F44 /* Release */, 1390 | ); 1391 | defaultConfigurationIsVisible = 0; 1392 | defaultConfigurationName = Release; 1393 | }; 1394 | DAEB6BA71943873200289F44 /* Build configuration list for PBXNativeTarget "Quick-OSXTests" */ = { 1395 | isa = XCConfigurationList; 1396 | buildConfigurations = ( 1397 | DAEB6BA81943873200289F44 /* Debug */, 1398 | DAEB6BA91943873200289F44 /* Release */, 1399 | ); 1400 | defaultConfigurationIsVisible = 0; 1401 | defaultConfigurationName = Release; 1402 | }; 1403 | /* End XCConfigurationList section */ 1404 | }; 1405 | rootObject = DAEB6B851943873100289F44 /* Project object */; 1406 | } 1407 | -------------------------------------------------------------------------------- /Quick.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Quick.xcodeproj/xcshareddata/xcschemes/Quick-OSX.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /Quick.xcodeproj/xcshareddata/xcschemes/Quick-iOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 61 | 62 | 68 | 69 | 70 | 71 | 72 | 73 | 79 | 80 | 86 | 87 | 88 | 89 | 91 | 92 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /Quick/Callsite.swift: -------------------------------------------------------------------------------- 1 | @objc public class Callsite { 2 | public let file: String 3 | public let line: Int 4 | 5 | init(file: String, line: Int) { 6 | self.file = file 7 | self.line = line 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Quick/Configuration/Configuration.swift: -------------------------------------------------------------------------------- 1 | /** 2 | A closure that temporarily exposes a Configuration object within 3 | the scope of the closure. 4 | */ 5 | public typealias QuickConfigurer = (configuration: Configuration) -> () 6 | 7 | /** 8 | A configuration encapsulates various options you can use 9 | to configure Quick's behavior. 10 | */ 11 | @objc public class Configuration { 12 | internal let exampleHooks = ExampleHooks() 13 | internal let suiteHooks = SuiteHooks() 14 | 15 | /** 16 | Identical to Quick.Configuration.beforeEach, except the closure is 17 | provided with metadata on the example that the closure is being run 18 | prior to. 19 | */ 20 | @objc(beforeEachWithMetadata:) 21 | public func beforeEach(closure: BeforeExampleWithMetadataClosure) { 22 | exampleHooks.appendBefore(closure) 23 | } 24 | 25 | /** 26 | Like Quick.DSL.beforeEach, this configures Quick to execute the 27 | given closure before each example that is run. The closure 28 | passed to this method is executed before each example Quick runs, 29 | globally across the test suite. You may call this method multiple 30 | times across mulitple +[QuickConfigure configure:] methods in order 31 | to define several closures to run before each example. 32 | 33 | Note that, since Quick makes no guarantee as to the order in which 34 | +[QuickConfiguration configure:] methods are evaluated, there is no 35 | guarantee as to the order in which beforeEach closures are evaluated 36 | either. Mulitple beforeEach defined on a single configuration, however, 37 | will be executed in the order they're defined. 38 | 39 | :param: closure The closure to be executed before each example 40 | in the test suite. 41 | */ 42 | public func beforeEach(closure: BeforeExampleClosure) { 43 | exampleHooks.appendBefore(closure) 44 | } 45 | 46 | /** 47 | Identical to Quick.Configuration.afterEach, except the closure 48 | is provided with metadata on the example that the closure is being 49 | run after. 50 | */ 51 | @objc(afterEachWithMetadata:) 52 | public func afterEach(closure: AfterExampleWithMetadataClosure) { 53 | exampleHooks.appendAfter(closure) 54 | } 55 | 56 | /** 57 | Like Quick.DSL.afterEach, this configures Quick to execute the 58 | given closure after each example that is run. The closure 59 | passed to this method is executed after each example Quick runs, 60 | globally across the test suite. You may call this method multiple 61 | times across mulitple +[QuickConfigure configure:] methods in order 62 | to define several closures to run after each example. 63 | 64 | Note that, since Quick makes no guarantee as to the order in which 65 | +[QuickConfiguration configure:] methods are evaluated, there is no 66 | guarantee as to the order in which afterEach closures are evaluated 67 | either. Mulitple afterEach defined on a single configuration, however, 68 | will be executed in the order they're defined. 69 | 70 | :param: closure The closure to be executed before each example 71 | in the test suite. 72 | */ 73 | public func afterEach(closure: AfterExampleClosure) { 74 | exampleHooks.appendAfter(closure) 75 | } 76 | 77 | /** 78 | Like Quick.DSL.beforeSuite, this configures Quick to execute 79 | the given closure prior to any and all examples that are run. 80 | The two methods are functionally equivalent. 81 | */ 82 | public func beforeSuite(closure: BeforeSuiteClosure) { 83 | suiteHooks.appendBefore(closure) 84 | } 85 | 86 | /** 87 | Like Quick.DSL.afterSuite, this configures Quick to execute 88 | the given closure after all examples have been run. 89 | The two methods are functionally equivalent. 90 | */ 91 | public func afterSuite(closure: AfterSuiteClosure) { 92 | suiteHooks.appendAfter(closure) 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /Quick/Configuration/QuickConfiguration.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @class Configuration; 4 | 5 | /** 6 | Subclass QuickConfiguration and override the +[QuickConfiguration configure:] 7 | method in order to configure how Quick behaves when running specs, or to define 8 | shared examples that are used across spec files. 9 | */ 10 | @interface QuickConfiguration : NSObject 11 | 12 | /** 13 | This method is executed on each subclass of this class before Quick runs 14 | any examples. You may override this method on as many subclasses as you like, but 15 | there is no guarantee as to the order in which these methods are executed. 16 | 17 | You can override this method in order to: 18 | 19 | 1. Configure how Quick behaves, by modifying properties on the Configuration object. 20 | Setting the same properties in several methods has undefined behavior. 21 | 22 | 2. Define shared examples using `sharedExamples`. 23 | 24 | @param configuration A mutable object that is used to configure how Quick behaves on 25 | a framework level. For details on all the options, see the 26 | documentation in Configuration.swift. 27 | */ 28 | + (void)configure:(Configuration *)configuration; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /Quick/Configuration/QuickConfiguration.m: -------------------------------------------------------------------------------- 1 | #import "QuickConfiguration.h" 2 | #import 3 | #import 4 | 5 | typedef void (^QCKClassEnumerationBlock)(Class klass); 6 | 7 | /** 8 | Finds all direct subclasses of the given class and passes them to the block provided. 9 | The classes are iterated over in the order that objc_getClassList returns them. 10 | 11 | @param klass The base class to find subclasses of. 12 | @param block A block that takes a Class. This block will be executed once for each subclass of klass. 13 | */ 14 | void qck_enumerateSubclasses(Class klass, QCKClassEnumerationBlock block) { 15 | Class *classes = NULL; 16 | int classesCount = objc_getClassList(NULL, 0); 17 | 18 | if (classesCount > 0) { 19 | classes = (Class *)calloc(sizeof(Class), classesCount); 20 | classesCount = objc_getClassList(classes, classesCount); 21 | 22 | Class subclass, superclass; 23 | for(int i = 0; i < classesCount; i++) { 24 | subclass = classes[i]; 25 | superclass = class_getSuperclass(subclass); 26 | if (superclass == klass && block) { 27 | block(subclass); 28 | } 29 | } 30 | 31 | free(classes); 32 | } 33 | } 34 | 35 | @implementation QuickConfiguration 36 | 37 | #pragma mark - Object Lifecycle 38 | 39 | /** 40 | QuickConfiguration is not meant to be instantiated; it merely provides a hook 41 | for users to configure how Quick behaves. Raise an exception if an instance of 42 | QuickConfiguration is created. 43 | */ 44 | - (instancetype)init { 45 | NSString *className = NSStringFromClass([self class]); 46 | NSString *selectorName = NSStringFromSelector(@selector(configure:)); 47 | [NSException raise:NSInternalInconsistencyException 48 | format:@"%@ is not meant to be instantiated; " 49 | @"subclass %@ and override %@ to configure Quick.", 50 | className, className, selectorName]; 51 | return nil; 52 | } 53 | 54 | #pragma mark - NSObject Overrides 55 | 56 | /** 57 | Hook into when QuickConfiguration is initialized in the runtime in order to 58 | call +[QuickConfiguration configure:] on each of its subclasses. 59 | */ 60 | + (void)initialize { 61 | // Only enumerate over the subclasses of QuickConfiguration, not any of its subclasses. 62 | if ([self class] == [QuickConfiguration class]) { 63 | 64 | // Only enumerate over subclasses once, even if +[QuickConfiguration initialize] 65 | // were to be called several times. This is necessary because +[QuickSpec initialize] 66 | // manually calls +[QuickConfiguration initialize]. 67 | static dispatch_once_t onceToken; 68 | dispatch_once(&onceToken, ^{ 69 | qck_enumerateSubclasses([QuickConfiguration class], ^(__unsafe_unretained Class klass) { 70 | [[World sharedWorld] configure:^(Configuration *configuration) { 71 | [klass configure:configuration]; 72 | }]; 73 | }); 74 | [[World sharedWorld] finalizeConfiguration]; 75 | }); 76 | } 77 | } 78 | 79 | #pragma mark - Public Interface 80 | 81 | + (void)configure:(Configuration *)configuration { } 82 | 83 | @end 84 | -------------------------------------------------------------------------------- /Quick/DSL/DSL.swift: -------------------------------------------------------------------------------- 1 | /** 2 | Defines a closure to be run prior to any examples in the test suite. 3 | You may define an unlimited number of these closures, but there is no 4 | guarantee as to the order in which they're run. 5 | 6 | If the test suite crashes before the first example is run, this closure 7 | will not be executed. 8 | */ 9 | public func beforeSuite(closure: BeforeSuiteClosure) { 10 | World.sharedWorld().beforeSuite(closure) 11 | } 12 | 13 | /** 14 | Defines a closure to be run after all of the examples in the test suite. 15 | You may define an unlimited number of these closures, but there is no 16 | guarantee as to the order in which they're run. 17 | 18 | If the test suite crashes before all examples are run, this closure 19 | will not be executed. 20 | */ 21 | public func afterSuite(closure: AfterSuiteClosure) { 22 | World.sharedWorld().afterSuite(closure) 23 | } 24 | 25 | /** 26 | Defines a group of shared examples. These examples can be re-used in several locations 27 | by using the `itBehavesLike` function. 28 | 29 | :param: name The name of the shared example group. This must be unique across all shared example 30 | groups defined in a test suite. 31 | :param: closure A closure containing the examples. This behaves just like an example group defined 32 | using `describe` or `context`--the closure may contain any number of `beforeEach` 33 | and `afterEach` closures, as well as any number of examples (defined using `it`). 34 | */ 35 | public func sharedExamples(name: String, closure: () -> ()) { 36 | World.sharedWorld().sharedExamples(name, closure: { (NSDictionary) in closure() }) 37 | } 38 | 39 | /** 40 | Defines a group of shared examples. These examples can be re-used in several locations 41 | by using the `itBehavesLike` function. 42 | 43 | :param: name The name of the shared example group. This must be unique across all shared example 44 | groups defined in a test suite. 45 | :param: closure A closure containing the examples. This behaves just like an example group defined 46 | using `describe` or `context`--the closure may contain any number of `beforeEach` 47 | and `afterEach` closures, as well as any number of examples (defined using `it`). 48 | 49 | The closure takes a SharedExampleContext as an argument. This context is a function 50 | that can be executed to retrieve parameters passed in via an `itBehavesLike` function. 51 | */ 52 | public func sharedExamples(name: String, closure: SharedExampleClosure) { 53 | World.sharedWorld().sharedExamples(name, closure: closure) 54 | } 55 | 56 | /** 57 | Defines an example group. Example groups are logical groupings of examples. 58 | Example groups can share setup and teardown code. 59 | 60 | :param: description An arbitrary string describing the example group. 61 | :param: closure A closure that can contain other examples. 62 | */ 63 | public func describe(description: String, closure: () -> ()) { 64 | World.sharedWorld().describe(description, closure: closure) 65 | } 66 | 67 | /** 68 | Defines an example group. Equivalent to `describe`. 69 | */ 70 | public func context(description: String, closure: () -> ()) { 71 | describe(description, closure) 72 | } 73 | 74 | /** 75 | Defines a closure to be run prior to each example in the current example 76 | group. This closure is not run for pending or otherwise disabled examples. 77 | An example group may contain an unlimited number of beforeEach. They'll be 78 | run in the order they're defined, but you shouldn't rely on that behavior. 79 | 80 | :param: closure The closure to be run prior to each example. 81 | */ 82 | public func beforeEach(closure: BeforeExampleClosure) { 83 | World.sharedWorld().beforeEach(closure) 84 | } 85 | 86 | /** 87 | Identical to Quick.DSL.beforeEach, except the closure is provided with 88 | metadata on the example that the closure is being run prior to. 89 | */ 90 | public func beforeEach(#closure: BeforeExampleWithMetadataClosure) { 91 | World.sharedWorld().beforeEach(closure: closure) 92 | } 93 | 94 | /** 95 | Defines a closure to be run after each example in the current example 96 | group. This closure is not run for pending or otherwise disabled examples. 97 | An example group may contain an unlimited number of afterEach. They'll be 98 | run in the order they're defined, but you shouldn't rely on that behavior. 99 | 100 | :param: closure The closure to be run after each example. 101 | */ 102 | public func afterEach(closure: AfterExampleClosure) { 103 | World.sharedWorld().afterEach(closure) 104 | } 105 | 106 | /** 107 | Identical to Quick.DSL.afterEach, except the closure is provided with 108 | metadata on the example that the closure is being run after. 109 | */ 110 | public func afterEach(#closure: AfterExampleWithMetadataClosure) { 111 | World.sharedWorld().afterEach(closure: closure) 112 | } 113 | 114 | /** 115 | Defines an example. Examples use assertions to demonstrate how code should 116 | behave. These are like "tests" in XCTest. 117 | 118 | :param: description An arbitrary string describing what the example is meant to specify. 119 | :param: closure A closure that can contain assertions. 120 | :param: file The absolute path to the file containing the example. A sensible default is provided. 121 | :param: line The line containing the example. A sensible default is provided. 122 | */ 123 | public func it(description: String, closure: () -> (), file: String = __FILE__, line: Int = __LINE__) { 124 | World.sharedWorld().it(description, file: file, line: line, closure: closure) 125 | } 126 | 127 | /** 128 | Inserts the examples defined using a `sharedExamples` function into the current example group. 129 | The shared examples are executed at this location, as if they were written out manually. 130 | 131 | :param: name The name of the shared examples group to be executed. This must be identical to the 132 | name of a shared examples group defined using `sharedExamples`. If there are no shared 133 | examples that match the name given, an exception is thrown and the test suite will crash. 134 | :param: file The absolute path to the file containing the current example group. A sensible default is provided. 135 | :param: line The line containing the current example group. A sensible default is provided. 136 | */ 137 | public func itBehavesLike(name: String, file: String = __FILE__, line: Int = __LINE__) { 138 | itBehavesLike(name, { return [:] }, file: file, line: line) 139 | } 140 | 141 | /** 142 | Inserts the examples defined using a `sharedExamples` function into the current example group. 143 | The shared examples are executed at this location, as if they were written out manually. 144 | This function also passes those shared examples a context that can be evaluated to give the shared 145 | examples extra information on the subject of the example. 146 | 147 | :param: name The name of the shared examples group to be executed. This must be identical to the 148 | name of a shared examples group defined using `sharedExamples`. If there are no shared 149 | examples that match the name given, an exception is thrown and the test suite will crash. 150 | :param: sharedExampleContext A closure that, when evaluated, returns key-value pairs that provide the 151 | shared examples with extra information on the subject of the example. 152 | :param: file The absolute path to the file containing the current example group. A sensible default is provided. 153 | :param: line The line containing the current example group. A sensible default is provided. 154 | */ 155 | public func itBehavesLike(name: String, sharedExampleContext: SharedExampleContext, file: String = __FILE__, line: Int = __LINE__) { 156 | World.sharedWorld().itBehavesLike(name, sharedExampleContext: sharedExampleContext, file: file, line: line) 157 | } 158 | 159 | /** 160 | Defines an example or example group that should not be executed. Use `pending` to temporarily disable 161 | examples or groups that should not be run yet. 162 | 163 | :param: description An arbitrary string describing the example or example group. 164 | :param: closure A closure that will not be evaluated. 165 | */ 166 | public func pending(description: String, closure: () -> ()) { 167 | World.sharedWorld().pending(description, closure: closure) 168 | } 169 | 170 | /** 171 | Identical to `pending`. Use this to quickly disable a `describe` closure. 172 | */ 173 | public func xdescribe(description: String, closure: () -> ()) { 174 | pending(description, closure) 175 | } 176 | 177 | /** 178 | Identical to `pending`. Use this to quickly disable a `context` closure. 179 | */ 180 | public func xcontext(description: String, closure: () -> ()) { 181 | pending(description, closure) 182 | } 183 | 184 | /** 185 | Identical to `pending`. Use this to quickly disable a `it` closure. 186 | */ 187 | public func xit(description: String, closure: () -> ()) { 188 | pending(description, closure) 189 | } 190 | -------------------------------------------------------------------------------- /Quick/DSL/QCKDSL.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | /** 4 | Provides a hook for Quick to be configured before any examples are run. 5 | Within this scope, override the +[QuickConfiguration configure:] method 6 | to set properties on a configuration object to customize Quick behavior. 7 | For details, see the documentation for Configuraiton.swift. 8 | 9 | @param name The name of the configuration class. Like any Objective-C 10 | class name, this must be unique to the current runtime 11 | environment. 12 | */ 13 | #define QuickConfigurationBegin(name) \ 14 | @interface name : QuickConfiguration; @end \ 15 | @implementation name \ 16 | 17 | 18 | /** 19 | Marks the end of a Quick configuration. 20 | Make sure you put this after `QuickConfigurationBegin`. 21 | */ 22 | #define QuickConfigurationEnd \ 23 | @end \ 24 | 25 | 26 | /** 27 | Defines a new QuickSpec. Define examples and example groups within the space 28 | between this and `QuickSpecEnd`. 29 | 30 | @param name The name of the spec class. Like any Objective-C class name, this 31 | must be unique to the current runtime environment. 32 | */ 33 | #define QuickSpecBegin(name) \ 34 | @interface name : QuickSpec; @end \ 35 | @implementation name \ 36 | - (void)spec { \ 37 | 38 | 39 | /** 40 | Marks the end of a QuickSpec. Make sure you put this after `QuickSpecBegin`. 41 | */ 42 | #define QuickSpecEnd \ 43 | } \ 44 | @end \ 45 | 46 | typedef NSDictionary *(^QCKDSLSharedExampleContext)(void); 47 | typedef void (^QCKDSLSharedExampleBlock)(QCKDSLSharedExampleContext); 48 | typedef void (^QCKDSLEmptyBlock)(void); 49 | 50 | extern void qck_beforeSuite(QCKDSLEmptyBlock closure); 51 | extern void qck_afterSuite(QCKDSLEmptyBlock closure); 52 | extern void qck_sharedExamples(NSString *name, QCKDSLSharedExampleBlock closure); 53 | extern void qck_describe(NSString *description, QCKDSLEmptyBlock closure); 54 | extern void qck_context(NSString *description, QCKDSLEmptyBlock closure); 55 | extern void qck_beforeEach(QCKDSLEmptyBlock closure); 56 | extern void qck_afterEach(QCKDSLEmptyBlock closure); 57 | extern void qck_pending(NSString *description, QCKDSLEmptyBlock closure); 58 | extern void qck_xdescribe(NSString *description, QCKDSLEmptyBlock closure); 59 | extern void qck_xcontext(NSString *description, QCKDSLEmptyBlock closure); 60 | extern void qck_xit(NSString *description, QCKDSLEmptyBlock closure); 61 | 62 | #ifndef QUICK_DISABLE_SHORT_SYNTAX 63 | static inline void beforeSuite(QCKDSLEmptyBlock closure) { 64 | qck_beforeSuite(closure); 65 | } 66 | 67 | static inline void afterSuite(QCKDSLEmptyBlock closure) { 68 | qck_afterSuite(closure); 69 | } 70 | 71 | static inline void sharedExamples(NSString *name, QCKDSLSharedExampleBlock closure) { 72 | qck_sharedExamples(name, closure); 73 | } 74 | 75 | static inline void describe(NSString *description, QCKDSLEmptyBlock closure) { 76 | qck_describe(description, closure); 77 | } 78 | 79 | static inline void context(NSString *description, QCKDSLEmptyBlock closure) { 80 | qck_context(description, closure); 81 | } 82 | 83 | static inline void beforeEach(QCKDSLEmptyBlock closure) { 84 | qck_beforeEach(closure); 85 | } 86 | 87 | static inline void afterEach(QCKDSLEmptyBlock closure) { 88 | qck_afterEach(closure); 89 | } 90 | 91 | static inline void pending(NSString *description, QCKDSLEmptyBlock closure) { 92 | qck_pending(description, closure); 93 | } 94 | 95 | static inline void xdescribe(NSString *description, QCKDSLEmptyBlock closure) { 96 | qck_xdescribe(description, closure); 97 | } 98 | 99 | static inline void xcontext(NSString *description, QCKDSLEmptyBlock closure) { 100 | qck_xcontext(description, closure); 101 | } 102 | 103 | static inline void xit(NSString *description, QCKDSLEmptyBlock closure) { 104 | qck_xit(description, closure); 105 | } 106 | 107 | #define it qck_it 108 | #define itBehavesLike qck_itBehavesLike 109 | #endif 110 | 111 | #define qck_it qck_it_builder(@(__FILE__), __LINE__) 112 | #define qck_itBehavesLike qck_itBehavesLike_builder(@(__FILE__), __LINE__) 113 | 114 | typedef void (^QCKItBlock)(NSString *description, QCKDSLEmptyBlock closure); 115 | typedef void (^QCKItBehavesLikeBlock)(NSString *descritpion, QCKDSLSharedExampleContext context); 116 | 117 | extern QCKItBlock qck_it_builder(NSString *file, NSUInteger line); 118 | extern QCKItBehavesLikeBlock qck_itBehavesLike_builder(NSString *file, NSUInteger line); 119 | -------------------------------------------------------------------------------- /Quick/DSL/QCKDSL.m: -------------------------------------------------------------------------------- 1 | #import "QCKDSL.h" 2 | #import 3 | 4 | void qck_beforeSuite(QCKDSLEmptyBlock closure) { 5 | [[World sharedWorld] beforeSuite:closure]; 6 | } 7 | 8 | void qck_afterSuite(QCKDSLEmptyBlock closure) { 9 | [[World sharedWorld] afterSuite:closure]; 10 | } 11 | 12 | void qck_sharedExamples(NSString *name, QCKDSLSharedExampleBlock closure) { 13 | [[World sharedWorld] sharedExamples:name closure:closure]; 14 | } 15 | 16 | void qck_describe(NSString *description, QCKDSLEmptyBlock closure) { 17 | [[World sharedWorld] describe:description closure:closure]; 18 | } 19 | 20 | void qck_context(NSString *description, QCKDSLEmptyBlock closure) { 21 | qck_describe(description, closure); 22 | } 23 | 24 | void qck_beforeEach(QCKDSLEmptyBlock closure) { 25 | [[World sharedWorld] beforeEach:closure]; 26 | } 27 | 28 | void qck_afterEach(QCKDSLEmptyBlock closure) { 29 | [[World sharedWorld] afterEach:closure]; 30 | } 31 | 32 | QCKItBlock qck_it_builder(NSString *file, NSUInteger line) { 33 | return ^(NSString *description, QCKDSLEmptyBlock closure) { 34 | [[World sharedWorld] itWithDescription:description file:file line:line closure:closure]; 35 | }; 36 | } 37 | 38 | QCKItBehavesLikeBlock qck_itBehavesLike_builder(NSString *file, NSUInteger line) { 39 | return ^(NSString *name, QCKDSLSharedExampleContext context) { 40 | [[World sharedWorld] itBehavesLikeSharedExampleNamed:name sharedExampleContext:context file:file line:line]; 41 | }; 42 | } 43 | 44 | void qck_pending(NSString *description, QCKDSLEmptyBlock closure) { 45 | [[World sharedWorld] pending:description closure:closure]; 46 | } 47 | 48 | void qck_xdescribe(NSString *description, QCKDSLEmptyBlock closure) { 49 | qck_pending(description, closure); 50 | } 51 | 52 | void qck_xcontext(NSString *description, QCKDSLEmptyBlock closure) { 53 | qck_pending(description, closure); 54 | } 55 | 56 | void qck_xit(NSString *description, QCKDSLEmptyBlock closure) { 57 | qck_pending(description, closure); 58 | } 59 | -------------------------------------------------------------------------------- /Quick/DSL/World+DSL.swift: -------------------------------------------------------------------------------- 1 | /** 2 | Adds methods to World to support top-level DSL functions (Swift) and 3 | macros (Objective-C). These functions map directly to the DSL that test 4 | writers use in their specs. 5 | */ 6 | extension World { 7 | public func beforeSuite(closure: BeforeSuiteClosure) { 8 | suiteHooks.appendBefore(closure) 9 | } 10 | 11 | public func afterSuite(closure: AfterSuiteClosure) { 12 | suiteHooks.appendAfter(closure) 13 | } 14 | 15 | public func sharedExamples(name: String, closure: SharedExampleClosure) { 16 | registerSharedExample(name, closure: closure) 17 | } 18 | 19 | public func describe(description: String, closure: () -> ()) { 20 | var group = ExampleGroup(description: description) 21 | currentExampleGroup!.appendExampleGroup(group) 22 | currentExampleGroup = group 23 | closure() 24 | currentExampleGroup = group.parent 25 | } 26 | 27 | public func context(description: String, closure: () -> ()) { 28 | describe(description, closure: closure) 29 | } 30 | 31 | public func beforeEach(closure: BeforeExampleClosure) { 32 | currentExampleGroup!.hooks.appendBefore(closure) 33 | } 34 | 35 | public func beforeEach(#closure: BeforeExampleWithMetadataClosure) { 36 | currentExampleGroup!.hooks.appendBefore(closure) 37 | } 38 | 39 | public func afterEach(closure: AfterExampleClosure) { 40 | currentExampleGroup!.hooks.appendAfter(closure) 41 | } 42 | 43 | public func afterEach(#closure: AfterExampleWithMetadataClosure) { 44 | currentExampleGroup!.hooks.appendAfter(closure) 45 | } 46 | 47 | @objc(itWithDescription:file:line:closure:) 48 | public func it(description: String, file: String, line: Int, closure: () -> ()) { 49 | let callsite = Callsite(file: file, line: line) 50 | let example = Example(description, callsite, closure) 51 | currentExampleGroup!.appendExample(example) 52 | } 53 | 54 | @objc(itBehavesLikeSharedExampleNamed:sharedExampleContext:file:line:) 55 | public func itBehavesLike(name: String, sharedExampleContext: SharedExampleContext, file: String, line: Int) { 56 | let callsite = Callsite(file: file, line: line) 57 | let closure = World.sharedWorld().sharedExample(name) 58 | 59 | var group = ExampleGroup(description: name) 60 | currentExampleGroup!.appendExampleGroup(group) 61 | currentExampleGroup = group 62 | closure(sharedExampleContext) 63 | currentExampleGroup!.walkDownExamples { (example: Example) in 64 | example.isSharedExample = true 65 | example.callsite = callsite 66 | } 67 | 68 | currentExampleGroup = group.parent 69 | } 70 | 71 | public func pending(description: String, closure: () -> ()) { 72 | NSLog("Pending: %@", description) 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Quick/Example.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | var _numberOfExamplesRun = 0 4 | 5 | @objc public class Example { 6 | weak var group: ExampleGroup? 7 | 8 | var _description: String 9 | var _closure: () -> () 10 | 11 | public var isSharedExample = false 12 | public var callsite: Callsite 13 | 14 | public var name: String { 15 | get { 16 | switch group!.name { 17 | case .Some(let groupName): 18 | return "\(groupName), \(_description)" 19 | case .None: 20 | return _description 21 | } 22 | } 23 | } 24 | 25 | init(_ description: String, _ callsite: Callsite, _ closure: () -> ()) { 26 | self._description = description 27 | self._closure = closure 28 | self.callsite = callsite 29 | } 30 | 31 | public func run() { 32 | let world = World.sharedWorld() 33 | 34 | if _numberOfExamplesRun == 0 { 35 | world.suiteHooks.executeBefores() 36 | } 37 | 38 | let exampleMetadata = ExampleMetadata(example: self, exampleIndex: _numberOfExamplesRun) 39 | world.exampleHooks.executeBefores(exampleMetadata) 40 | for before in group!.befores { 41 | before(exampleMetadata: exampleMetadata) 42 | } 43 | 44 | _closure() 45 | 46 | for after in group!.afters { 47 | after(exampleMetadata: exampleMetadata) 48 | } 49 | world.exampleHooks.executeAfters(exampleMetadata) 50 | 51 | ++_numberOfExamplesRun 52 | 53 | 54 | if !world.isRunningAdditionalSuites && _numberOfExamplesRun >= world.exampleCount { 55 | world.suiteHooks.executeAfters() 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Quick/ExampleGroup.swift: -------------------------------------------------------------------------------- 1 | @objc public class ExampleGroup { 2 | internal let hooks = ExampleHooks() 3 | 4 | weak var parent: ExampleGroup? 5 | 6 | let _description: String 7 | let _isInternalRootExampleGroup: Bool 8 | var _groups = [ExampleGroup]() 9 | var _localExamples = [Example]() 10 | 11 | init(description: String, isInternalRootExampleGroup: Bool = false) { 12 | self._description = description 13 | self._isInternalRootExampleGroup = isInternalRootExampleGroup 14 | } 15 | 16 | var befores: [BeforeExampleWithMetadataClosure] { 17 | get { 18 | var closures = hooks.befores 19 | walkUp() { (group: ExampleGroup) -> () in 20 | closures.extend(group.hooks.befores) 21 | } 22 | return closures.reverse() 23 | } 24 | } 25 | 26 | var afters: [AfterExampleWithMetadataClosure] { 27 | get { 28 | var closures = hooks.afters 29 | walkUp() { (group: ExampleGroup) -> () in 30 | closures.extend(group.hooks.afters) 31 | } 32 | return closures 33 | } 34 | } 35 | 36 | public var examples: [Example] { 37 | get { 38 | var examples = _localExamples 39 | for group in _groups { 40 | examples.extend(group.examples) 41 | } 42 | return examples 43 | } 44 | } 45 | 46 | var name: String? { 47 | get { 48 | if self._isInternalRootExampleGroup { 49 | return nil 50 | } else { 51 | var name = _description 52 | walkUp() { (group: ExampleGroup) -> () in 53 | name = group._description + ", " + name 54 | } 55 | return name 56 | } 57 | } 58 | } 59 | 60 | func run() { 61 | walkDownExamples { (example: Example) -> () in 62 | example.run() 63 | } 64 | } 65 | 66 | func walkUp(callback: (group: ExampleGroup) -> ()) { 67 | var group = self 68 | while let parent = group.parent { 69 | callback(group: parent) 70 | group = parent 71 | } 72 | } 73 | 74 | func walkDownExamples(callback: (example: Example) -> ()) { 75 | for example in _localExamples { 76 | callback(example: example) 77 | } 78 | for group in _groups { 79 | group.walkDownExamples(callback) 80 | } 81 | } 82 | 83 | func appendExampleGroup(group: ExampleGroup) { 84 | group.parent = self 85 | _groups.append(group) 86 | } 87 | 88 | func appendExample(example: Example) { 89 | example.group = self 90 | _localExamples.append(example) 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /Quick/ExampleMetadata.swift: -------------------------------------------------------------------------------- 1 | @objc public class ExampleMetadata { 2 | public let example: Example 3 | public let exampleIndex: Int 4 | 5 | init(example: Example, exampleIndex: Int) { 6 | self.example = example 7 | self.exampleIndex = exampleIndex 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Quick/Failure.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | @objc class Failure { 4 | let callsite: Callsite 5 | let exception: NSException 6 | 7 | init(exception: NSException, callsite: Callsite) { 8 | self.exception = exception 9 | self.callsite = callsite 10 | } 11 | 12 | @objc(failureWithException:callsite:) 13 | class func failure(exception: NSException, callsite: Callsite) -> Failure { 14 | return Failure(exception: exception, callsite: callsite) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Quick/Hooks/Closures.swift: -------------------------------------------------------------------------------- 1 | // MARK: Example Hooks 2 | 3 | /** 4 | A closure executed before an example is run. 5 | */ 6 | public typealias BeforeExampleClosure = () -> () 7 | 8 | /** 9 | A closure executed before an example is run. The closure is given example metadata, 10 | which contains information about the example that is about to be run. 11 | */ 12 | public typealias BeforeExampleWithMetadataClosure = (exampleMetadata: ExampleMetadata) -> () 13 | 14 | /** 15 | A closure executed after an example is run. 16 | */ 17 | public typealias AfterExampleClosure = BeforeExampleClosure 18 | 19 | /** 20 | A closure executed after an example is run. The closure is given example metadata, 21 | which contains information about the example that has just finished running. 22 | */ 23 | public typealias AfterExampleWithMetadataClosure = BeforeExampleWithMetadataClosure 24 | 25 | // MARK: Suite Hooks 26 | 27 | 28 | /** 29 | A closure executed before any examples are run. 30 | */ 31 | public typealias BeforeSuiteClosure = () -> () 32 | 33 | /** 34 | A closure executed after all examples have finished running. 35 | */ 36 | public typealias AfterSuiteClosure = BeforeSuiteClosure 37 | -------------------------------------------------------------------------------- /Quick/Hooks/ExampleHooks.swift: -------------------------------------------------------------------------------- 1 | /** 2 | A container for closures to be executed before and after each example. 3 | */ 4 | internal class ExampleHooks { 5 | 6 | internal var befores: [BeforeExampleWithMetadataClosure] = [] 7 | internal var afters: [AfterExampleWithMetadataClosure] = [] 8 | 9 | internal func appendBefore(closure: BeforeExampleWithMetadataClosure) { 10 | befores.append(closure) 11 | } 12 | 13 | internal func appendBefore(closure: BeforeExampleClosure) { 14 | befores.append { (exampleMetadata: ExampleMetadata) in closure() } 15 | } 16 | 17 | internal func appendAfter(closure: AfterExampleWithMetadataClosure) { 18 | afters.append(closure) 19 | } 20 | 21 | internal func appendAfter(closure: AfterExampleClosure) { 22 | afters.append { (exampleMetadata: ExampleMetadata) in closure() } 23 | } 24 | 25 | internal func executeBefores(exampleMetadata: ExampleMetadata) { 26 | for before in befores { 27 | before(exampleMetadata: exampleMetadata) 28 | } 29 | } 30 | 31 | internal func executeAfters(exampleMetadata: ExampleMetadata) { 32 | for after in afters { 33 | after(exampleMetadata: exampleMetadata) 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Quick/Hooks/SuiteHooks.swift: -------------------------------------------------------------------------------- 1 | /** 2 | A container for closures to be executed before and after all examples. 3 | */ 4 | internal class SuiteHooks { 5 | internal var befores: [BeforeSuiteClosure] = [] 6 | internal var beforesAlreadyExecuted = false 7 | 8 | internal var afters: [AfterSuiteClosure] = [] 9 | internal var aftersAlreadyExecuted = false 10 | 11 | internal func appendBefore(closure: BeforeSuiteClosure) { 12 | befores.append(closure) 13 | } 14 | 15 | internal func appendAfter(closure: AfterSuiteClosure) { 16 | afters.append(closure) 17 | } 18 | 19 | internal func executeBefores() { 20 | assert(!beforesAlreadyExecuted) 21 | for before in befores { 22 | before() 23 | } 24 | beforesAlreadyExecuted = true 25 | } 26 | 27 | internal func executeAfters() { 28 | assert(!aftersAlreadyExecuted) 29 | for after in afters { 30 | after() 31 | } 32 | aftersAlreadyExecuted = true 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Quick/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | io.quick.${PRODUCT_NAME:rfc1034identifier} 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 | NSHumanReadableCopyright 24 | Copyright © 2014 - present, Quick Team. All rights reserved. 25 | NSPrincipalClass 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Quick/NSException+Callsite.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | let FilenameKey = "SenTestFilenameKey" 4 | let LineNumberKey = "SenTestLineNumberKey" 5 | 6 | extension NSException { 7 | var qck_callsite: Callsite? { 8 | if let info: NSDictionary = userInfo { 9 | if let file = info[FilenameKey] as? String { 10 | if let line = info[LineNumberKey] as? Int { 11 | return Callsite(file: file, line: line) 12 | } 13 | } 14 | } 15 | 16 | return nil 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Quick/NSString+QCKSelectorName.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | /** 4 | QuickSpec converts example names into test methods. 5 | Those test methods need valid selector names, which means no whitespace, 6 | control characters, etc. This category gives NSString objects an easy way 7 | to replace those illegal characters with underscores. 8 | */ 9 | @interface NSString (QCKSelectorName) 10 | 11 | /** 12 | Returns a string with underscores in place of all characters that cannot 13 | be included in a selector (SEL) name. 14 | */ 15 | @property (nonatomic, readonly) NSString *qck_selectorName; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Quick/NSString+QCKSelectorName.m: -------------------------------------------------------------------------------- 1 | #import "NSString+QCKSelectorName.h" 2 | 3 | @implementation NSString (QCKSelectorName) 4 | 5 | - (NSString *)qck_selectorName { 6 | static NSMutableCharacterSet *invalidCharacters = nil; 7 | static dispatch_once_t onceToken; 8 | dispatch_once(&onceToken, ^{ 9 | invalidCharacters = [NSMutableCharacterSet new]; 10 | 11 | NSCharacterSet *whitespaceCharacterSet = [NSCharacterSet whitespaceCharacterSet]; 12 | NSCharacterSet *newlineCharacterSet = [NSCharacterSet newlineCharacterSet]; 13 | NSCharacterSet *illegalCharacterSet = [NSCharacterSet illegalCharacterSet]; 14 | NSCharacterSet *controlCharacterSet = [NSCharacterSet controlCharacterSet]; 15 | NSCharacterSet *punctuationCharacterSet = [NSCharacterSet punctuationCharacterSet]; 16 | NSCharacterSet *nonBaseCharacterSet = [NSCharacterSet nonBaseCharacterSet]; 17 | NSCharacterSet *symbolCharacterSet = [NSCharacterSet symbolCharacterSet]; 18 | 19 | [invalidCharacters formUnionWithCharacterSet:whitespaceCharacterSet]; 20 | [invalidCharacters formUnionWithCharacterSet:newlineCharacterSet]; 21 | [invalidCharacters formUnionWithCharacterSet:illegalCharacterSet]; 22 | [invalidCharacters formUnionWithCharacterSet:controlCharacterSet]; 23 | [invalidCharacters formUnionWithCharacterSet:punctuationCharacterSet]; 24 | [invalidCharacters formUnionWithCharacterSet:nonBaseCharacterSet]; 25 | [invalidCharacters formUnionWithCharacterSet:symbolCharacterSet]; 26 | }); 27 | 28 | NSArray *validComponents = [self componentsSeparatedByCharactersInSet:invalidCharacters]; 29 | 30 | return [validComponents componentsJoinedByString:@"_"]; 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /Quick/Quick.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | //! Project version number for Quick. 4 | FOUNDATION_EXPORT double QuickVersionNumber; 5 | 6 | //! Project version string for Quick. 7 | FOUNDATION_EXPORT const unsigned char QuickVersionString[]; 8 | 9 | // In this header, you should import all the public headers of your framework using statements like #import 10 | 11 | #import 12 | #import 13 | #import 14 | -------------------------------------------------------------------------------- /Quick/QuickSpec.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | /** 4 | QuickSpec is a base class all specs written in Quick inherit from. 5 | They need to inherit from QuickSpec, a subclass of XCTestCase, in 6 | order to be discovered by the XCTest framework. 7 | 8 | XCTest automatically compiles a list of XCTestCase subclasses included 9 | in the test target. It iterates over each class in that list, and creates 10 | a new instance of that class for each test method. It then creates an 11 | "invocation" to execute that test method. The invocation is an instance of 12 | NSInvocation, which represents a single message send in Objective-C. 13 | The invocation is set on the XCTestCase instance, and the test is run. 14 | 15 | Most of the code in QuickSpec is dedicated to hooking into XCTest events. 16 | First, when the spec is first loaded and before it is sent any messages, 17 | the +[NSObject initialize] method is called. QuickSpec overrides this method 18 | to call +[QuickSpec spec]. This builds the example group stacks and 19 | registers them with Quick.World, a global register of examples. 20 | 21 | Then, XCTest queries QuickSpec for a list of test methods. Normally, XCTest 22 | automatically finds all methods whose selectors begin with the string "test". 23 | However, QuickSpec overrides this default behavior by implementing the 24 | +[XCTestCase testInvocations] method. This method iterates over each example 25 | registered in Quick.World, defines a new method for that example, and 26 | returns an invocation to call that method to XCTest. Those invocations are 27 | the tests that are run by XCTest. Their selector names are displayed in 28 | the Xcode test navigation bar. 29 | */ 30 | @interface QuickSpec : XCTestCase 31 | 32 | /** 33 | Override this method in your spec to define a set of example groups 34 | and examples. 35 | 36 | override class func spec() { 37 | describe("winter") { 38 | it("is coming") { 39 | // ... 40 | } 41 | } 42 | } 43 | 44 | See DSL.swift for more information on what syntax is available. 45 | */ 46 | - (void)spec; 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /Quick/QuickSpec.m: -------------------------------------------------------------------------------- 1 | #import "QuickSpec.h" 2 | #import "QuickConfiguration.h" 3 | #import "NSString+QCKSelectorName.h" 4 | #import 5 | #import 6 | 7 | const void * const QCKExampleKey = &QCKExampleKey; 8 | 9 | @interface QuickSpec () 10 | @property (nonatomic, strong) Example *example; 11 | @end 12 | 13 | @implementation QuickSpec 14 | 15 | #pragma mark - XCTestCase Overrides 16 | 17 | /** 18 | The runtime sends initialize to each class in a program just before the class, or any class 19 | that inherits from it, is sent its first message from within the program. QuickSpec hooks into 20 | this event to compile the example groups for this spec subclass. 21 | 22 | If an exception occurs when compiling the examples, report it to the user. Chances are they 23 | included an expectation outside of a "it", "describe", or "context" block. 24 | */ 25 | + (void)initialize { 26 | [QuickConfiguration initialize]; 27 | 28 | World *world = [World sharedWorld]; 29 | world.currentExampleGroup = [world rootExampleGroupForSpecClass:[self class]]; 30 | QuickSpec *spec = [self new]; 31 | 32 | @try { 33 | [spec spec]; 34 | } 35 | @catch (NSException *exception) { 36 | [NSException raise:NSInternalInconsistencyException 37 | format:@"An exception occurred when building Quick's example groups.\n" 38 | @"Some possible reasons this might happen include:\n\n" 39 | @"- An 'expect(...).to' expectation was evaluated outside of " 40 | @"an 'it', 'context', or 'describe' block\n" 41 | @"- 'sharedExamples' was called twice with the same name\n" 42 | @"- 'itBehavesLike' was called with a name that is not registered as a shared example\n\n" 43 | @"Here's the original exception: '%@', reason: '%@', userInfo: '%@'", 44 | exception.name, exception.reason, exception.userInfo]; 45 | } 46 | } 47 | 48 | /** 49 | Invocations for each test method in the test case. QuickSpec overrides this method to define a 50 | new method for each example defined in +[QuickSpec spec]. 51 | 52 | @return An array of invocations that execute the newly defined example methods. 53 | */ 54 | + (NSArray *)testInvocations { 55 | NSArray *examples = [[World sharedWorld] rootExampleGroupForSpecClass:[self class]].examples; 56 | NSMutableArray *invocations = [NSMutableArray arrayWithCapacity:[examples count]]; 57 | 58 | for (Example *example in examples) { 59 | SEL selector = [self addInstanceMethodForExample:example]; 60 | NSInvocation *invocation = [self invocationForInstanceMethodWithSelector:selector 61 | example:example]; 62 | [invocations addObject:invocation]; 63 | } 64 | 65 | return invocations; 66 | } 67 | 68 | /** 69 | XCTest sets the invocation for the current test case instance using this setter. 70 | QuickSpec hooks into this event to give the test case a reference to the current example. 71 | It will need this reference to correctly report its name to XCTest. 72 | */ 73 | - (void)setInvocation:(NSInvocation *)invocation { 74 | self.example = objc_getAssociatedObject(invocation, QCKExampleKey); 75 | [super setInvocation:invocation]; 76 | } 77 | 78 | #pragma mark - Public Interface 79 | 80 | - (void)spec { } 81 | 82 | #pragma mark - Internal Methods 83 | 84 | /** 85 | QuickSpec uses this method to dynamically define a new instance method for the 86 | given example. The instance method runs the example, catching any exceptions. 87 | The exceptions are then reported as test failures. 88 | 89 | In order to report the correct file and line number, examples must raise exceptions 90 | containing following keys in their userInfo: 91 | 92 | - "SenTestFilenameKey": A String representing the file name 93 | - "SenTestLineNumberKey": An Int representing the line number 94 | 95 | These keys used to be used by SenTestingKit, and are still used by some testing tools 96 | in the wild. See: https://github.com/Quick/Quick/pull/41 97 | 98 | @return The selector of the newly defined instance method. 99 | */ 100 | + (SEL)addInstanceMethodForExample:(Example *)example { 101 | IMP implementation = imp_implementationWithBlock(^(id self){ 102 | [example run]; 103 | }); 104 | const char *types = [[NSString stringWithFormat:@"%s%s%s", @encode(id), @encode(id), @encode(SEL)] UTF8String]; 105 | SEL selector = NSSelectorFromString(example.name.qck_selectorName); 106 | class_addMethod(self, selector, implementation, types); 107 | 108 | return selector; 109 | } 110 | 111 | + (NSInvocation *)invocationForInstanceMethodWithSelector:(SEL)selector 112 | example:(Example *)example { 113 | NSMethodSignature *signature = [self instanceMethodSignatureForSelector:selector]; 114 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; 115 | invocation.selector = selector; 116 | objc_setAssociatedObject(invocation, 117 | QCKExampleKey, 118 | example, 119 | OBJC_ASSOCIATION_RETAIN_NONATOMIC); 120 | return invocation; 121 | } 122 | 123 | /** 124 | This method is used to record failures, whether they represent example 125 | expectations that were not met, or exceptions raised during test setup 126 | and teardown. By default, the failure will be reported as an 127 | XCTest failure, and the example will be highlighted in Xcode. 128 | */ 129 | - (void)recordFailureWithDescription:(NSString *)description 130 | inFile:(NSString *)filePath 131 | atLine:(NSUInteger)lineNumber 132 | expected:(BOOL)expected { 133 | if (self.example.isSharedExample) { 134 | filePath = self.example.callsite.file; 135 | lineNumber = self.example.callsite.line; 136 | } 137 | [super recordFailureWithDescription:description 138 | inFile:filePath 139 | atLine:lineNumber 140 | expected:expected]; 141 | } 142 | 143 | @end 144 | -------------------------------------------------------------------------------- /Quick/World+Singleton.swift: -------------------------------------------------------------------------------- 1 | extension World { 2 | struct _Shared { 3 | static let instance = World() 4 | } 5 | public class func sharedWorld() -> World { 6 | return _Shared.instance 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Quick/World.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public typealias SharedExampleContext = () -> (NSDictionary) 4 | public typealias SharedExampleClosure = (SharedExampleContext) -> () 5 | 6 | public class World: NSObject { 7 | var _specs: Dictionary = [:] 8 | var _sharedExamples: [String: SharedExampleClosure] = [:] 9 | 10 | let _configuration = Configuration() 11 | var _isConfigurationFinalized = false 12 | 13 | internal var exampleHooks: ExampleHooks {return _configuration.exampleHooks } 14 | internal var suiteHooks: SuiteHooks { return _configuration.suiteHooks } 15 | 16 | /** 17 | Exposes the World's Configuration object within the scope of the closure 18 | so that it may be configured. This method must not be called outside of 19 | an overridden +[QuickConfiguration configure:] method. 20 | 21 | :param: closure A closure that takes a Configuration object that can 22 | be mutated to change Quick's behavior. 23 | */ 24 | public func configure(closure: QuickConfigurer) { 25 | assert(!_isConfigurationFinalized, 26 | "Quick cannot be configured outside of a +[QuickConfiguration configure:] method. You should not call -[World configure:] directly. Instead, subclass QuickConfiguration and override the +[QuickConfiguration configure:] method.") 27 | closure(configuration: _configuration) 28 | } 29 | 30 | /** 31 | Finalizes the World's configuration. 32 | Any subsequent calls to World.configure() will raise. 33 | */ 34 | public func finalizeConfiguration() { 35 | _isConfigurationFinalized = true 36 | } 37 | 38 | public var currentExampleGroup: ExampleGroup? 39 | 40 | public var isRunningAdditionalSuites = false 41 | 42 | public func rootExampleGroupForSpecClass(cls: AnyClass) -> ExampleGroup { 43 | let name = NSStringFromClass(cls) 44 | if let group = _specs[name] { 45 | return group 46 | } else { 47 | let group = ExampleGroup(description: "root example group", 48 | isInternalRootExampleGroup: true) 49 | _specs[name] = group 50 | return group 51 | } 52 | } 53 | 54 | var exampleCount: Int { 55 | get { 56 | var count = 0 57 | for (_, group) in _specs { 58 | group.walkDownExamples { (example: Example) -> () in 59 | _ = ++count 60 | } 61 | } 62 | return count 63 | } 64 | } 65 | 66 | func registerSharedExample(name: String, closure: SharedExampleClosure) { 67 | _raiseIfSharedExampleAlreadyRegistered(name) 68 | _sharedExamples[name] = closure 69 | } 70 | 71 | func _raiseIfSharedExampleAlreadyRegistered(name: String) { 72 | if _sharedExamples[name] != nil { 73 | NSException(name: NSInternalInconsistencyException, 74 | reason: "A shared example named '\(name)' has already been registered.", 75 | userInfo: nil).raise() 76 | } 77 | } 78 | 79 | func sharedExample(name: String) -> SharedExampleClosure { 80 | _raiseIfSharedExampleNotRegistered(name) 81 | return _sharedExamples[name]! 82 | } 83 | 84 | func _raiseIfSharedExampleNotRegistered(name: String) { 85 | if _sharedExamples[name] == nil { 86 | NSException(name: NSInternalInconsistencyException, 87 | reason: "No shared example named '\(name)' has been registered. Registered shared examples: '\(Array(_sharedExamples.keys))'", 88 | userInfo: nil).raise() 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /QuickTests/ExampleMetadataFunctionalTests.swift: -------------------------------------------------------------------------------- 1 | import Quick 2 | import Nimble 3 | 4 | class ExampleMetadataFunctionalTestsSpec: QuickSpec { 5 | override func spec() { 6 | var currentExampleName = "" 7 | var lastExampleName = "" 8 | 9 | beforeEach { (exampleMetadata: ExampleMetadata) -> () in 10 | currentExampleName = exampleMetadata.example.name 11 | } 12 | 13 | afterEach { (exampleMetadata: ExampleMetadata) -> () in 14 | lastExampleName = exampleMetadata.example.name 15 | } 16 | 17 | it("calls beforeEach with the metadata for the first example") { 18 | expect(currentExampleName).to(contain("calls beforeEach with the metadata")) 19 | } 20 | 21 | it("calls afterEach with the metadata for the first example") { 22 | expect(lastExampleName).to(contain("calls beforeEach with the metadata")) 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /QuickTests/Fixtures/FunctionalTests_SharedExamplesTests_SharedExamples.swift: -------------------------------------------------------------------------------- 1 | import Quick 2 | import Nimble 3 | 4 | class FunctionalTests_SharedExamplesTests_SharedExamples: QuickConfiguration { 5 | override class func configure(configuration: Configuration) { 6 | sharedExamples("a group of three shared examples") { 7 | it("passes once") { expect(true).to(beTruthy()) } 8 | it("passes twice") { expect(true).to(beTruthy()) } 9 | it("passes three times") { expect(true).to(beTruthy()) } 10 | } 11 | 12 | sharedExamples("shared examples that take a context") { (sharedExampleContext: SharedExampleContext) in 13 | it("is passed the correct parameters via the context") { 14 | let callsite = sharedExampleContext()["callsite"] as String 15 | expect(callsite).to(equal("SharedExamplesSpec")) 16 | } 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /QuickTests/Fixtures/Person.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | class Person: NSObject { 4 | var isHappy = true 5 | var isHungry = false 6 | var isSatisfied = false 7 | var hopes = ["winning the lottery", "going on a blimp ride"] 8 | var smalltalk = "Come here often?" 9 | var valediction = "See you soon." 10 | 11 | var greeting: String { 12 | get { 13 | if isHappy { 14 | return "Hello!" 15 | } else { 16 | return "Oh, hi." 17 | } 18 | } 19 | } 20 | 21 | func eatChineseFood() { 22 | let after = dispatch_time(DISPATCH_TIME_NOW, 500000000) 23 | dispatch_after(after, dispatch_get_main_queue()) { 24 | self.isHungry = true 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /QuickTests/Fixtures/Poet.swift: -------------------------------------------------------------------------------- 1 | class Poet: Person { 2 | override var greeting: String { 3 | get { 4 | if isHappy { 5 | return "Oh, joyous day!" 6 | } else { 7 | return "Woe is me!" 8 | } 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /QuickTests/FunctionalTests+ObjC.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | QuickConfigurationBegin(FunctionalTestsObjCSharedExampleGroups) 5 | 6 | + (void)configure:(Configuration *)configuration { 7 | sharedExamples(@"a truthy value", ^(QCKDSLSharedExampleContext sharedExampleContext) { 8 | __block NSNumber *value = nil; 9 | beforeEach(^{ 10 | value = sharedExampleContext()[@"value"]; 11 | }); 12 | 13 | it(@"is true", ^{ 14 | expect(value).to(beTruthy()); 15 | }); 16 | }); 17 | } 18 | 19 | QuickConfigurationEnd 20 | 21 | static BOOL beforeSuiteExecuted_afterSuiteNotYetExecuted = NO; 22 | 23 | QuickSpecBegin(FunctionalTestsObjC) 24 | 25 | beforeSuite(^{ 26 | beforeSuiteExecuted_afterSuiteNotYetExecuted = YES; 27 | }); 28 | 29 | afterSuite(^{ 30 | beforeSuiteExecuted_afterSuiteNotYetExecuted = NO; 31 | }); 32 | 33 | describe(@"a describe block", ^{ 34 | it(@"contains an it block", ^{ 35 | expect(@(beforeSuiteExecuted_afterSuiteNotYetExecuted)).to(beTruthy()); 36 | }); 37 | 38 | itBehavesLike(@"a truthy value", ^{ 39 | return @{ @"value": @YES }; 40 | }); 41 | 42 | pending(@"a pending block", ^{ 43 | it(@"contains a failing it block", ^{ 44 | expect(@NO).to(beTruthy()); 45 | }); 46 | }); 47 | 48 | xdescribe(@"a pending (shorthand) describe block", ^{ 49 | it(@"contains a failing it block", ^{ 50 | expect(@NO).to(beTruthy()); 51 | }); 52 | }); 53 | 54 | xcontext(@"a pending (shorthand) context block", ^{ 55 | it(@"contains a failing it block", ^{ 56 | expect(@NO).to(beTruthy()); 57 | }); 58 | }); 59 | 60 | xit(@"contains a pending (shorthand) it block", ^{ 61 | expect(@NO).to(beTruthy()); 62 | }); 63 | }); 64 | 65 | QuickSpecEnd 66 | -------------------------------------------------------------------------------- /QuickTests/FunctionalTests.swift: -------------------------------------------------------------------------------- 1 | import Quick 2 | import Nimble 3 | 4 | var dinosaursExtinct = false 5 | var mankindExtinct = false 6 | 7 | class FunctionalSharedExamples: QuickConfiguration { 8 | override class func configure(configuration: Configuration) { 9 | sharedExamples("something living after dinosaurs are extinct") { 10 | it("no longer deals with dinosaurs") { 11 | expect(dinosaursExtinct).to(beTruthy()) 12 | } 13 | } 14 | 15 | sharedExamples("an optimistic person") { (sharedExampleContext: SharedExampleContext) in 16 | var person: Person! 17 | beforeEach { 18 | person = sharedExampleContext()["person"] as Person 19 | } 20 | 21 | it("is happy") { 22 | expect(person.isHappy).to(beTruthy()) 23 | } 24 | 25 | it("is a dreamer") { 26 | expect(person.hopes).to(contain("winning the lottery")) 27 | } 28 | } 29 | } 30 | } 31 | 32 | class PersonSpec: QuickSpec { 33 | override func spec() { 34 | describe("Person") { 35 | var person: Person! = nil 36 | 37 | beforeSuite { 38 | assert(!dinosaursExtinct, "nothing goes extinct twice") 39 | dinosaursExtinct = true 40 | } 41 | 42 | afterSuite { 43 | assert(!mankindExtinct, "tests shouldn't run after the apocalypse") 44 | mankindExtinct = true 45 | } 46 | 47 | beforeEach { person = Person() } 48 | afterEach { person = nil } 49 | 50 | it("gets hungry") { 51 | person!.eatChineseFood() 52 | expect{person.isHungry}.toEventually(beTruthy()) 53 | } 54 | 55 | it("will never be satisfied") { 56 | expect{person.isSatisfied}.toEventuallyNot(beTruthy()) 57 | } 58 | 59 | it("🔥🔥それでも俺たちは🔥🔥") { 60 | expect{person.isSatisfied}.toEventuallyNot(beTruthy()) 61 | } 62 | 63 | pending("but one day") { 64 | it("will never want for anything") { 65 | expect{person.isSatisfied}.toEventually(beTruthy()) 66 | } 67 | } 68 | 69 | it("does not live with dinosaurs") { 70 | expect(dinosaursExtinct).to(beTruthy()) 71 | expect(mankindExtinct).notTo(beTruthy()) 72 | } 73 | 74 | describe("greeting") { 75 | context("when the person is unhappy") { 76 | beforeEach { person.isHappy = false } 77 | it("is lukewarm") { 78 | expect(person.greeting).to(equal("Oh, hi.")) 79 | expect(person.greeting).notTo(equal("Hello!")) 80 | } 81 | } 82 | 83 | context("when the person is happy") { 84 | beforeEach { person!.isHappy = true } 85 | it("is enthusiastic") { 86 | expect(person.greeting).to(equal("Hello!")) 87 | expect(person.greeting).notTo(equal("Oh, hi.")) 88 | } 89 | } 90 | } 91 | 92 | xdescribe("smalltalk") { 93 | context("when the person is unhappy") { 94 | beforeEach { person.isHappy = false } 95 | it("is lukewarm") { 96 | expect{person.smalltalk}.to(equal("Weather's nice.")) 97 | expect{person.smalltalk}.notTo(equal("How are you!?")) 98 | } 99 | } 100 | 101 | context("when the person is happy") { 102 | beforeEach { person.isHappy = true } 103 | it("is enthusiastic") { 104 | expect{person.smalltalk}.to(equal("How are you!?")) 105 | expect{person.smalltalk}.notTo(equal("Weather's nice.")) 106 | } 107 | } 108 | } 109 | 110 | describe("valediction") { 111 | xcontext("when the person is unhappy") { 112 | beforeEach { person.isHappy = false } 113 | it("is lukewarm") { 114 | expect{person.valediction}.to(equal("Bye then.")) 115 | expect{person.valediction}.notTo(equal("I'll miss you!")) 116 | } 117 | } 118 | 119 | context("when the person is happy") { 120 | beforeEach { person.isHappy = true } 121 | xit("is enthusiastic") { 122 | expect{person.valediction}.to(equal("I'll miss you!")) 123 | expect{person.valediction}.notTo(equal("Bye then.")) 124 | } 125 | } 126 | } 127 | } 128 | } 129 | } 130 | 131 | class PoetSpec: QuickSpec { 132 | override func spec() { 133 | describe("Poet") { 134 | // FIXME: Radar worthy? `var poet: Poet?` results in build error: 135 | // "Could not find member 'greeting'" 136 | var poet: Person! = nil 137 | beforeEach { poet = Poet() } 138 | 139 | describe("greeting") { 140 | context("when the poet is unhappy") { 141 | beforeEach { poet.isHappy = false } 142 | it("is dramatic") { 143 | expect(poet.greeting).to(equal("Woe is me!")) 144 | } 145 | } 146 | 147 | context("when the poet is happy") { 148 | beforeEach { poet.isHappy = true } 149 | it("is joyous") { 150 | expect(poet.greeting).to(equal("Oh, joyous day!")) 151 | } 152 | } 153 | } 154 | } 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /QuickTests/FunctionalTests/AfterEachTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import Quick 3 | import Nimble 4 | 5 | var outerAfterEachExecutedCount = 0 6 | var innerAfterEachExecutedCount = 0 7 | var noExamplesAfterEachExecutedCount = 0 8 | 9 | class FunctionalTests_AfterEachSpec: QuickSpec { 10 | override func spec() { 11 | beforeEach { outerAfterEachExecutedCount += 1 } 12 | it("executes the outer afterEach once") {} 13 | it("executes the outer afterEach a second time") {} 14 | 15 | context("when there are nested beforeEach") { 16 | beforeEach { innerAfterEachExecutedCount += 1 } 17 | it("executes the outer and inner afterEach") {} 18 | } 19 | 20 | context("when there are nested afterEach without examples") { 21 | beforeEach { noExamplesAfterEachExecutedCount += 1 } 22 | } 23 | } 24 | } 25 | 26 | class AfterEachTests: XCTestCase { 27 | override func setUp() { 28 | super.setUp() 29 | outerAfterEachExecutedCount = 0 30 | innerAfterEachExecutedCount = 0 31 | noExamplesAfterEachExecutedCount = 0 32 | } 33 | 34 | override func tearDown() { 35 | outerAfterEachExecutedCount = 0 36 | innerAfterEachExecutedCount = 0 37 | noExamplesAfterEachExecutedCount = 0 38 | super.tearDown() 39 | } 40 | 41 | func testOuterAfterEachIsExecutedOnceAfterEachExample() { 42 | qck_runSpec(FunctionalTests_AfterEachSpec.classForCoder()) 43 | XCTAssertEqual(outerAfterEachExecutedCount, 3) 44 | } 45 | 46 | func testInnerAfterEachIsExecutedOnceAfterEachInnerExample() { 47 | qck_runSpec(FunctionalTests_AfterEachSpec.classForCoder()) 48 | XCTAssertEqual(innerAfterEachExecutedCount, 1) 49 | } 50 | 51 | func testNoExamplesAfterEachIsNeverExecuted() { 52 | qck_runSpec(FunctionalTests_AfterEachSpec.classForCoder()) 53 | XCTAssertEqual(noExamplesAfterEachExecutedCount, 0) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /QuickTests/FunctionalTests/AfterSuiteTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import Quick 3 | import Nimble 4 | 5 | var afterSuiteWasExecuted = false 6 | 7 | class FunctionalTests_AfterSuite_AfterSuiteSpec: QuickSpec { 8 | override func spec() { 9 | afterSuite { 10 | afterSuiteWasExecuted = true 11 | } 12 | } 13 | } 14 | 15 | class FunctionalTests_AfterSuite_Spec: QuickSpec { 16 | override func spec() { 17 | it("is executed before afterSuite") { 18 | expect(afterSuiteWasExecuted).to(beFalsy()) 19 | } 20 | } 21 | } 22 | 23 | class AfterSuiteTests: XCTestCase { 24 | func testAfterSuiteIsNotExecutedBeforeAnyExamples() { 25 | // Execute the spec with an assertion after the one with an afterSuite. 26 | let specs = NSArray(objects: FunctionalTests_AfterSuite_AfterSuiteSpec.classForCoder(), 27 | FunctionalTests_AfterSuite_Spec.classForCoder()) 28 | let result = qck_runSpecs(specs) 29 | 30 | // Although this ensures that afterSuite is not called before any 31 | // examples, it doesn't test that it's ever called in the first place. 32 | XCTAssert(result.hasSucceeded) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /QuickTests/FunctionalTests/BeforeEachTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import Quick 3 | import Nimble 4 | 5 | var outerBeforeEachExecutedCount = 0 6 | var innerBeforeEachExecutedCount = 0 7 | var noExamplesBeforeEachExecutedCount = 0 8 | 9 | class FunctionalTests_BeforeEachSpec: QuickSpec { 10 | override func spec() { 11 | beforeEach { outerBeforeEachExecutedCount += 1 } 12 | it("executes the outer beforeEach once") {} 13 | it("executes the outer beforeEach a second time") {} 14 | 15 | context("when there are nested beforeEach") { 16 | beforeEach { innerBeforeEachExecutedCount += 1 } 17 | it("executes the outer and inner beforeEach") {} 18 | } 19 | 20 | context("when there are nested beforeEach without examples") { 21 | beforeEach { noExamplesBeforeEachExecutedCount += 1 } 22 | } 23 | } 24 | } 25 | 26 | class BeforeEachTests: XCTestCase { 27 | override func setUp() { 28 | super.setUp() 29 | outerBeforeEachExecutedCount = 0 30 | innerBeforeEachExecutedCount = 0 31 | noExamplesBeforeEachExecutedCount = 0 32 | } 33 | 34 | override func tearDown() { 35 | outerBeforeEachExecutedCount = 0 36 | innerBeforeEachExecutedCount = 0 37 | noExamplesBeforeEachExecutedCount = 0 38 | super.tearDown() 39 | } 40 | 41 | func testOuterBeforeEachIsExecutedOnceBeforeEachExample() { 42 | qck_runSpec(FunctionalTests_BeforeEachSpec.classForCoder()) 43 | XCTAssertEqual(outerBeforeEachExecutedCount, 3) 44 | } 45 | 46 | func testInnerBeforeEachIsExecutedOnceBeforeEachInnerExample() { 47 | qck_runSpec(FunctionalTests_BeforeEachSpec.classForCoder()) 48 | XCTAssertEqual(innerBeforeEachExecutedCount, 1) 49 | } 50 | 51 | func testNoExamplesBeforeEachIsNeverExecuted() { 52 | qck_runSpec(FunctionalTests_BeforeEachSpec.classForCoder()) 53 | XCTAssertEqual(noExamplesBeforeEachExecutedCount, 0) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /QuickTests/FunctionalTests/BeforeSuiteTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import Quick 3 | import Nimble 4 | 5 | var beforeSuiteWasExecuted = false 6 | 7 | class FunctionalTests_BeforeSuite_BeforeSuiteSpec: QuickSpec { 8 | override func spec() { 9 | beforeSuite { 10 | beforeSuiteWasExecuted = true 11 | } 12 | } 13 | } 14 | 15 | class FunctionalTests_BeforeSuite_Spec: QuickSpec { 16 | override func spec() { 17 | it("is executed after beforeSuite") { 18 | expect(beforeSuiteWasExecuted).to(beTruthy()) 19 | } 20 | } 21 | } 22 | 23 | class BeforeSuiteTests: XCTestCase { 24 | func testBeforeSuiteIsExecutedBeforeAnyExamples() { 25 | // Execute the spec with an assertion before the one with a beforeSuite 26 | let specs = NSArray(objects: FunctionalTests_BeforeSuite_Spec.classForCoder(), 27 | FunctionalTests_BeforeSuite_BeforeSuiteSpec.classForCoder()) 28 | let result = qck_runSpecs(specs) 29 | 30 | XCTAssert(result.hasSucceeded) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /QuickTests/FunctionalTests/Configuration/AfterEach/Configuration+AfterEach.swift: -------------------------------------------------------------------------------- 1 | import Quick 2 | 3 | public var FunctionalTests_Configuration_AfterEachWasExecuted = false 4 | 5 | class FunctionalTests_Configuration_AfterEach: QuickConfiguration { 6 | override class func configure(configuration: Configuration) { 7 | configuration.afterEach { 8 | FunctionalTests_Configuration_AfterEachWasExecuted = true 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /QuickTests/FunctionalTests/Configuration/AfterEach/Configuration+AfterEachTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import Quick 3 | import Nimble 4 | 5 | class Configuration_AfterEachSpec: QuickSpec { 6 | override func spec() { 7 | beforeEach { 8 | FunctionalTests_Configuration_AfterEachWasExecuted = false 9 | } 10 | it("is executed before the configuration afterEach") { 11 | expect(FunctionalTests_Configuration_AfterEachWasExecuted).to(beFalsy()) 12 | } 13 | } 14 | } 15 | 16 | class Configuration_AfterEachTests: XCTestCase { 17 | override func setUp() { 18 | super.setUp() 19 | FunctionalTests_Configuration_AfterEachWasExecuted = false 20 | } 21 | 22 | override func tearDown() { 23 | FunctionalTests_Configuration_AfterEachWasExecuted = false 24 | super.tearDown() 25 | } 26 | 27 | func testExampleIsRunAfterTheConfigurationBeforeEachIsExecuted() { 28 | qck_runSpec(Configuration_BeforeEachSpec.classForCoder()) 29 | XCTAssert(FunctionalTests_Configuration_AfterEachWasExecuted) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /QuickTests/FunctionalTests/Configuration/BeforeEach/Configuration+BeforeEach.swift: -------------------------------------------------------------------------------- 1 | import Quick 2 | 3 | public var FunctionalTests_Configuration_BeforeEachWasExecuted = false 4 | 5 | class FunctionalTests_Configuration_BeforeEach: QuickConfiguration { 6 | override class func configure(configuration: Configuration) { 7 | configuration.beforeEach { 8 | FunctionalTests_Configuration_BeforeEachWasExecuted = true 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /QuickTests/FunctionalTests/Configuration/BeforeEach/Configuration+BeforeEachTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import Quick 3 | import Nimble 4 | 5 | class Configuration_BeforeEachSpec: QuickSpec { 6 | override func spec() { 7 | it("is executed after the configuration beforeEach") { 8 | expect(FunctionalTests_Configuration_BeforeEachWasExecuted).to(beTruthy()) 9 | } 10 | } 11 | } 12 | 13 | class Configuration_BeforeEachTests: XCTestCase { 14 | override func setUp() { 15 | super.setUp() 16 | FunctionalTests_Configuration_BeforeEachWasExecuted = false 17 | } 18 | 19 | override func tearDown() { 20 | FunctionalTests_Configuration_BeforeEachWasExecuted = false 21 | super.tearDown() 22 | } 23 | 24 | func testExampleIsRunAfterTheConfigurationBeforeEachIsExecuted() { 25 | qck_runSpec(Configuration_BeforeEachSpec.classForCoder()) 26 | XCTAssert(FunctionalTests_Configuration_BeforeEachWasExecuted) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /QuickTests/FunctionalTests/FailureTests+ObjC.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import 4 | #import 5 | 6 | #import "QCKSpecRunner.h" 7 | 8 | static BOOL isRunningFunctionalTests = NO; 9 | 10 | #pragma mark - Spec 11 | 12 | QuickSpecBegin(FunctionalTests_FailureSpec) 13 | 14 | describe(@"a group of failing examples", ^{ 15 | it(@"passes", ^{ 16 | expect(@YES).to(beTruthy()); 17 | }); 18 | 19 | it(@"fails (but only when running the functional tests)", ^{ 20 | expect(@(isRunningFunctionalTests)).to(beFalsy()); 21 | }); 22 | 23 | it(@"fails again (but only when running the functional tests)", ^{ 24 | expect(@(isRunningFunctionalTests)).to(beFalsy()); 25 | }); 26 | }); 27 | 28 | QuickSpecEnd 29 | 30 | #pragma mark - Test Helpers 31 | 32 | /** 33 | Run the functional tests within a context that causes two test failures 34 | and return the result. 35 | */ 36 | static XCTestRun *qck_runFailureSpec(void) { 37 | isRunningFunctionalTests = YES; 38 | XCTestRun *result = qck_runSpec([FunctionalTests_FailureSpec class]); 39 | isRunningFunctionalTests = NO; 40 | 41 | return result; 42 | } 43 | 44 | #pragma mark - Tests 45 | 46 | @interface FailureTests : XCTestCase; @end 47 | 48 | @implementation FailureTests 49 | 50 | - (void)testFailureSpecHasSucceededIsFalse { 51 | XCTestRun *result = qck_runFailureSpec(); 52 | XCTAssertFalse(result.hasSucceeded); 53 | } 54 | 55 | - (void)testFailureSpecExecutedAllExamples { 56 | XCTestRun *result = qck_runFailureSpec(); 57 | XCTAssertEqual(result.executionCount, 3); 58 | } 59 | 60 | - (void)testFailureSpecFailureCountIsEqualToTheNumberOfFailingExamples { 61 | XCTestRun *result = qck_runFailureSpec(); 62 | XCTAssertEqual(result.failureCount, 2); 63 | } 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /QuickTests/FunctionalTests/ItTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import Quick 3 | import Nimble 4 | 5 | class FunctionalTests_ItSpec: QuickSpec { 6 | override func spec() { 7 | var exampleMetadata: ExampleMetadata? 8 | beforeEach { (metadata: ExampleMetadata) in exampleMetadata = metadata } 9 | 10 | it("") { 11 | expect(exampleMetadata!.example.name).to(equal("")) 12 | } 13 | 14 | it("has a description with セレクター名に使えない文字が入っている 👊💥") { 15 | let name = "has a description with セレクター名に使えない文字が入っている 👊💥" 16 | expect(exampleMetadata!.example.name).to(equal(name)) 17 | } 18 | } 19 | } 20 | 21 | class ItTests: XCTestCase { 22 | func testAllExamplesAreExecuted() { 23 | let result = qck_runSpec(FunctionalTests_ItSpec.classForCoder()) 24 | XCTAssertEqual(result.executionCount, 2 as UInt) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /QuickTests/FunctionalTests/PendingTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import Quick 3 | import Nimble 4 | 5 | var oneExampleBeforeEachExecutedCount = 0 6 | var onlyPendingExamplesBeforeEachExecutedCount = 0 7 | 8 | class FunctionalTests_PendingSpec: QuickSpec { 9 | override func spec() { 10 | pending("an example that will not run") { 11 | expect(true).to(beFalsy()) 12 | } 13 | 14 | describe("a describe block containing only one enabled example") { 15 | beforeEach { oneExampleBeforeEachExecutedCount += 1 } 16 | it("an example that will run") {} 17 | pending("an example that will not run") {} 18 | } 19 | 20 | describe("a describe block containing only pending examples") { 21 | beforeEach { onlyPendingExamplesBeforeEachExecutedCount += 1 } 22 | pending("an example that will not run") {} 23 | } 24 | } 25 | } 26 | 27 | class PendingTests: XCTestCase { 28 | override func setUp() { 29 | super.setUp() 30 | oneExampleBeforeEachExecutedCount = 0 31 | onlyPendingExamplesBeforeEachExecutedCount = 0 32 | } 33 | 34 | override func tearDown() { 35 | oneExampleBeforeEachExecutedCount = 0 36 | onlyPendingExamplesBeforeEachExecutedCount = 0 37 | super.tearDown() 38 | } 39 | 40 | func testAnOtherwiseFailingExampleWhenMarkedPendingDoesNotCauseTheSuiteToFail() { 41 | let result = qck_runSpec(FunctionalTests_PendingSpec.classForCoder()) 42 | XCTAssert(result.hasSucceeded) 43 | } 44 | 45 | func testBeforeEachOnlyRunForEnabledExamples() { 46 | qck_runSpec(FunctionalTests_PendingSpec.classForCoder()) 47 | XCTAssertEqual(oneExampleBeforeEachExecutedCount, 1) 48 | } 49 | 50 | func testBeforeEachDoesNotRunForContextsWithOnlyPendingExamples() { 51 | qck_runSpec(FunctionalTests_PendingSpec.classForCoder()) 52 | XCTAssertEqual(onlyPendingExamplesBeforeEachExecutedCount, 0) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /QuickTests/FunctionalTests/SharedExamples+BeforeEachTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import Quick 3 | import Nimble 4 | 5 | var specBeforeEachExecutedCount = 0 6 | var sharedExamplesBeforeEachExecutedCount = 0 7 | 8 | class FunctionalTests_SharedExamples_BeforeEachTests_SharedExamples: QuickConfiguration { 9 | override class func configure(configuration: Configuration) { 10 | sharedExamples("a group of three shared examples with a beforeEach") { 11 | beforeEach { sharedExamplesBeforeEachExecutedCount += 1 } 12 | it("passes once") {} 13 | it("passes twice") {} 14 | it("passes three times") {} 15 | } 16 | } 17 | } 18 | 19 | class FunctionalTests_SharedExamples_BeforeEachSpec: QuickSpec { 20 | override func spec() { 21 | beforeEach { specBeforeEachExecutedCount += 1 } 22 | it("executes the spec beforeEach once") {} 23 | itBehavesLike("a group of three shared examples with a beforeEach") 24 | } 25 | } 26 | 27 | class SharedExamples_BeforeEachTests: XCTestCase { 28 | override func setUp() { 29 | super.setUp() 30 | specBeforeEachExecutedCount = 0 31 | sharedExamplesBeforeEachExecutedCount = 0 32 | } 33 | 34 | override func tearDown() { 35 | specBeforeEachExecutedCount = 0 36 | sharedExamplesBeforeEachExecutedCount = 0 37 | super.tearDown() 38 | } 39 | 40 | func testBeforeEachOutsideOfSharedExamplesExecutedOnceBeforeEachExample() { 41 | qck_runSpec(FunctionalTests_SharedExamples_BeforeEachSpec.classForCoder()) 42 | XCTAssertEqual(specBeforeEachExecutedCount, 4) 43 | } 44 | 45 | func testBeforeEachInSharedExamplesExecutedOnceBeforeEachSharedExample() { 46 | qck_runSpec(FunctionalTests_SharedExamples_BeforeEachSpec.classForCoder()) 47 | XCTAssertEqual(sharedExamplesBeforeEachExecutedCount, 3) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /QuickTests/FunctionalTests/SharedExamplesTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import Quick 3 | import Nimble 4 | 5 | class FunctionalTests_SharedExamples_Spec: QuickSpec { 6 | override func spec() { 7 | itBehavesLike("a group of three shared examples") 8 | } 9 | } 10 | 11 | class FunctionalTests_SharedExamples_ContextSpec: QuickSpec { 12 | override func spec() { 13 | itBehavesLike("shared examples that take a context") { ["callsite": "SharedExamplesSpec"] } 14 | } 15 | } 16 | 17 | // Shared examples are defined in QuickTests/Fixtures 18 | class SharedExamplesTests: XCTestCase { 19 | func testAGroupOfThreeSharedExamplesExecutesThreeExamples() { 20 | let result = qck_runSpec(FunctionalTests_SharedExamples_Spec.classForCoder()) 21 | XCTAssert(result.hasSucceeded) 22 | XCTAssertEqual(result.executionCount, 3 as UInt) 23 | } 24 | 25 | func testSharedExamplesWithContextPassContextToExamples() { 26 | let result = qck_runSpec(FunctionalTests_SharedExamples_ContextSpec.classForCoder()) 27 | XCTAssert(result.hasSucceeded) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /QuickTests/Helpers/QCKSpecRunner.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | /** 4 | Runs an XCTestSuite instance containing only the given XCTestCase subclass. 5 | Use this to run QuickSpec subclasses from within a set of unit tests. 6 | 7 | Due to implicit dependencies in _XCTFailureHandler, this function raises an 8 | exception when used in Swift to run a failing test case. 9 | 10 | @param specClass The class of the spec to be run. 11 | @return An XCTestRun instance that contains information such as the number of failures, etc. 12 | */ 13 | extern XCTestRun *qck_runSpec(Class specClass); 14 | 15 | /** 16 | Runs an XCTestSuite instance containing the given XCTestCase subclasses, in the order provided. 17 | See the documentation for `qck_runSpec` for more details. 18 | 19 | @param specClasses An array of QuickSpec classes, in the order they should be run. 20 | @return An XCTestRun instance that contains information such as the number of failures, etc. 21 | */ 22 | extern XCTestRun *qck_runSpecs(NSArray *specClasses); 23 | -------------------------------------------------------------------------------- /QuickTests/Helpers/QCKSpecRunner.m: -------------------------------------------------------------------------------- 1 | #import "QCKSpecRunner.h" 2 | #import "XCTestObservationCenter.h" 3 | 4 | #import 5 | 6 | XCTestRun *qck_runSuite(XCTestSuite *suite) { 7 | [World sharedWorld].isRunningAdditionalSuites = YES; 8 | 9 | __block XCTestRun *result = nil; 10 | [[XCTestObservationCenter sharedObservationCenter] _suspendObservationForBlock:^{ 11 | result = [suite run]; 12 | }]; 13 | return result; 14 | } 15 | 16 | XCTestRun *qck_runSpec(Class specClass) { 17 | return qck_runSuite([XCTestSuite testSuiteForTestCaseClass:specClass]); 18 | } 19 | 20 | XCTestRun *qck_runSpecs(NSArray *specClasses) { 21 | XCTestSuite *suite = [XCTestSuite testSuiteWithName:@"MySpecs"]; 22 | for (Class specClass in specClasses) { 23 | [suite addTest:[XCTestSuite testSuiteForTestCaseClass:specClass]]; 24 | } 25 | 26 | return qck_runSuite(suite); 27 | } 28 | -------------------------------------------------------------------------------- /QuickTests/Helpers/QuickTestsBridgingHeader.h: -------------------------------------------------------------------------------- 1 | #import "QCKSpecRunner.h" 2 | -------------------------------------------------------------------------------- /QuickTests/Helpers/XCTestObservationCenter.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | /** 4 | Expose internal XCTest class and methods in order to run isolated XCTestSuite 5 | instances while the QuickTests test suite is running. 6 | 7 | If an Xcode upgrade causes QuickTests to crash when executing, or for tests to fail 8 | with the message "Timed out waiting for IDE barrier message to complete", it is 9 | likely that this internal interface has been changed. 10 | */ 11 | @interface XCTestObservationCenter : NSObject 12 | 13 | /** 14 | Returns the global instance of XCTestObservationCenter. 15 | */ 16 | + (instancetype)sharedObservationCenter; 17 | 18 | /** 19 | Suspends test suite observation for the duration that the block is executing. 20 | Any test suites that are executed within the block do not generate any log output. 21 | Failures are still reported. 22 | 23 | Use this method to run XCTestSuite objects while another XCTestSuite is running. 24 | Without this method, tests fail with the message: "Timed out waiting for IDE 25 | barrier message to complete". 26 | */ 27 | - (void)_suspendObservationForBlock:(void (^)(void))block; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /QuickTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | io.quick.${PRODUCT_NAME:rfc1034identifier} 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 | -------------------------------------------------------------------------------- /QuickTests/QuickConfigurationTests.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface QuickConfigurationTests : XCTestCase; @end 5 | 6 | @implementation QuickConfigurationTests 7 | 8 | - (void)testInitThrows { 9 | XCTAssertThrowsSpecificNamed([QuickConfiguration new], NSException, NSInternalInconsistencyException); 10 | } 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![](http://f.cl.ly/items/0r1E192C1R0b2g2Q3h2w/QuickLogo_Color.png) 2 | 3 | Quick is a behavior-driven development framework for Swift and Objective-C. 4 | Inspired by [RSpec](https://github.com/rspec/rspec), [Specta](https://github.com/specta/specta), and [Ginkgo](https://github.com/onsi/ginkgo). 5 | 6 | [![Build Status](https://travis-ci.org/Quick/Quick.svg)](https://travis-ci.org/Quick/Quick) 7 | 8 | ![](https://raw.githubusercontent.com/Quick/Assets/master/Screenshots/QuickSpec%20screenshot.png) 9 | 10 | ```swift 11 | // Swift 12 | 13 | import Quick 14 | import Nimble 15 | 16 | class TableOfContentsSpec: QuickSpec { 17 | override func spec() { 18 | describe("the table of contents below") { 19 | it("has everything you need to get started") { 20 | let sections = TableOfContents().sections 21 | expect(sections).to(contain("Quick: Examples and Example Groups")) 22 | expect(sections).to(contain("Nimble: Assertions using expect(...).to")) 23 | expect(sections).to(contain("How to Install Quick")) 24 | } 25 | 26 | context("if it doesn't have what you're looking for") { 27 | it("needs to be updated") { 28 | let you = You(awesome: true) 29 | expect{you.submittedAnIssue}.toEventually(beTruthy()) 30 | } 31 | } 32 | } 33 | } 34 | } 35 | ``` 36 | 37 | # How to Use Quick 38 | 39 | 40 | 41 | 42 | - [Quick: Examples and Example Groups](#quick-examples-and-example-groups) 43 | - [Examples Using `it`](#examples-using-it) 44 | - [Example Groups Using `describe` and `context`](#example-groups-using-describe-and-context) 45 | - [Describing Classes and Methods Using `describe`](#describing-classes-and-methods-using-describe) 46 | - [Sharing Setup/Teardown Code Using `beforeEach` and `afterEach`](#sharing-setupteardown-code-using-beforeeach-and-aftereach) 47 | - [Specifying Conditional Behavior Using `context`](#specifying-conditional-behavior-using-context) 48 | - [Temporarily Disabling Examples or Groups Using `pending`](#temporarily-disabling-examples-or-groups-using-pending) 49 | - [Shorthand syntax](#shorthand-syntax) 50 | - [Global Setup/Teardown Using `beforeSuite` and `afterSuite`](#global-setupteardown-using-beforesuite-and-aftersuite) 51 | - [Sharing Examples](#sharing-examples) 52 | - [Using Quick in Objective-C: The Optional Shorthand Syntax](#using-quick-in-objective-c-the-optional-shorthand-syntax) 53 | - [Nimble: Assertions Using `expect(...).to`](#nimble-assertions-using-expectto) 54 | - [Testing UIKit with Quick](#testing-uikit-with-quick) 55 | - [How to Install Quick](#how-to-install-quick) 56 | - [1. Clone the Quick and Nimble repositories](#1-clone-the-quick-and-nimble-repositories) 57 | - [2. Add `Quick.xcodeproj` and `Nimble.xcodeproj` to your test target](#2-add-quickxcodeproj-and-nimblexcodeproj-to-your-test-target) 58 | - [3. Link `Quick.framework` and `Nimble.framework`](#3-link-quickframework-and-nimbleframework) 59 | - [4. Start writing specs!](#4-start-writing-specs!) 60 | - [Including Quick in a Git Repository Using Submodules](#including-quick-in-a-git-repository-using-submodules) 61 | - [Adding Quick as a Git Submodule](#adding-quick-as-a-git-submodule) 62 | - [Updating the Quick Submodule](#updating-the-quick-submodule) 63 | - [Cloning a Repository that Includes a Quick Submodule](#cloning-a-repository-that-includes-a-quick-submodule) 64 | - [How to Install Quick File Templates](#how-to-install-quick-file-templates) 65 | - [Using Alcatraz](#using-alcatraz) 66 | - [Manually via the Rakefile](#manually-via-the-rakefile) 67 | - [Who Uses Quick](#who-uses-quick) 68 | - [License](#license) 69 | 70 | 71 | 72 | ## Quick: Examples and Example Groups 73 | 74 | Quick uses a special syntax to define **examples** and **example groups**. 75 | 76 | ### Examples Using `it` 77 | 78 | Examples, defined with the `it` function, use assertions to demonstrate 79 | how code should behave. These are like "tests" in XCTest. 80 | 81 | `it` takes two parameters: the name of the example, and a closure. 82 | The examples below specify how the `Dolphin` class should behave. 83 | A new dolphin should be smart and friendly: 84 | 85 | ```swift 86 | // Swift 87 | 88 | import Quick 89 | import Nimble 90 | 91 | class DolphinSpec: QuickSpec { 92 | override func spec() { 93 | it("is friendly") { 94 | expect(Dolphin().isFriendly).to(beTruthy()) 95 | } 96 | 97 | it("is smart") { 98 | expect(Dolphin().isSmart).to(beTruthy()) 99 | } 100 | } 101 | } 102 | ``` 103 | 104 | ```objc 105 | // Objective-C 106 | 107 | #import 108 | #import 109 | 110 | QuickSpecBegin(DolphinSpec) 111 | 112 | it(@"is friendly", ^{ 113 | expect(@([[Dolphin new] isFriendly])).to(beTruthy()); 114 | }); 115 | 116 | it(@"is smart", ^{ 117 | expect(@([[Dolphin new] isSmart])).to(beTruthy()); 118 | }); 119 | 120 | QuickSpecEnd 121 | ``` 122 | 123 | > Descriptions can use any character, including characters from languages 124 | besides English, or even emoji! :v: :sunglasses: 125 | 126 | ### Example Groups Using `describe` and `context` 127 | 128 | Example groups are logical groupings of examples. Example groups can share 129 | setup and teardown code. 130 | 131 | #### Describing Classes and Methods Using `describe` 132 | 133 | To specify the behavior of the `Dolphin` class's `click` method--in 134 | other words, to test the method works--several `it` examples can be 135 | grouped together using the `describe` function. Grouping similar 136 | examples together makes the spec easier to read: 137 | 138 | ```swift 139 | // Swift 140 | 141 | import Quick 142 | import Nimble 143 | 144 | class DolphinSpec: QuickSpec { 145 | override func spec() { 146 | describe("a dolphin") { 147 | describe("its click") { 148 | it("is loud") { 149 | let click = Dolphin().click() 150 | expect(click.isLoud).to(beTruthy()) 151 | } 152 | 153 | it("has a high frequency") { 154 | let click = Dolphin().click() 155 | expect(click.hasHighFrequency).to(beTruthy()) 156 | } 157 | } 158 | } 159 | } 160 | } 161 | ``` 162 | 163 | ```objc 164 | // Objective-C 165 | 166 | #import 167 | #import 168 | 169 | QuickSpecBegin(DolphinSpec) 170 | 171 | describe(@"a dolphin", ^{ 172 | describe(@"its click", ^{ 173 | it(@"is loud", ^{ 174 | Click *click = [[Dolphin new] click]; 175 | expect(@(click.isLoud)).to(beTruthy()); 176 | }); 177 | 178 | it(@"has a high frequency", ^{ 179 | Click *click = [[Dolphin new] click]; 180 | expect(@(click.hasHighFrequency)).to(beTruthy()); 181 | }); 182 | }); 183 | }); 184 | 185 | QuickSpecEnd 186 | ``` 187 | 188 | #### Sharing Setup/Teardown Code Using `beforeEach` and `afterEach` 189 | 190 | Example groups don't just make the examples clearer, they're also useful 191 | for sharing setup and teardown code among examples in a group. 192 | 193 | In the example below, the `beforeEach` function is used to create a brand 194 | new instance of a dolphin and its click before each example in the group. 195 | This ensures that both are in a "fresh" state for every example: 196 | 197 | ```swift 198 | // Swift 199 | 200 | import Quick 201 | import Nimble 202 | 203 | class DolphinSpec: QuickSpec { 204 | override func spec() { 205 | describe("a dolphin") { 206 | var dolphin: Dolphin? 207 | beforeEach { 208 | dolphin = Dolphin() 209 | } 210 | 211 | describe("its click") { 212 | var click: Click? 213 | beforeEach { 214 | click = dolphin!.click() 215 | } 216 | 217 | it("is loud") { 218 | expect(click!.isLoud).to(beTruthy()) 219 | } 220 | 221 | it("has a high frequency") { 222 | expect(click!.hasHighFrequency).to(beTruthy()) 223 | } 224 | } 225 | } 226 | } 227 | } 228 | ``` 229 | 230 | ```objc 231 | // Objective-C 232 | 233 | #import 234 | #import 235 | 236 | QuickSpecBegin(DolphinSpec) 237 | 238 | describe(@"a dolphin", ^{ 239 | __block Dolphin *dolphin = nil; 240 | beforeEach(^{ 241 | dolphin = [Dolphin new]; 242 | }); 243 | 244 | describe(@"its click", ^{ 245 | __block Click *click = nil; 246 | beforeEach(^{ 247 | click = [dolphin click]; 248 | }); 249 | 250 | it(@"is loud", ^{ 251 | expect(@(click.isLoud)).to(beTruthy()); 252 | }); 253 | 254 | it(@"has a high frequency", ^{ 255 | expect(@(click.hasHighFrequency)).to(beTruthy()); 256 | }); 257 | }); 258 | }); 259 | 260 | QuickSpecEnd 261 | ``` 262 | 263 | Sharing setup like this might not seem like a big deal with the 264 | dolphin example, but for more complicated objects, it saves a lot 265 | of typing! 266 | 267 | To execute code *after* each example, use `afterEach`. 268 | 269 | #### Specifying Conditional Behavior Using `context` 270 | 271 | Dolphins use clicks for echolocation. When they approach something 272 | particularly interesting to them, they release a series of clicks in 273 | order to get a better idea of what it is. 274 | 275 | The tests need to show that the `click` method behaves differently in 276 | different circumstances. Normally, the dolphin just clicks once. But when 277 | the dolphin is close to something interesting, it clicks several times. 278 | 279 | This can be expressed using `context` functions: one `context` for the 280 | normal case, and one `context` for when the dolphin is close to 281 | something interesting: 282 | 283 | ```swift 284 | // Swift 285 | 286 | import Quick 287 | import Nimble 288 | 289 | class DolphinSpec: QuickSpec { 290 | override func spec() { 291 | describe("a dolphin") { 292 | var dolphin: Dolphin? 293 | beforeEach { dolphin = Dolphin() } 294 | 295 | describe("its click") { 296 | context("when the dolphin is not near anything interesting") { 297 | it("is only emitted once") { 298 | expect(dolphin!.click().count).to(equal(1)) 299 | } 300 | } 301 | 302 | context("when the dolphin is near something interesting") { 303 | beforeEach { 304 | let ship = SunkenShip() 305 | Jamaica.dolphinCove.add(ship) 306 | Jamaica.dolphinCove.add(dolphin) 307 | } 308 | 309 | it("is emitted three times") { 310 | expect(dolphin!.click().count).to(equal(3)) 311 | } 312 | } 313 | } 314 | } 315 | } 316 | } 317 | ``` 318 | 319 | ```objc 320 | // Objective-C 321 | 322 | #import 323 | #import 324 | 325 | QuickSpecBegin(DolphinSpec) 326 | 327 | describe(@"a dolphin", ^{ 328 | __block Dolphin *dolphin = nil; 329 | beforeEach(^{ dolphin = [Dolphin new]; }); 330 | 331 | describe(@"its click", ^{ 332 | context(@"when the dolphin is not near anything interesting", ^{ 333 | it(@"is only emitted once", ^{ 334 | expect(@([[dolphin click] count])).to(equal(@1)); 335 | }); 336 | }); 337 | 338 | context(@"when the dolphin is near something interesting", ^{ 339 | beforeEach(^{ 340 | [[Jamaica dolphinCove] add:[SunkenShip new]]; 341 | [[Jamaica dolphinCove] add:dolphin]; 342 | }); 343 | 344 | it(@"is emitted three times", ^{ 345 | expect(@([[dolphin click] count])).to(equal(@3)); 346 | }); 347 | }); 348 | }); 349 | }); 350 | 351 | QuickSpecEnd 352 | ``` 353 | 354 | ### Temporarily Disabling Examples or Groups Using `pending` 355 | 356 | For examples that don't pass yet, use `pending`. Pending examples 357 | are not run, but are printed out along with the test results. 358 | 359 | The example below marks the cases in which the dolphin is close to 360 | something interesting as "pending"--perhaps that functionality hasn't 361 | been implemented yet, but these tests have been written as reminders 362 | that it should be soon: 363 | 364 | ```swift 365 | // Swift 366 | 367 | pending("when the dolphin is near something interesting") { 368 | // ...none of the code in this closure will be run. 369 | } 370 | ``` 371 | 372 | ```objc 373 | // Objective-C 374 | 375 | pending(@"when the dolphin is near something interesting", ^{ 376 | // ...none of the code in this closure will be run. 377 | }); 378 | ``` 379 | 380 | #### Shorthand syntax 381 | 382 | Examples and groups can also be marked as pending by using 383 | `xdescribe`, `xcontext`, and `xit`: 384 | 385 | ```swift 386 | // Swift 387 | 388 | xdescribe("its click") { 389 | // ...none of the code in this closure will be run. 390 | } 391 | 392 | xcontext("when the dolphin is not near anything interesting") { 393 | // ...none of the code in this closure will be run. 394 | } 395 | 396 | xit("is only emitted once") { 397 | // ...none of the code in this closure will be run. 398 | } 399 | ``` 400 | 401 | ```objc 402 | // Objective-C 403 | 404 | xdescribe(@"its click", ^{ 405 | // ...none of the code in this closure will be run. 406 | }); 407 | 408 | xcontext(@"when the dolphin is not near anything interesting", ^{ 409 | // ...none of the code in this closure will be run. 410 | }); 411 | 412 | xit(@"is only emitted once", ^{ 413 | // ...none of the code in this closure will be run. 414 | }); 415 | ``` 416 | 417 | ### Global Setup/Teardown Using `beforeSuite` and `afterSuite` 418 | 419 | Some test setup needs to be performed before *any* examples are 420 | run. For these cases, use `beforeSuite` and `afterSuite`. 421 | 422 | In the example below, a database of all the creatures in the ocean is 423 | created before any examples are run. That database is torn down once all 424 | the examples have finished: 425 | 426 | ```swift 427 | // Swift 428 | 429 | import Quick 430 | 431 | class DolphinSpec: QuickSpec { 432 | override func spec() { 433 | beforeSuite { 434 | OceanDatabase.createDatabase(name: "test.db") 435 | OceanDatabase.connectToDatabase(name: "test.db") 436 | } 437 | 438 | afterSuite { 439 | OceanDatabase.teardownDatabase(name: "test.db") 440 | } 441 | 442 | describe("a dolphin") { 443 | // ... 444 | } 445 | } 446 | } 447 | ``` 448 | 449 | ```objc 450 | // Objective-C 451 | 452 | #import 453 | 454 | QuickSpecBegin(DolphinSpec) 455 | 456 | beforeSuite(^{ 457 | [OceanDatabase createDatabase:@"test.db"]; 458 | [OceanDatabase connectToDatabase:@"test.db"]; 459 | }); 460 | 461 | afterSuite(^{ 462 | [OceanDatabase teardownDatabase:@"test.db"]; 463 | }); 464 | 465 | describe(@"a dolphin", ^{ 466 | // ... 467 | }); 468 | 469 | QuickSpecEnd 470 | ``` 471 | 472 | > You can specify as many `beforeSuite` and `afterSuite` as you like. All 473 | `beforeSuite` closures will be executed before any tests run, and all 474 | `afterSuite` closures will be executed after all the tests are finished. 475 | There is no guarantee as to what order these closures will be executed in. 476 | 477 | ### Sharing Examples 478 | 479 | In some cases, the same set of specifications apply to multiple objects. 480 | 481 | For example, consider a protocol called `Edible`. When a dolphin 482 | eats something `Edible`, the dolphin becomes happy. `Mackerel` and 483 | `Cod` are both edible. Quick allows you to easily test that a dolphin is 484 | happy to eat either one. 485 | 486 | The example below defines a set of "shared examples" for "something edible", 487 | and specifies that both mackerel and cod behave like "something edible": 488 | 489 | ```swift 490 | // Swift 491 | 492 | import Quick 493 | import Nimble 494 | 495 | class EdibleSharedExamplesConfiguration: QuickConfiguration { 496 | override class func configure(configuration: Configuration) { 497 | sharedExamples("something edible") { (sharedExampleContext: SharedExampleContext) in 498 | it("makes dolphins happy") { 499 | let dolphin = Dolphin(happy: false) 500 | let edible = sharedExampleContext()["edible"] 501 | dolphin.eat(edible) 502 | expect(dolphin.isHappy).to(beTruthy()) 503 | } 504 | } 505 | } 506 | } 507 | 508 | class MackerelSpec: QuickSpec { 509 | override func spec() { 510 | var mackerel: Mackerel! = nil 511 | beforeEach { 512 | mackerel = Mackerel() 513 | } 514 | 515 | itBehavesLike("something edible") { ["edible": mackerel] } 516 | } 517 | } 518 | 519 | class CodSpec: QuickSpec { 520 | override func spec() { 521 | var cod: Cod! = nil 522 | beforeEach { 523 | cod = Cod() 524 | } 525 | 526 | itBehavesLike("something edible") { ["edible": cod] } 527 | } 528 | } 529 | ``` 530 | 531 | ```objc 532 | // Objective-C 533 | 534 | #import 535 | #import 536 | 537 | QuickConfigurationBegin(EdibleSharedExamplesConfiguration) 538 | 539 | + (void)configure:(Configuration *configuration) { 540 | sharedExamples(@"something edible", ^(QCKDSLSharedExampleContext exampleContext) { 541 | it(@"makes dolphins happy") { 542 | Dolphin *dolphin = [[Dolphin alloc] init]; 543 | dolphin.happy = NO; 544 | id edible = exampleContext()[@"edible"]; 545 | [dolphin eat:edible]; 546 | expect(dolphin.isHappy).to(beTruthy()) 547 | } 548 | }); 549 | } 550 | 551 | QuickConfigurationEnd 552 | 553 | QuickSpecBegin(MackerelSpec) 554 | 555 | __block Mackerel *mackerel = nil; 556 | beforeEach(^{ 557 | mackerel = [[Mackerel alloc] init]; 558 | }); 559 | 560 | itBehavesLike(@"someting edible", ^{ return @{ @"edible": mackerel }; }); 561 | 562 | QuickSpecEnd 563 | 564 | QuickSpecBegin(CodSpec) 565 | 566 | __block Mackerel *cod = nil; 567 | beforeEach(^{ 568 | cod = [[Cod alloc] init]; 569 | }); 570 | 571 | itBehavesLike(@"someting edible", ^{ return @{ @"edible": cod }; }); 572 | 573 | QuickSpecEnd 574 | ``` 575 | 576 | Shared examples can include any number of `it`, `context`, and 577 | `describe` blocks. They save a *lot* of typing when running 578 | the same tests against several different kinds of objects. 579 | 580 | In some cases, you won't need any additional context. In Swift, you can 581 | simply use `sharedExampleFor` closures that take no parameters. This 582 | might be useful when testing some sort of global state: 583 | 584 | ```swift 585 | // Swift 586 | 587 | import Quick 588 | 589 | sharedExamplesFor("everything under the sea") { 590 | // ... 591 | } 592 | 593 | itBehavesLike("everything under the sea") 594 | ``` 595 | 596 | > In Objective-C, you'll have to pass a block that takes a 597 | `QCKDSLSharedExampleContext`, even if you don't plan on using that 598 | argument. Sorry, but that's the way the cookie crumbles! 599 | :cookie: :bomb: 600 | 601 | ## Using Quick in Objective-C: The Optional Shorthand Syntax 602 | 603 | Quick works equally well in both Swift and Objective-C. 604 | 605 | Importing Quick in an Objective-C file defines macros named `it` and 606 | `itShouldBehaveLike`, as well as functions like `context()`, `describe()`, etc. 607 | If the project you are testing also defines symbols with these names, you may 608 | encounter confusing build failures. In that case, you can avoid namespace 609 | collision by turning off Quick's optional "shorthand" syntax: 610 | 611 | ```objc 612 | #define QUICK_DISABLE_SHORT_SYNTAX 1 613 | 614 | #import 615 | 616 | QuickSpecBegin(DolphinSpec) 617 | // ... 618 | QuickSpecEnd 619 | ``` 620 | 621 | You must define the `QUICK_DISABLE_SHORT_SYNTAX` macro *before* 622 | importing the Quick header. 623 | 624 | ## Nimble: Assertions Using `expect(...).to` 625 | 626 | Quick provides an easy language to define examples and example groups. Within those 627 | examples, [Nimble](https://github.com/Quick/Nimble) provides a simple 628 | language to define expectations--that is, to assert that code behaves a 629 | certain way, and to display a test failure if it doesn't. 630 | 631 | Nimble expectations use the `expect(...).to` syntax: 632 | 633 | ```swift 634 | // Swift 635 | 636 | import Nimble 637 | 638 | expect(person.greeting).to(equal("Oh, hi.")) 639 | expect(person.greeting).notTo(equal("Hello!")) 640 | expect(person.isHappy).toEventually(beTruthy()) 641 | ``` 642 | 643 | ```objc 644 | // Objective-C 645 | 646 | #import 647 | 648 | expect(person.greeting).to(equal(@"Oh, hi.")); 649 | expect(person.greeting).notTo(equal(@"Hello!")); 650 | expect(@(person.isHappy)).toEventually(beTruthy()); 651 | ``` 652 | 653 | You can find much more detailed documentation on 654 | [Nimble](https://github.com/Quick/Nimble), including a 655 | full set of available matchers and details on how to perform asynchronous tests, 656 | in [the project's README](https://github.com/Quick/Nimble). 657 | 658 | ## Testing UIKit with Quick 659 | 660 | Quick can be used for testing UIKit interaction as well. Say, for example, we have a `DolphinTableViewController` that displays one cell with label `Bottlenose`. We want to test that the cell gets displayed when the view is loaded. Additionally, we would like to delete the row upon selecting it. An approach might be: 661 | 662 | ```swift 663 | // Swift 664 | 665 | import UIKit 666 | import Quick 667 | import Nimble 668 | 669 | class DolphinTableViewControllerSpecs: QuickSpec { 670 | override func spec() { 671 | var viewController: DolphinTableViewController! 672 | 673 | beforeEach { 674 | viewController = DolphinTableViewController() 675 | } 676 | 677 | describe("viewDidLoad") { 678 | beforeEach { 679 | // Accessing the view property causes the UIKit framework to trigger the necessary methods to render the view. 680 | viewController.view 681 | } 682 | 683 | 684 | it("loads the table view with one cell") { 685 | let tableView = viewController.tableView 686 | 687 | var indexPath = NSIndexPath(forRow: 0, inSection: 0) 688 | var cell = viewController.tableView(tableView, cellForRowAtIndexPath: indexPath) 689 | 690 | expect(cell.textLabel?.text).to(equal("Bottlenose")) 691 | } 692 | } 693 | 694 | describe("didSelectRowAtIndexPath") { 695 | beforeEach { 696 | // Causes the UIKit framework to trigger the necessary methods to render the view and perform viewWillAppear: and viewDidAppear: callbacks 697 | viewController.beginAppearanceTransition(true, animated: false) 698 | viewController.endAppearanceTransition() 699 | } 700 | 701 | it("deletes the selected row and reloads the tableView's data") { 702 | let tableView = viewController.tableView 703 | let indexPath = NSIndexPath(forRow: 0, inSection: 0) 704 | 705 | viewController.tableView(tableView, didSelectRowAtIndexPath: indexPath) 706 | 707 | var cell = viewController.tableView(tableView, cellForRowAtIndexPath: indexPath) 708 | expect(cell.textLabel?.text).to(beNil()) 709 | } 710 | } 711 | } 712 | } 713 | ``` 714 | 715 | ```objc 716 | // Objective-C 717 | 718 | #import 719 | #import 720 | #import 721 | 722 | QuickSpecBegin(DolphinTableViewControllerSpec) 723 | 724 | describe(@"viewDidLoad") { 725 | __block DolphinTableViewController *viewController = nil; 726 | 727 | beforeEach(^{ 728 | viewController = [[DolphinTableViewController alloc] init]; 729 | }); 730 | 731 | it(@"loads the table view with three types of dolphin", ^{ 732 | beforeEach(^{ 733 | // Accessing the view property causes the UIKit framework to trigger the necessary methods to render the view. 734 | [viewController view]; 735 | }); 736 | 737 | UITableView *tableView = [viewController tableView]; 738 | NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; 739 | UITableViewCell *cell = [viewController tableView:tableView cellForRowAtIndexPath:indexPath]; 740 | 741 | expect(@([[cell textLabel] text])).to(equal(@"Bottlenose")); 742 | }); 743 | } 744 | 745 | describe(@"didSelectRowAtIndexPath") { 746 | __block DolphinTableViewController *viewController = nil; 747 | 748 | beforeEach(^{ 749 | // Causes the UIKit framework to trigger the necessary methods to render the view and perform viewWillAppear: and 750 | viewController = [[DolphinTableViewController alloc] init]; 751 | [viewController beginAppearanceTransition:YES animated:NO]; 752 | [viewController endAppearanceTransition]; 753 | }); 754 | 755 | it(@"deletes the selected row and reloads the tableView's data", ^{ 756 | UITableView *tableView = [viewController tableView]; 757 | NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; 758 | 759 | [viewController tableView:tableView didSelectRowAtIndexPath:indexPath]; 760 | 761 | UITableViewCell *cell = [viewController tableView:tableView cellForRowAtIndexPath:indexPath]; 762 | 763 | expect(@([[cell textLabel] text])).to(beNil()); 764 | }); 765 | } 766 | 767 | QuickSpecEnd 768 | ``` 769 | 770 | ## How to Install Quick 771 | 772 | > This module is beta software, it currently supports Xcode 6 Beta 4. 773 | 774 | Quick provides the syntax to define examples and example groups. Nimble 775 | provides the `expect(...).to` assertion syntax. You may use either one, 776 | or both, in your tests. 777 | 778 | To use Quick and Nimble to test your iOS or OS X applications, follow these 4 easy steps: 779 | 780 | 1. [Clone the Quick and Nimble repositories](#1-clone-the-quick-and-nimble-repositories) 781 | 2. [Add `Quick.xcodeproj` and `Nimble.xcodeproj` to your test target](#2-add-quickxcodeproj-and-nimblexcodeproj-to-your-test-target) 782 | 3. [Link `Quick.framework` and `Nimble.framework`](#3-link-quickframework-and-nimbleframework) 783 | 4. Start writing specs! 784 | 785 | Example projects with this complete setup is available in the 786 | [`Examples`](https://github.com/modocache/Quick/tree/master/Examples) directory. 787 | 788 | ### 1. Clone the Quick and Nimble repositories 789 | 790 | ```sh 791 | git clone git@github.com:Quick/Quick.git Vendor/Quick 792 | git clone git@github.com:Quick/Nimble.git Vendor/Nimble 793 | ``` 794 | 795 | ### 2. Add `Quick.xcodeproj` and `Nimble.xcodeproj` to your test target 796 | 797 | Right-click on the group containing your application's tests and 798 | select `Add Files To YourApp...`. 799 | 800 | ![](http://cl.ly/image/3m110l2s0a18/Screen%20Shot%202014-06-08%20at%204.25.59%20AM.png) 801 | 802 | Next, select `Quick.xcodeproj`, which you downloaded in step 1. 803 | 804 | ![](http://cl.ly/image/431F041z3g1P/Screen%20Shot%202014-06-08%20at%204.26.49%20AM.png) 805 | 806 | Once you've added the Quick project, you should see it in Xcode's project 807 | navigator, grouped with your tests. 808 | 809 | ![](http://cl.ly/image/0p0k2F2u2O3I/Screen%20Shot%202014-06-08%20at%204.27.29%20AM%20copy.png) 810 | 811 | Follow the same steps for `Nimble.xcodeproj`. 812 | 813 | ### 3. Link `Quick.framework` and `Nimble.framework` 814 | 815 | Link the `Quick.framework` during your test target's 816 | `Link Binary with Libraries` build phase. You should see two 817 | `Quick.frameworks`; one is for OS X, and the other is for iOS. 818 | 819 | ![](http://cl.ly/image/2L0G0H1a173C/Screen%20Shot%202014-06-08%20at%204.27.48%20AM.png) 820 | 821 | Do the same for the `Nimble.framework`. 822 | 823 | ### 4. Start writing specs! 824 | 825 | If you run into any problems, please file an issue. 826 | 827 | ## Including Quick in a Git Repository Using Submodules 828 | 829 | The best way to include Quick in a Git repository is by using Git 830 | submodules. Git submodules are great because: 831 | 832 | 1. They track exactly which version of Quick is being used 833 | 2. It's easy to update Quick to the latest--or any other--version 834 | 835 | ### Adding Quick as a Git Submodule 836 | 837 | To use Git submodules, follow the same steps as above, except instead of 838 | cloning the Quick and Nimble repositories, add them to your project as 839 | submodules: 840 | 841 | ```sh 842 | mkdir Vendor # you can keep your submodules in their own directory 843 | git submodule add git@github.com:Quick/Quick.git Vendor/Quick 844 | git submodule add git@github.com:Quick/Nimble.git Vendor/Nimble 845 | git submodule update --init --recursive 846 | ``` 847 | 848 | ### Updating the Quick Submodule 849 | 850 | If you ever want to update the Quick submodule to latest version, enter 851 | the Quick directory and pull from the master repository: 852 | 853 | ```sh 854 | cd Vendor/Quick 855 | git pull --rebase origin master 856 | ``` 857 | 858 | Your Git repository will track changes to submodules. You'll want to 859 | commit the fact that you've updated the Quick submodule: 860 | 861 | ```sh 862 | git commit -m "Updated Quick submodule" 863 | ``` 864 | 865 | ### Cloning a Repository that Includes a Quick Submodule 866 | 867 | After other people clone your repository, they'll have to pull down the 868 | submodules as well. They can do so by running the `git submodule update` 869 | command: 870 | 871 | ```sh 872 | git submodule update --init --recursive 873 | ``` 874 | 875 | You can read more about Git submodules 876 | [here](http://git-scm.com/book/en/Git-Tools-Submodules). To see examples 877 | of Git submodules in action, check out any of the repositories linked to 878 | in the ["Who Uses Quick"](#who-uses-quick) section of this guide. 879 | 880 | ## How to Install Quick File Templates 881 | 882 | The Quick repository includes file templates for both Swift and 883 | Objective-C specs. 884 | 885 | ### Using Alcatraz 886 | 887 | Quick templates can be installed via [Alcatraz](https://github.com/supermarin/Alcatraz), 888 | a package manager for Xcode. Just search for the templates from the 889 | Package Manager window. 890 | 891 | ![](http://f.cl.ly/items/3T3q0G1j0b2t1V0M0T04/Screen%20Shot%202014-06-27%20at%202.01.10%20PM.png) 892 | 893 | ### Manually via the Rakefile 894 | 895 | To manually install the templates, just clone the repository and 896 | run the `templates:install` rake task: 897 | 898 | ```sh 899 | $ git clone git@github.com:Quick/Quick.git 900 | $ rake templates:install 901 | ``` 902 | 903 | Uninstalling is easy, too: 904 | 905 | ```sh 906 | $ rake templates:uninstall 907 | ``` 908 | 909 | ## Who Uses Quick 910 | 911 | Quick is used by many companies, open-source projects, and individuals, 912 | including [GitHub](https://github.com/github) and 913 | [ReactiveCocoa](https://github.com/ReactiveCocoa). See examples below: 914 | 915 | - https://github.com/ReactiveCocoa/ReactiveCocoa 916 | - https://github.com/github/Archimedes 917 | - https://github.com/libgit2/objective-git 918 | - https://github.com/jspahrsummers/RXSwift 919 | - https://github.com/artsy/eidolon 920 | - https://github.com/AshFurrow/Moya 921 | - https://github.com/nerdyc/Squeal 922 | - https://github.com/pepibumur/SugarRecord 923 | 924 | > Add an issue or [tweet](https://twitter.com/modocache) if you'd like to be added to this list. 925 | 926 | ## License 927 | 928 | Apache 2.0 license. See the `LICENSE` file for details. 929 | 930 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | def run(command) 2 | system(command) or raise "RAKE TASK FAILED: #{command}" 3 | end 4 | 5 | namespace "test" do 6 | desc "Run unit tests for all iOS targets" 7 | task :ios do |t| 8 | run "xcodebuild -project Quick.xcodeproj -scheme Quick-iOS clean test" 9 | end 10 | 11 | desc "Run unit tests for all OS X targets" 12 | task :osx do |t| 13 | run "xcodebuild -project Quick.xcodeproj -scheme Quick-OSX clean test" 14 | end 15 | end 16 | 17 | namespace "templates" do 18 | install_dir = File.expand_path("~/Library/Developer/Xcode/Templates/File Templates/Quick") 19 | src_dir = File.expand_path("../Quick Templates", __FILE__) 20 | 21 | desc "Install Quick templates" 22 | task :install do 23 | if File.exists? install_dir 24 | raise "RAKE TASK FAILED: Quick templates are already installed at #{install_dir}" 25 | else 26 | mkdir_p install_dir 27 | cp_r src_dir, install_dir 28 | end 29 | end 30 | 31 | desc "Uninstall Quick templates" 32 | task :uninstall do 33 | rm_rf install_dir 34 | end 35 | end 36 | 37 | task default: ["test:ios", "test:osx"] 38 | 39 | --------------------------------------------------------------------------------