Skip to content

Commit

Permalink
Adds matchers for Swift 5 Result type
Browse files Browse the repository at this point in the history
  • Loading branch information
xzeror authored and ikesyo committed May 22, 2020
1 parent ca652f9 commit d6e0345
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 0 deletions.
16 changes: 16 additions & 0 deletions Nimble.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@
0477153523B740AD00402D4E /* DispatchTimeInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0477153423B740AD00402D4E /* DispatchTimeInterval.swift */; };
0477153623B740B700402D4E /* DispatchTimeInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0477153423B740AD00402D4E /* DispatchTimeInterval.swift */; };
0477153723B740B800402D4E /* DispatchTimeInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0477153423B740AD00402D4E /* DispatchTimeInterval.swift */; };
106112BD2251DFE7000A5848 /* BeResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 106112BC2251DFE7000A5848 /* BeResult.swift */; };
106112C02251E0FA000A5848 /* BeResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 106112BC2251DFE7000A5848 /* BeResult.swift */; };
106112C22251E0FD000A5848 /* BeResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 106112BC2251DFE7000A5848 /* BeResult.swift */; };
106112C52251E13B000A5848 /* BeResultTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 106112C42251E13B000A5848 /* BeResultTest.swift */; };
106112C62251E13B000A5848 /* BeResultTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 106112C42251E13B000A5848 /* BeResultTest.swift */; };
106112C72251E13B000A5848 /* BeResultTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 106112C42251E13B000A5848 /* BeResultTest.swift */; };
1F0648CC19639F5A001F9C46 /* ObjectWithLazyProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648CB19639F5A001F9C46 /* ObjectWithLazyProperty.swift */; };
1F0648CD19639F5A001F9C46 /* ObjectWithLazyProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648CB19639F5A001F9C46 /* ObjectWithLazyProperty.swift */; };
1F0648D41963AAB2001F9C46 /* SynchronousTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648D31963AAB2001F9C46 /* SynchronousTest.swift */; };
Expand Down Expand Up @@ -492,6 +498,8 @@

