Framework
Quick/Quick avatar
Quick/Quick

Quick: BDD-style specs for Swift and Objective-C test targets

The Swift (and Objective-C) testing framework.

9,826 stars894 forksSwiftApache-2.0

At a glance

What is it?
Quick is a behavior-driven testing framework for Swift and Objective-C, usually paired with Nimble matchers. It installs through CocoaPods or Swift Package Manager and belongs only in a test target, never in a shipping binary.
Who is it for?
Adopt Quick when your team already writes XCTest cases and wants describe/context/it structure with Nimble's expect(...).to(...) assertions, and when you can keep it in a test target only. Do not adopt it if you are not on Xcode and a supported Swift version, or if you want assertions that read like plain XCTest.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 134 days ago.
What is it written in?
Mainly Swift, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem Quick solves in an Xcode test target

XCTest gives you one flat class per test case and method names like testThatTheDocumentationDirectoryHasGettingStartedSection. Quick replaces that with nested example groups. The README shows a QuickSpec subclass that opens with describe("the 'Documentation' directory"), then nests it("has everything you need to get started") and a context("if it doesn't have what you're looking for") inside it. The strings carry the intent; the class and method names stop doing that work.

The framework is aimed at Swift and Objective-C developers who already have an Xcode test target and want RSpec-style organization. The README names RSpec, Specta and Ginkgo as the inspiration, so anyone arriving from Ruby or Go testing will recognize the shape. It is not a replacement for XCTest's runner: Quick specs still execute under the same test infrastructure, which is why the README can state that Quick is only used for testing.

How describe, context and it fit together at runtime

A QuickSpec subclass overrides the class method spec(). Everything inside that method registers examples and example groups with Quick before the tests run. Nested describe and context calls build a tree, and each it block is a leaf that Quick later executes as an individual test case. That is why the strings matter: they are the only structural labels the tree has.

The README example mixes two styles of assertion. expect(sections).to(contain(...)) is Nimble's synchronous matcher form. expect{you.submittedAnIssue}.toEventually(beTruthy()) wraps the expression in a closure and polls it over time, which is the form you want for asynchronous work. Both compile inside the same it block, so a spec can check a static list and a callback-driven result without switching frameworks.

Quick and Nimble are separate repositories with separate version numbers. The README's compatibility table pairs them explicitly: Swift 5.2 works with Quick v3.0.0 or later and Nimble v9.0.0 or later, while Swift 4.2 or Swift 5 needs Quick v1.3.2 or later with Nimble v7.3.2 or later. Treat the two versions as a pair when you resolve dependencies.

Installing Quick with CocoaPods or Swift Package Manager

The README points to the Documentation folder for detailed installation instructions covering CocoaPods, Git submodules and Swift Package Manager. The CocoaPods route puts Quick and Nimble in a nested test target. Add this to your Podfile, keeping the pod lines inside the test target rather than the app target:

rb
# Podfile

use_frameworks!

target "MyApp" do
  # Normal libraries

  target 'MyApp_Tests' do
    inherit! :search_paths

    pod 'Quick'
    pod 'Nimble'
  end
end

After running pod install, open the generated workspace rather than the project file. The inherit! :search_paths line lets the test target see the app target's headers and modules without duplicating them.

For Swift Package Manager, the README shows adding both packages to the dependencies array in Package.swift, with Quick from "7.0.0" and Nimble from "12.0.0":

swift
dependencies: [
    .package(url: "https://github.com/Quick/Quick.git", from: "7.0.0"),
    .package(url: "https://github.com/Quick/Nimble.git", from: "12.0.0"),
],

Your first spec follows the README's shape directly: import Quick and Nimble, subclass QuickSpec, override class func spec(), and put describe/it inside it. Run the test target in Xcode and each it block appears as its own result, labeled with the strings you passed in.

The App Store rejection rule you cannot work around

The README is unusually blunt about this. Quick uses private APIs to integrate with Xcode, and the README states that an app will be rejected if Quick is included in the binary submitted to App Store Connect. It also says Quick should never be included in that binary. This is not a configuration preference; it is a constraint on how you wire your targets.

The practical failure mode is a dependency declared in the wrong place. A pod 'Quick' line in the app target instead of the test target, or a package dependency added to the app target's list rather than the test target's, produces a build that links Quick into the shipping product. The README's own Podfile example avoids this with the nested target and inherit! :search_paths. If you use Swift Package Manager, the same discipline applies: the dependency belongs to the test target.

The README also notes that Quick collects no analytics or tracking, despite not shipping to Apple. That is a statement about the library's behavior, not a substitute for checking your own dependency graph.

Where Quick is the wrong choice

