{"id":15048354,"url":"https://github.com/github/nimble","last_synced_at":"2025-10-04T08:31:23.221Z","repository":{"id":21413351,"uuid":"24731392","full_name":"github/Nimble","owner":"github","description":"A Matcher Framework for Swift and Objective-C","archived":true,"fork":true,"pushed_at":"2014-11-11T18:03:12.000Z","size":494,"stargazers_count":11,"open_issues_count":0,"forks_count":9,"subscribers_count":24,"default_branch":"master","last_synced_at":"2024-09-29T00:21:26.192Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"Quick/Nimble","license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/github.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-10-02T18:35:43.000Z","updated_at":"2024-07-31T03:22:14.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/github/Nimble","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/github%2FNimble","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/github%2FNimble/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/github%2FNimble/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/github%2FNimble/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/github","download_url":"https://codeload.github.com/github/Nimble/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":235232524,"owners_count":18957057,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-09-24T21:11:05.031Z","updated_at":"2025-10-04T08:31:22.856Z","avatar_url":"https://github.com/github.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Nimble\n\n[![Build Status](https://travis-ci.org/Quick/Nimble.svg?branch=master)](https://travis-ci.org/Quick/Nimble)\n\nUse Nimble to express the expected outcomes of Swift\nor Objective-C expressions. Inspired by\n[Cedar](https://github.com/pivotal/cedar).\n\n```swift\n// Swift\n\nexpect(1 + 1).to(equal(2))\nexpect(1.2).to(beCloseTo(1.1, within: 0.1))\nexpect(3) \u003e 2\nexpect(\"seahorse\").to(contain(\"sea\"))\nexpect([\"Atlantic\", \"Pacific\"]).toNot(contain(\"Mississippi\"))\nexpect(ocean.isClean).toEventually(beTruthy())\n```\n\n# How to Use Nimble\n\n\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n\n- [Some Background: Expressing Outcomes Using Assertions in XCTest](#some-background-expressing-outcomes-using-assertions-in-xctest)\n- [Nimble: Expectations Using `expect(...).to`](#nimble-expectations-using-expectto)\n  - [Type Checking](#type-checking)\n  - [Operator Overloads](#operator-overloads)\n  - [Lazily Computed Values](#lazily-computed-values)\n  - [C Primitives](#c-primitives)\n  - [Asynchronous Expectations](#asynchronous-expectations)\n  - [Objective-C Support](#objective-c-support)\n  - [Disabling Objective-C Shorthand](#disabling-objective-c-shorthand)\n- [Built-in Matcher Functions](#built-in-matcher-functions)\n  - [Equivalence](#equivalence)\n  - [Identity](#identity)\n  - [Comparisons](#comparisons)\n  - [Types/Classes](#typesclasses)\n  - [Truthiness](#truthiness)\n  - [Exceptions](#exceptions)\n  - [Collection Membership](#collection-membership)\n  - [Strings](#strings)\n- [Writing Your Own Matchers](#writing-your-own-matchers)\n  - [Lazy Evaluation](#lazy-evaluation)\n  - [Type Checking via Swift Generics](#type-checking-via-swift-generics)\n  - [Customizing Failure Messages](#customizing-failure-messages)\n  - [Supporting Objective-C](#supporting-objective-c)\n    - [Properly Handling `nil` in Objective-C Matchers](#properly-handling-nil-in-objective-c-matchers)\n- [Installing Nimble](#installing-nimble)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\n# Some Background: Expressing Outcomes Using Assertions in XCTest\n\nApple's Xcode includes the XCTest framework, which provides\nassertion macros to test whether code behaves properly.\nFor example, to assert that `1 + 1 = 2`, XCTest has you write:\n\n```swift\n// Swift\n\nXCTAssertEqual(1 + 1, 2, \"expected one plus one to equal two\")\n```\n\nOr, in Objective-C:\n\n```objc\n// Objective-C\n\nXCTAssertEqual(1 + 1, 2, @\"expected one plus one to equal two\");\n```\n\nXCTest assertions have several drawbacks:\n\n1. **Not enough macros.** There's no easy way to assert that a string\n   contains a particular substring, or that a number is less than or\n   equal to another.\n2. **No type checking.** It doesn't make sense to comapre a number to\n   a string, but XCTest assertions allow it. Assertions are implemented\n   using macros, so there's no type checking.\n\n   `XCTAssertEqual(1 + 1, \"2\")` compiles and runs--you won't\n   find out that you've made an impossible comparison until the test\n   runs and fails. That could take seconds, or even minutes in larger test\n   suites.\n3. **It's hard to write asynchronous tests.** XCTest forces you to write\n   a lot of boilerplate code.\n\nNimble addresses all three of these concerns.\n\n# Nimble: Expectations Using `expect(...).to`\n\nNimble allows you to express expectations using a natural,\neasily understood language:\n\n```swift\n// Swift\n\nimport Nimble\n\nexpect(seagull.squawk).to(equal(\"Squee!\"))\n```\n\n```objc\n// Objective-C\n\n#import \u003cNimble/Nimble.h\u003e\n\nexpect(seagull.squawk).to(equal(@\"Squee!\"));\n```\n\n\u003e The `expect` function autocompletes to include `file:` and `line:`,\n  but these parameters are optional. Use the default values to have\n  Xcode highlight the correct line when an expectation is not met.\n\nTo perform the opposite expectation--to assert something is *not*\nequal--use `toNot` or `notTo`:\n\n```swift\n// Swift\n\nimport Nimble\n\nexpect(seagull.squawk).toNot(equal(\"Oh, hello there!\"))\nexpect(seagull.squawk).notTo(equal(\"Oh, hello there!\"))\n```\n\n```objc\n// Objective-C\n\n#import \u003cNimble/Nimble.h\u003e\n\nexpect(seagull.squawk).toNot(equal(@\"Oh, hello there!\"));\nexpect(seagull.squawk).notTo(equal(@\"Oh, hello there!\"));\n```\n\n## Type Checking\n\nNimble makes sure you don't compare two types that don't match:\n\n```swift\n// Swift\n\n// Does not compile:\nexpect(1 + 1).to(equal(\"Squee!\"))\n```\n\n\u003e Nimble uses generics--only available in Swift--to ensure\n  type correctness. That means type checking is\n  not available when using Nimble in Objective-C. :sob:\n\n## Operator Overloads\n\nTired of so much typing? With Nimble, you can use overloaded operators\nlike `==` for equivalence, or `\u003e` for comparisons:\n\n```swift\n// Swift\n\n// Passes if squawk does not equal \"Hi!\":\nexpect(seagull.squawk) != \"Hi!\"\n\n// Passes if 10 is greater than 2:\nexpect(10) \u003e 2\n```\n\n\u003e Operator overloads are only available in Swift, so you won't be able\n  to use this syntax in Objective-C. :broken_heart:\n\n## Lazily Computed Values\n\nThe `expect` function doesn't evalaute the value it's given until it's\ntime to match. So Nimble can test whether an expression raises an\nexception once evaluated:\n\n```swift\n// Swift\n\nlet exception = NSException(\n  name: NSInternalInconsistencyException,\n  reason: \"Not enough fish in the sea.\",\n  userInfo: nil)\nexpect(exception.raise()).to(raiseException())\n```\n\nObjective-C works the same way, but you must use the `expectAction`\nmacro when making an expectation on an expression that has no return\nvalue:\n\n```objc\n// Objective-C\n\nNSException *exception = [NSException exceptionWithName:NSInternalInconsistencyException\n                                                 reason:@\"Not enough fish in the sea.\"\n                                               userInfo:nil];\nexpectAction([exception raise]).to(raiseException());\n```\n\nIn Swift, the `expect` function can also take a trailing closure:\n\n```swift\n// Swift\n\nexpect {\n  exception.raise()\n}.to(raiseException(named: NSInternalInconsistencyException))\n```\n\n## C Primitives\n\nSome testing frameworks make it hard to test primitive C values.\nIn Nimble, it just works:\n\n```swift\n// Swift\n\nlet actual: CInt = 1\nlet expectedValue: CInt = 1\nexpect(actual).to(equal(expectedValue))\n```\n\nIn fact, Nimble uses type inference, so you can write the above\nwithout explicitly specifying both types:\n\n```swift\n// Swift\n\nexpect(1 as CInt).to(equal(1))\n```\n\n\u003e In Objective-C, Nimble only supports Objective-C objects. To\n  make expectations on primitive C values, wrap then in an object\n  literal:\n\n  ```objc\n  expect(@(1 + 1)).to(equal(@2));\n  ```\n\n## Asynchronous Expectations\n\nIn Nimble, it's easy to make expectations on values that are updated\nasynchronously. Just use `toEventually` or `toEventuallyNot`:\n\n```swift\n// Swift\n\ndispatch_async(dispatch_get_main_queue()) {\n  ocean.add(\"dolphins\"\")\n  ocean.add(\"whales\")\n}\nexpect(ocean).toEventually(contain(\"dolphins\", \"whales\"))\n```\n\n\n```objc\n// Objective-C\ndispatch_async(dispatch_get_main_queue(), ^{\n  [ocean add:@\"dolphins\"];\n  [ocean add:@\"whales\"];\n});\nexpect(ocean).toEventually(contain(@\"dolphins\", @\"whales\"));\n```\n\nIn the above example, `ocean` is constantly re-evaluated. If it ever\ncontains dolphins and whales, the expectation passes. If `ocean` still\ndoesn't contain them, even after being continuously re-evaluated for one\nwhole second, the expectation fails.\n\nSometimes it takes more than a second for a value to update. In those\ncases, use the `timeout` parameter:\n\n```swift\n// Swift\n\n// Waits three seconds for ocean to contain \"starfish\":\nexpect(ocean).toEventually(contain(\"starfish\"), timeout: 3)\n```\n\n\u003e Sorry, [Nimble doesn't support specifying custom timeouts in Objective-C yet](https://github.com/Quick/Nimble/issues/25).\n\nYou can also provide a callback by using the `waitUntil` function:\n\n```swift\n// Swift\n\nwaitUntil { done in\n  // do some stuff that takes a while...\n  NSThread.sleepForTimeInterval(0.5)\n  done()\n}\n```\n\n`waitUntil` also optionally takes a timeout parameter:\n\n```swift\n// Swift\n\nwaitUntil(timeout: 10) { done in\n  // do some stuff that takes a while...\n  NSThread.sleepForTimeInterval(1)\n  done()\n}\n```\n\n## Objective-C Support\n\nNimble has full support for Objective-C. However, there are two things\nto keep in mind when using Nimble in Objective-C:\n\n1. All parameters passed to the `expect` function, as well as matcher\n   functions like `equal`, must be Objective-C objects:\n\n   ```objc\n   // Objective-C\n\n   #import \u003cNimble/Nimble.h\u003e\n\n   expect(@(1 + 1)).to(equal(@2));\n   expect(@\"Hello world\").to(contain(@\"world\"));\n   ```\n\n2. To make an expectation on an expression that does not return a value,\n   such as `-[NSException raise]`, use `expectAction` instead of\n   `expect`:\n\n   ```objc\n   // Objective-C\n\n   expectAction([exception raise]).to(raiseException());\n   ```\n\n## Disabling Objective-C Shorthand\n\nNimble provides a shorthand for expressing expectations using the\n`expect` function. To disable this shorthand in Objective-C, define the\n`NIMBLE_DISABLE_SHORT_SYNTAX` macro somewhere in your code before\nimporting Nimble:\n\n```objc\n#define NIMBLE_DISABLE_SHORT_SYNTAX 1\n\n#import \u003cNimble/Nimble.h\u003e\n\nNMB_expect(^{ return seagull.squawk; }, __FILE__, __LINE__).to(NMB_equal(@\"Squee!\"));\n```\n\n\u003e Disabling the shorthand is useful if you're testing functions with\n  names that conflict with Nimble functions, such as `expect` or\n  `equal`. If that's not the case, there's no point in disabling the\n  shorthand.\n\n# Built-in Matcher Functions\n\nNimble includes a wide variety of matcher functions.\n\n## Equivalence\n\n```swift\n// Swift\n\n// Passes if actual is equivalent to expected:\nexpect(actual).to(equal(expected))\nexpect(actual) == expected\n\n// Passes if actual is not equivalent to expected:\nexpect(actual).toNot(equal(expected))\nexpect(actual) != expected\n```\n\n```objc\n// Objective-C\n\n// Passes if actual is equivalent to expected:\nexpect(actual).to(equal(expected))\n\n// Passes if actual is not equivalent to expected:\nexpect(actual).toNot(equal(expected))\n```\n\nValues must be `Equatable`, `Comparable`, or subclasses of `NSObject`.\n`equal` will always fail when used to compare one or more `nil` values.\n\n## Identity\n\n```swift\n// Swift\n\n// Passes if actual has the same pointer address as expected:\nexpect(actual).to(beIdenticalTo(expected))\nexpect(actual) === expected\n\n// Passes if actual does not have the same pointer address as expected:\nexpect(actual).toNot(beIdenticalTo(expected))\nexpect(actual) !== expected\n```\n\n```objc\n// Objective-C\n\n// Passes if actual has the same pointer address as expected:\nexpect(actual).to(beIdenticalTo(expected));\n\n// Passes if actual does not have the same pointer address as expected:\nexpect(actual).toNot(beIdenticalTo(expected));\n```\n\n\u003e `beIdenticalTo` only supports Objective-C objects: subclasses\n  of `NSObject`, or Swift objects bridged to Objective-C with the\n  `@objc` prefix.\n\n## Comparisons\n\n```swift\n// Swift\n\nexpect(actual).to(beLessThan(expected))\nexpect(actual) \u003c expected\n\nexpect(actual).to(beLessThanOrEqualTo(expected))\nexpect(actual) \u003c= expected\n\nexpect(actual).to(beGreaterThan(expected))\nexpect(actual) \u003e expected\n\nexpect(actual).to(beGreaterThanOrEqualTo(expected))\nexpect(actual) \u003e= expected\n```\n\n```objc\n// Objective-C\n\nexpect(actual).to(beLessThan(expected));\nexpect(actual).to(beLessThanOrEqualTo(expected));\nexpect(actual).to(beGreaterThan(expected));\nexpect(actual).to(beGreaterThanOrEqualTo(expected));\n```\n\n\u003e Values given to the comparison matchers above must implement\n  `Comparable`.\n\nBecause of how computers represent floating point numbers, assertions\nthat two floating point numbers be equal will sometimes fail. To express\nthat two numbers should be close to one another within a certain margin\nof error, use `beCloseTo`:\n\n```swift\n// Swift\n\nexpect(actual).to(beCloseTo(expected, within: delta))\n```\n\n```objc\n// Objective-C\n\nexpect(actual).to(beCloseTo(expected).within(delta));\n```\n\nFor example, to assert that `10.01` is close to `10`, you can write:\n\n```swift\n// Swift\n\nexpect(10.01).to(beCloseTo(10, within: 0.1))\n```\n\n```objc\n// Objective-C\n\nexpect(@(10.01)).to(beCloseTo(@10).within(0.1));\n```\n\n\u003e Values given to the `beCloseTo` matcher must be coercable into a\n  `Double`.\n\n## Types/Classes\n\n```swift\n// Swift\n\n// Passes if instance is an instance of aClass:\nexpect(instance).to(beAnInstanceOf(aClass))\n\n// Passes if instance is an instance of aClass or any of its subclasses:\nexpect(instance).to(beAKindOf(aClass))\n```\n\n```objc\n// Objective-C\n\n// Passes if instance is an instance of aClass:\nexpect(instance).to(beAnInstanceOf(aClass));\n\n// Passes if instance is an instance of aClass or any of its subclasses:\nexpect(instance).to(beAKindOf(aClass));\n```\n\n\u003e Instances must be Objective-C objects: subclasses of `NSObject`,\n  or Swift objects bridged to Objective-C with the `@objc` prefix.\n\nFor example, to assert that `dolphin` is a kind of `Mammal`:\n\n```swift\n// Swift\n\nexpect(dolphin).to(beAKindOf(Mammal))\n```\n\n```objc\n// Objective-C\n\nexpect(dolphin).to(beAKindOf([Mammal class]));\n```\n\n\u003e `beAnInstanceOf` uses the `-[NSObject isMemberOfClass:]` method to\n  test membership. `beAKindOf` uses `-[NSObject isKindOfClass:]`.\n\n## Truthiness\n\n```swift\n// Passes if actual is not nil, false, or an object with a boolean value of false:\nexpect(actual).to(beTruthy())\n\n// Passes if actual is only true (not nil or an object conforming to BooleanType true):\nexpect(actual).to(beTrue())\n\n// Passes if actual is nil, false, or an object with a boolean value of false:\nexpect(actual).to(beFalsy())\n\n// Passes if actual is only false (not nil or an object conforming to BooleanType false):\nexpect(actual).to(beFalse())\n\n// Passes if actual is nil:\nexpect(actual).to(beNil())\n```\n\n```objc\n// Objective-C\n\n// Passes if actual is not nil, false, or an object with a boolean value of false:\nexpect(actual).to(beTruthy());\n\n// Passes if actual is only true (not nil or an object conforming to BooleanType true):\nexpect(actual).to(beTrue());\n\n// Passes if actual is nil, false, or an object with a boolean value of false:\nexpect(actual).to(beFalsy());\n\n// Passes if actual is only false (not nil or an object conforming to BooleanType false):\nexpect(actual).to(beFalse());\n\n// Passes if actual is nil:\nexpect(actual).to(beNil());\n```\n\n## Exceptions\n\n```swift\n// Swift\n\n// Passes if actual, when evaluated, raises an exception:\nexpect(actual).to(raiseException())\n\n// Passes if actual raises an exception with the given name:\nexpect(actual).to(raiseException(named: name))\n\n// Passes if actual raises an exception with the given name and reason:\nexpect(actual).to(raiseException(named: name, reason: reason))\n```\n\n```objc\n// Objective-C\n\n// Passes if actual, when evaluated, raises an exception:\nexpect(actual).to(raiseException())\n```\n\n\u003e Sorry, [Nimble doesn't support matching on exception `name`, `reason`, or `userInfo` yet](https://github.com/Quick/Nimble/issues/26).\n\n## Collection Membership\n\n```swift\n// Swift\n\n// Passes if all of the expected values are members of actual:\nexpect(actual).to(contain(expected...))\n\n// Passes if actual is an empty collection (it contains no elements):\nexpect(actual).to(beEmpty())\n```\n\n```objc\n// Objective-C\n\n// Passes if expected is a member of actual:\nexpect(actual).to(contain(expected));\n\n// Passes if actual is an empty collection (it contains no elements):\nexpect(actual).to(beEmpty());\n```\n\n\u003e In Swift `contain` takes any number of arguments. The expectation\n  passes if all of them are members of the collection. In Objective-C,\n  `contain` only takes one argument [for now](https://github.com/Quick/Nimble/issues/27).\n\nFor example, to assert that a list of sea creature names contains\n\"dolphin\" and \"starfish\":\n\n```swift\n// Swift\n\nexpect([\"whale\", \"dolphin\", \"starfish\"]).to(contain(\"dolphin\", \"starfish\"))\n```\n\n```objc\n// Objective-C\n\nexpect(@[@\"whale\", @\"dolphin\", @\"starfish\"]).to(contain(@\"dolphin\"));\nexpect(@[@\"whale\", @\"dolphin\", @\"starfish\"]).to(contain(@\"starfish\"));\n```\n\n\u003e `contain` and `beEmpty` expect collections to be instances of\n  `NSArray`, `NSSet`, or a Swift collection composed of `Equatable` elements.\n\nTo test whether a set of elements is present at the beginning or end of\nan ordered collection, use `beginWith` and `endWith`:\n\n```swift\n// Swift\n\n// Passes if the elements in expected appear at the beginning of actual:\nexpect(actual).to(beginWith(expected...))\n\n// Passes if the the elements in expected come at the end of actual:\nexpect(actual).to(endWith(expected...))\n```\n\n```objc\n// Objective-C\n\n// Passes if the elements in expected appear at the beginning of actual:\nexpect(actual).to(beginWith(expected));\n\n// Passes if the the elements in expected come at the end of actual:\nexpect(actual).to(endWith(expected));\n```\n\n\u003e `beginWith` and `endWith` expect collections to be instances of\n  `NSArray`, or ordered Swift collections composed of `Equatable`\n  elements.\n\n  Like `contain`, in Objective-C `beginWith` and `endWith` only support\n  a single argument [for now](https://github.com/Quick/Nimble/issues/27).\n\n## Strings\n\n```swift\n// Swift\n\n// Passes if actual contains substring expected:\nexpect(actual).to(contain(expected))\n\n// Passes if actual begins with substring:\nexpect(actual).to(beginWith(expected))\n\n// Passes if actual ends with substring:\nexpect(actual).to(endWith(expected))\n\n// Passes if actual is an empty string, \"\":\nexpect(actual).to(beEmpty())\n\n// Passes if actual matches the regular expression defined in expected:\nexpect(actual).to(match(expected))\n```\n\n```objc\n// Objective-C\n\n// Passes if actual contains substring expected:\nexpect(actual).to(contain(expected));\n\n// Passes if actual begins with substring:\nexpect(actual).to(beginWith(expected));\n\n// Passes if actual ends with substring:\nexpect(actual).to(endWith(expected));\n\n// Passes if actual is an empty string, \"\":\nexpect(actual).to(beEmpty());\n\n// Passes if actual matches the regular expression defined in expected:\nexpect(actual).to(match(expected))\n```\n\n# Writing Your Own Matchers\n\nIn Nimble, matchers are Swift functions that take an expected\nvalue and return a `MatcherFunc` closure. Take `equal`, for example:\n\n```swift\n// Swift\n\npublic func equal\u003cT: Equatable\u003e(expectedValue: T?) -\u003e MatcherFunc\u003cT?\u003e {\n  return MatcherFunc { actualExpression, failureMessage in\n    failureMessage.postfixMessage = \"equal \u003c\\(expectedValue)\u003e\"\n    return actualExpression.evaluate() == expectedValue\n  }\n}\n```\n\nThe return value of a `MatcherFunc` closure is a `Bool` that indicates\nwhether the actual value matches the expectation: `true` if it does, or\n`false` if it doesn't.\n\n\u003e The actual `equal` matcher function does not match when either\n  `actual` or `expected` are nil; the example above has been edited for\n  brevity.\n\nSince matchers are just Swift functions, you can define them anywhere:\nat the top of your test file, in a file shared by all of your tests, or\nin an Xcode project you distribute to others.\n\n\u003e If you write a matcher you think everyone can use, consider adding it\n  to Nimble's built-in set of matchers by sending a pull request! Or\n  distribute it yourself via GitHub.\n\nFor examples of how to write your own matchers, just check out the\n[`Matchers` directory](https://github.com/Quick/Nimble/tree/master/Nimble/Matchers)\nto see how Nimble's built-in set of matchers are implemented. You can\nalso check out the tips below.\n\n## Lazy Evaluation\n\n`actualExpression` is a lazy, memoized closure around the value provided to\nthe `expect` function. In order to determine whether that value matches,\ncustom matchers should call `actualExpression.evalaute()`:\n\n```swift\n// Swift\n\npublic func beNil\u003cT\u003e() -\u003e MatcherFunc\u003cT?\u003e {\n  return MatcherFunc { actualExpression, failureMessage in\n    failureMessage.postfixMessage = \"be nil\"\n    return actualExpression.evaluate() == nil\n  }\n}\n```\n\nIn the above example, `actualExpression` is not `nil`--it is a closure\nthat returns a value. The value it returns, which is accessed via the\n`evaluate()` method, may be `nil`. If that value is `nil`, the `beNil`\nmatcher function returns `true`, indicating that the expectation passed.\n\n## Type Checking via Swift Generics\n\nUsing Swift's generics, matchers can constrain the type of the actual value\npassed to the `expect` function by modifying the return type.\n\nFor example, the following matcher, `haveDescription`, only accepts actual\nvalues that implement the `Printable` protocol. It checks their `description`\nagainst the one provided to the matcher function, and passes if they are the same:\n\n```swift\n// Swift\n\npublic func haveDescription(description: String) -\u003e MatcherFunc\u003cPrintable?\u003e {\n  return MatcherFunc { actual, failureMessage in\n    return actual.evaluate().description == description\n  }\n}\n```\n\n## Customizing Failure Messages\n\nBy default, Nimble outputs the following failure message when an\nexpectation fails:\n\n```\nexpected to match, got \u003c\\(actual)\u003e\n```\n\nYou can customize this message by modifying the `failureMessage` struct\nfrom within your `MatcherFunc` closure. To change the verb \"match\" to\nsomething else, update the `postfixMessage` property:\n\n```swift\n// Swift\n\n// Outputs: expected to be under the sea, got \u003c\\(actual)\u003e\nfailureMessage.postfixMessage = \"be under the sea\"\n```\n\nYou can change how the `actual` value is displayed by updating\n`failureMessage.actualValue`. Or, to remove it altogether, set it to\n`nil`:\n\n```swift\n// Swift\n\n// Outputs: expected to be under the sea\nfailureMessage.actualValue = nil\nfailureMessage.postfixMessage = \"be under the sea\"\n```\n\n## Supporting Objective-C\n\nTo use a custom matcher written in Swift from Objective-C, you'll have\nto extend the `NMBObjCMatcher` class, adding a new class method for your\ncustom matcher. The example below defines the class method\n`+[NMBObjCMatcher beNilMatcher]`:\n\n```swift\n// Swift\n\nextension NMBObjCMatcher {\n  public class func beNilMatcher() -\u003e NMBObjCMatcher {\n    return NMBObjCMatcher { actualBlock, failureMessage, location in\n      let block = ({ actualBlock() as NSObject? })\n      let expr = Expression(expression: block, location: location)\n      return beNil().matches(expr, failureMessage: failureMessage)\n    }\n  }\n}\n```\n\nThe above allows you to use the matcher from Objective-C:\n\n```objc\n// Objective-C\n\nexpect(actual).to([NMBObjCMatcher beNilMatcher]());\n```\n\nTo make the syntax easier to use, define a C function that calls the\nclass method:\n\n```objc\n// Objective-C\n\nFOUNDATION_EXPORT id\u003cNMBMatcher\u003e beNil() {\n  return [NMBObjCMatcher beNilMatcher];\n}\n```\n\n### Properly Handling `nil` in Objective-C Matchers\n\nWhen supporting Objective-C, make sure you handle `nil` appropriately.\nLike [Cedar](https://github.com/pivotal/cedar/issues/100),\n**most matchers do not match with nil**. This is to bring prevent test\nwriters from being surprised by `nil` values where they did not expect\nthem.\n\nNimble provides the `beNil` matcher function for test writer that want\nto make expectations on `nil` objects:\n\n```objc\n// Objective-C\n\nexpect(nil).to(equal(nil)); // fails\nexpect(nil).to(beNil());    // passes\n```\n\n# Installing Nimble\n\n\u003e Nimble can be used on its own, or in conjunction with its sister\n  project, [Quick](https://github.com/Quick/Quick). To install both\n  Quick and Nimble, follow [the installation instructions in the Quick\n  README](https://github.com/Quick/Quick#how-to-install-quick).\n\nTo use Nimble to test your iOS or OS X applications, follow these 4 easy\nsteps:\n\n1. Clone the Nimble repository\n2. Add Nimble.xcodeproj to your test target\n3. Link Nimble.framework to your test target\n4. Start writing expectations!\n\nFor more detailed instructions on each of these steps,\nread [How to Install Quick](https://github.com/Quick/Quick#how-to-install-quick).\nIgnore the steps involving adding Quick to your project in order to\ninstall just Nimble.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgithub%2Fnimble","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgithub%2Fnimble","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgithub%2Fnimble/lists"}