/* Begin PBXFileReference section */
0477153423B740AD00402D4E /* DispatchTimeInterval.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DispatchTimeInterval.swift; sourceTree = "<group>"; };
106112BC2251DFE7000A5848 /* BeResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeResult.swift; sourceTree = "<group>"; };
106112C42251E13B000A5848 /* BeResultTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeResultTest.swift; sourceTree = "<group>"; };
1F0648CB19639F5A001F9C46 /* ObjectWithLazyProperty.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjectWithLazyProperty.swift; sourceTree = "<group>"; };
1F0648D31963AAB2001F9C46 /* SynchronousTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SynchronousTest.swift; sourceTree = "<group>"; };
1F14FB63194180C5009F2A08 /* utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = utils.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -812,6 +820,7 @@
1F925F0A195C18E100ED456B /* BeLessThanTest.swift */,
1F925EEE195C136500ED456B /* BeLogicalTest.swift */,
1F925EF8195C175000ED456B /* BeNilTest.swift */,
106112C42251E13B000A5848 /* BeResultTest.swift */,
1F91DD2C1C74BF36002C309F /* BeVoidTest.swift */,
7B13BA091DD360DE00C9098C /* ContainElementSatisfyingTest.swift */,
1F925F01195C189500ED456B /* ContainTest.swift */,
Expand Down Expand Up @@ -864,6 +873,7 @@
1FD8CD161968AB07008ED995 /* BeLessThanOrEqual.swift */,
1FD8CD171968AB07008ED995 /* BeLogical.swift */,
1FD8CD181968AB07008ED995 /* BeNil.swift */,
106112BC2251DFE7000A5848 /* BeResult.swift */,
1F91DD301C74BF61002C309F /* BeVoid.swift */,
1FD8CD1A1968AB07008ED995 /* Contain.swift */,
7B13BA051DD360AA00C9098C /* ContainElementSatisfying.swift */,
Expand Down Expand Up @@ -1321,6 +1331,7 @@
CDFB6A401F7E082500AD8CC7 /* CwlDarwinDefinitions.swift in Sources */,
1FD8CD401968AB07008ED995 /* BeCloseTo.swift in Sources */,
1F1871C81CA89EDB00A34BF2 /* NMBExceptionCapture.m in Sources */,
106112C02251E0FA000A5848 /* BeResult.swift in Sources */,
1FD8CD361968AB07008ED995 /* Expectation.swift in Sources */,
1FD8CD321968AB07008ED995 /* NimbleXCTestHandler.swift in Sources */,
1F43728F1A1B344000EB80F8 /* Stringers.swift in Sources */,
Expand Down Expand Up @@ -1430,6 +1441,7 @@
1F299EAB19627B2D002641AF /* BeEmptyTest.swift in Sources */,
7B13BA111DD361EB00C9098C /* ObjCContainElementSatisfyingTest.m in Sources */,
1F925EF6195C147800ED456B /* BeCloseToTest.swift in Sources */,
106112C62251E13B000A5848 /* BeResultTest.swift in Sources */,
1F4A56791A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m in Sources */,
A8A3B6F6207329DD00E25A08 /* SatisfyAllOfTest.swift in Sources */,
AE7ADE491C80C00D00B94CD3 /* MatchErrorTest.swift in Sources */,
Expand Down Expand Up @@ -1505,6 +1517,7 @@
1F5DF17A1BDCA0F500C3A531 /* BeEmpty.swift in Sources */,
1F5DF18C1BDCA0F500C3A531 /* Await.swift in Sources */,
1F1871D81CA89EEF00A34BF2 /* NMBStringify.m in Sources */,
106112C22251E0FD000A5848 /* BeResult.swift in Sources */,
1F5DF1821BDCA0F500C3A531 /* BeNil.swift in Sources */,
1F5DF16F1BDCA0F500C3A531 /* AssertionDispatcher.swift in Sources */,
964CFEFF1C4FF48900513336 /* ThrowAssertion.swift in Sources */,
Expand Down Expand Up @@ -1568,6 +1581,7 @@
1F5DF1A61BDCA10200C3A531 /* EndWithTest.swift in Sources */,
CD79C9A31D2CC841004B6F9A /* ObjCBeFalseTest.m in Sources */,
1F5DF1A71BDCA10200C3A531 /* EqualTest.swift in Sources */,
106112C72251E13B000A5848 /* BeResultTest.swift in Sources */,
CD79C9AA1D2CC848004B6F9A /* ObjCBeLessThanOrEqualToTest.m in Sources */,
1F5DF1931BDCA10200C3A531 /* SynchronousTest.swift in Sources */,
CD79C9A11D2CC83B004B6F9A /* ObjCBeCloseToTest.m in Sources */,
Expand Down Expand Up @@ -1602,6 +1616,7 @@
CDFB6A3F1F7E082500AD8CC7 /* CwlDarwinDefinitions.swift in Sources */,
1FD8CD411968AB07008ED995 /* BeCloseTo.swift in Sources */,
1F1871D31CA89EEE00A34BF2 /* NMBExceptionCapture.m in Sources */,
106112BD2251DFE7000A5848 /* BeResult.swift in Sources */,
1FD8CD371968AB07008ED995 /* Expectation.swift in Sources */,
1FD8CD331968AB07008ED995 /* NimbleXCTestHandler.swift in Sources */,
1F43728E1A1B343F00EB80F8 /* Stringers.swift in Sources */,
Expand Down Expand Up @@ -1719,6 +1734,7 @@
1F4A56801A3B333F009E1637 /* ObjCBeLessThanTest.m in Sources */,
1F925EE7195C121200ED456B /* AsynchronousTest.swift in Sources */,
1F0648CD19639F5A001F9C46 /* ObjectWithLazyProperty.swift in Sources */,
106112C52251E13B000A5848 /* BeResultTest.swift in Sources */,
1F4A56861A3B33A0009E1637 /* ObjCBeTruthyTest.m in Sources */,
DD9A9A9019CF43AD00706F49 /* BeIdenticalToObjectTest.swift in Sources */,
1F4BB8B61DACA0E30048464B /* ThrowAssertionTest.swift in Sources */,
Expand Down
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ expect(ocean.isClean).toEventually(beTruthy())
- [Collection Elements](#collection-elements)
- [Collection Count](#collection-count)
- [Notifications](#notifications)
- [Result](#result)
- [Matching a value to any of a group of matchers](#matching-a-value-to-any-of-a-group-of-matchers)
- [Custom Validation](#custom-validation)
- [Writing Your Own Matchers](#writing-your-own-matchers)
Expand Down Expand Up @@ -1190,6 +1191,35 @@ expect {

> This matcher is only available in Swift.
## Result

```swift
// Swift
let aResult: Result<String, Error> = .success("Hooray")

// passes if result is .success
expect(aResult).to(beSuccess())

// passes if result value is .success and validates Success value
expect(aResult).to(beSuccess { value in
expect(value).to(equal("Hooray"))
})


enum AnError: Error {
case somethingHappened
}
let otherResult: Result<String, Error> = .failure(AnError.somethingHappened)

// passes if result is .failure
expect(otherResult).to(beFailure())

// passes if result value is .failure and validates error
expect(otherResult).to(beFailure { error in
expect(error).to(matchError(AnError.somethingHappened))
})
```

## Matching a value to any of a group of matchers

```swift
Expand Down
33 changes: 33 additions & 0 deletions Sources/Nimble/Matchers/BeResult.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import Foundation

///
/// A Nimble matcher for Result that succeeds when the actual value is success
///
/// You can pass a closure to do any arbitrary custom matching
/// to the value inside result. The closure only gets called when result is success.
public func beSuccess<T>(test: ((T) -> Void)? = nil) -> Predicate<Result<T, Error>> {
return Predicate.define("be <success>") { expression, message in
guard case let .success(value)? = try expression.evaluate()
else {
return PredicateResult(status: .doesNotMatch, message: message)
}
test?(value)
return PredicateResult(status: .matches, message: message)
}
}

///
/// A Nimble matcher for Result that succeeds when the actual value is failure
///
/// You can pass a closure to do custom matching for the error inside result.
/// The closure only gets called when result is failure.
public func beFailure<T>(test: ((Error) -> Void)? = nil) -> Predicate<Result<T, Error>> {
return Predicate.define("be <failure>") { expression, message in
guard case let .failure(error)? = try expression.evaluate()
else {
return PredicateResult(status: .doesNotMatch, message: message)
}
test?(error)
return PredicateResult(status: .matches, message: message)
}
}
59 changes: 59 additions & 0 deletions Tests/NimbleTests/Matchers/BeResultTest.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import XCTest
import Nimble

private struct StubError: Error, CustomDebugStringConvertible {
let debugDescription = "StubError"
}

final class BeSuccessTest: XCTestCase {
func testPositiveMatch() {
let successfulResult: Result<Int, Error> = .success(1)
expect(successfulResult).to(beSuccess())
}

func testPositiveMatchWithValueTesting() {
let stubValue = 1
let successfulResult: Result<Int, Error> = .success(stubValue)
expect(successfulResult).to(beSuccess { value in
expect(value).to(equal(stubValue))
})
}

func testNegativeMatch() {
let failureResult: Result<Int, Error> = .failure(StubError())
expect(failureResult).toNot(beSuccess())
}

func testExpectationFailureMessage() {
let failureResult: Result<Int, Error> = .failure(StubError())
failsWithErrorMessage("expected to be <success>, got <failure(StubError)>") {
expect(failureResult).to(beSuccess())
}
}
}

final class BeFailureTest: XCTestCase {
func testPositiveMatch() {
let failureResult: Result<Int, Error> = .failure(StubError())
expect(failureResult).to(beFailure())
}

func testPositiveMatchWithValueTesting() {
let failureResult: Result<Int, Error> = .failure(StubError())
expect(failureResult).to(beFailure { value in
expect(value).to(matchError(StubError.self))
})
}

func testNegativeMatch() {
let successfulResult: Result<Int, Error> = .success(1)
expect(successfulResult).toNot(beFailure())
}

func testExpectationFailureMessage() {
let successfulResult: Result<Int, Error> = .success(1)
failsWithErrorMessage("expected to be <failure>, got <success(1)>") {
expect(successfulResult).to(beFailure())
}
}
}

0 comments on commit d6e0345

Please sign in to comment.