Quick's compatibility table is also a constraint. If your project is pinned to a Swift version outside the rows listed, you are choosing between upgrading Swift and picking an older Quick and Nimble pair. The README documents combinations down to Swift 2.2 and Swift 2.3 with Quick v0.9.3 and Nimble v4.1.0, but nothing newer than Swift 5.2 appears in the table, so a team on a newer toolchain has to confirm compatibility from the release notes rather than the README.

There is also a style cost. Quick adds a layer of string-labeled structure on top of XCTest. Teams that prefer test names the compiler can check, or that already have a large XCTest suite with no appetite for rewriting it, gain little from the nesting. The README describes Quick as coming together with Nimble, and the examples lean on Nimble matchers; adopting Quick without Nimble leaves you with the group structure but not the assertion style that motivates it.

Finally, this is an Apple-platform tool. The README's installation paths are CocoaPods, Git submodules and Swift Package Manager inside an Xcode project. Nothing in the README describes a server-side or Linux test workflow.

Quick compared with plain XCTest

The honest alternative is XCTest by itself. XCTest gives you XCTestCase subclasses, test methods discovered by name prefix, and XCTAssert family assertions. It has no describe/context nesting and no expect(...).to(...) matcher syntax. The README's NimbleAssertions document argues that XCTAssert() statements make expectations unclear and shows Nimble as the fix.

The difference in approach is where the description lives. In XCTest, the test method name is the description, and the assertion is a function call with the expected value as an argument. In Quick, the description is a string passed to describe, context or it, and the assertion reads as expect(actual).to(matcher). Neither is more correct. XCTest names are refactorable by the compiler; Quick strings are not, which is a real trade-off when you rename a feature and forget to update the spec labels.

Quick also does not remove XCTest. The specs run inside the same test target and the same runner. You can migrate one test class at a time, which is the practical reason teams adopt it incrementally rather than all at once.

Maintenance, versions and the Apache 2.0 licence

The repository is not archived, and the last push was on 2026-05-18. The most recent release listed is v7.6.2 from 2024-07-23, preceded by v7.6.1 on 2024-07-02 and v7.6.0 on 2024-05-12. The gap between the latest release and the last push means the branch has moved since the last tagged version, so if you need a tagged artifact, v7.6.2 is the newest one named in the release list.

The upgrade cost is dominated by the Swift and Nimble pairing, not by Quick alone. The compatibility table means a Swift upgrade can force a Quick and Nimble upgrade at the same time, and the README's Package.swift example pins Quick from "7.0.0" and Nimble from "12.0.0". Budget for both when you plan a toolchain move.

Quick is licensed under Apache-2.0, with the LICENSE file at the repository root. That is a permissive licence, but it is not legal advice and your own distribution model, including how you vendor the source through CocoaPods or a Git submodule, is worth checking against your organization's policy.

Editorial conclusion

Adopt Quick when your team already writes XCTest cases and wants describe/context/it structure with Nimble's expect(...).to(...) assertions, and when you can keep it in a test target only. Do not adopt it if you are not on Xcode and a supported Swift version, or if you want assertions that read like plain XCTest. Before committing, check the Swift version table against your toolchain, confirm the Podfile or Package.swift entry resolves, and verify that Quick is absent from the archive you submit to App Store Connect.

Frequently asked questions

What is Quick, the Swift testing framework?

Quick is a behavior-driven development framework for Swift and Objective-C, inspired by RSpec, Specta and Ginkgo. It lets you organize tests with describe, context and it blocks inside a QuickSpec subclass.

How do I install Quick in an iOS project?

The README shows adding pod 'Quick' and pod 'Nimble' to a nested test target in your Podfile, or adding the Quick and Nimble package URLs to the dependencies array in Package.swift. Detailed instructions for CocoaPods, Git submodules and Swift Package Manager live in the Documentation folder.

Does Quick ship inside the app binary?

No. The README states Quick is only used for testing and should never be included in the binary submitted to App Store Connect, because it uses private APIs to integrate with Xcode. An app will be rejected if Quick is included.

Which Swift version does Quick support?

The README's table pairs Swift 5.2 with Quick v3.0.0 or later and Nimble v9.0.0 or later, and Swift 4.2 or Swift 5 with Quick v1.3.2 or later and Nimble v7.3.2 or later. Older rows cover Swift 3, Swift 4, Swift 2.2 and Swift 2.3.

Does Quick collect any analytics?

The README states that Quick does not and will never collect any kind of analytics or tracking, even though it is not shipped to Apple.

Official sources

  1. License: Apache-2.0
  2. Project website
  3. Quick/Quick on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/quick-quick.svg)](https://hysenlabs.com/projects/quick-quick)