Skip to content

Tags: arekt/Nimble

Tags

v7.3.0

Toggle v7.3.0's commit message

Verified

This tag was signed with the committer’s verified signature.
ikesyo IKEDA Sho
- Make `recordFailure` public, which is useful for defining a custom …

…`AssertionHandler` Quick#543, Quick#599 (Thanks @maryamaffinityclick and @ikesyo)

v7.2.0

Toggle v7.2.0's commit message

Verified

This tag was signed with the committer’s verified signature.
ikesyo IKEDA Sho
- Internal refactoring Quick#564, Quick#565, Quick#566, Quick#567, Qu…

…ick#568, Quick#569, Quick#570, Quick#571, Quick#572, Quick#573, Quick#577, Quick#578, Quick#579, Quick#580, Quick#581, Quick#584, Quick#589, Quick#590, Quick#595 (Thanks @ikesyo)

- Make `Expectation` constructor public Quick#576 (Thanks @ikesyo)

- Fix `ExpectationMessage.update(failureMessage:)` not to update a `FailureMessage` instance with empty string Quick#587 (Thanks @ikesyo)
- [containElementSatisfyingMatcher] Using `postfixMessage` would be preferable instead of overwriting `to` Quick#588 (Thanks @ikesyo)

v7.1.3

Toggle v7.1.3's commit message

Verified

This tag was signed with the committer’s verified signature.
ikesyo IKEDA Sho
- Add `-Xlinker -no_application_extension` to `OTHER_LDFLAGS` to sile…

…nce a linker warning Quick#541 (Thanks @ikesyo)

- Internal refactoring Quick#546, Quick#548, Quick#552, Quick#558 and Quick#559 (Thanks @ikesyo)

- Fix test failures with Xcode 10 Quick#534 (Thanks @sharplet)
- Fix that assertion failures stop a test suite execution Quick#545 (Thanks @ikesyo)
- Fix a build error on Swift 4.2 mode Quick#549 and Quick#554 (Thanks @sunshinejr and @ikesyo)

v7.1.2

Toggle v7.1.2's commit message

Verified

This tag was signed with the committer’s verified signature.
ikesyo IKEDA Sho
- Swift 4.2 and Xcode 10 support Quick#530, Quick#532 and Quick#536 (…

…Thanks @sharplet, @Dschee and @ikesyo)

- Fix CocoaPods integration issue regarding `APPLICATION_EXTENSION_API_ONLY` build setting Quick#525 (Thanks @ikesyo)

v7.1.1

Toggle v7.1.1's commit message

Verified

This tag was signed with the committer’s verified signature.
ikesyo IKEDA Sho
- Improve the interoperability with CocoaPods 1.5 Swift Static Librar…

…ies support (Thanks @ikesyo)

v7.1.0

Toggle v7.1.0's commit message

Verified

This tag was signed with the committer’s verified signature.
ikesyo IKEDA Sho
- Make `PredicateResult` members public for use in custom matchers Qu…

…ick#455 (Thanks @ishaanSejwal)

- Implement `satisfyAllOf` matcher and `&&` operator Quick#511 (Thanks @wongzigii)
- Xcode 9.3 support Quick#513 (Thanks @ikesyo)

- Fix `waitUntil` ignore `AsyncDefaults.Timeout` value Quick#512 (Thanks @wongzigii)

- README improvements Quick#497 and Quick#504 (Thanks @fphilipe and @revolter)

v7.0.3

Toggle v7.0.3's commit message

Verified

This tag was signed with the committer’s verified signature.
ikesyo IKEDA Sho
- Update CwlPreconditionTesting dependency and improve Thread Sanitiz…

…er interoperability Quick#472 (Thanks @ikesyo)

- Address some SwiftLint warnings Quick#484 (Thanks @wongzigii)

- Fix Swift 4.0.2 compatibility on Linux Quick#483 (Thanks @ikesyo)

v7.0.2

Toggle v7.0.2's commit message

Verified

This tag was signed with the committer’s verified signature.
ikesyo IKEDA Sho
This release fully supports Xcode 9 (both Swift 3.2 and Swift 4)! 🎉 T…

…his also contains a memory leak fix and some documentation updates.

- Support both Swift 3.x and Swift 4 Quick#457 (Thanks @ikesyo)
- Xcode 9 Support (Swift 3.2) Quick#446 (Thanks @shaps80 and @ikesyo)
- Address redundant conformance warnings in Swift 4 Quick#443 (Thanks @ikesyo)

- Fix memory leak when using async expectations Quick#449 and Quick#450 (Thanks @ryanfitz and @jeffh)

- README tweaks for Custom Validation Quick#462 (Thanks @holmes)
- Fix async Swift docs Quick#458 (Thanks @mrh-is)
- Show more illustrative example for waitUntil Quick#441 (Thanks @mrh-is)

v7.0.1

Toggle v7.0.1's commit message
A small release with a hotfix for Xcode 9 and some documentation upkeep.

Docs:

- Documentation update Quick#423 (Thanks @chamander)
- Fixed parameter name Quick#421 (Thanks @honghaoz)
- Fixed typos Quick#426 (Thanks @Lutzifer)

Bugfixes:

- Test in Swift 3 compatibility mode Quick#431 (Thanks @sharplet)
  - Fixes errors in Xcode 9
    `'Cannot use mutating member on immutable value: 'generator' is a 'let' constant`
- Fixed expectation regression & failure bugs Quick#428 (Thanks @jeffh)

v7.0.0

Toggle v7.0.0's commit message

Verified

This tag was signed with the committer’s verified signature.
jeffh Jeff Hui
v7.0.0

======

Nimble 7 is released! This is part of a series of major version releases to support a major change undergoing in Nimble - specifically how custom matchers are written. **If you don't use custom matchers, you should see little visible changes and can safely skip to the bottom to see the "Other Changes"**. But if you do use custom matchers or are interested in the technical details, continue reading.

In short, Nimble is replacing `Matcher` protocol with `Predicate` type. The `Predicate` type attempts to address several common pitfalls when creating custom matchers and allow for several major features in the future:

 - Protocol extension matchers: `expect(1).to.equal(1)`
 - Add more composable matchers: `expect([1, 2]).to(contain(1) && contain(2))`
 - Increase flexibility of existing composable matchers: `expect(1).to(equal(1) || beNil())`
 - Allow wrapping existing matchers like: `expect([1, 2]).to(contain(1).followed(by: 2))`

But we're getting ahead of ourselves for a future that isn't here yet (or guaranteed). Let's focus back on `Predicate`.

The New `Predicate` Type
======================

Nimble v7.0.0 introduces a new matcher API via the `Predicate` type (we used all the matcher names). For the purposes of discussion, matcher refers to the concept Nimble has for building expectations and `Matcher` refers to the (now) deprecated matcher API.

The main goal is to help make matcher writing less error-prone in several ways:

 - Support special `nil` handling typical for Nimble matchers.
 - Make error messaging explicit and less shared-state munging.
 - Be explicit about the trinary behavior matchers have instead of relying on bools.

`Predicate` aims to address these goals by changing the closure to be a pure function that returns a custom `PredicateResult` type. The `PredicateResult` type is simply two values:

```swift
PredicateResult(status: .fail, message: .expectedActualValueTo("equal <\(expected)>"))
```

`status` describes if the matcher succeeds or fails against the given value and `message` is the structured textual representation of that status. `status` is a trinary with the following values:

 - `.matches` - similar to returning "true". Indicates the expectation passes.
 - `.doesNotMatch` - similar to returning "false". Indicates the expectation failed, but negation would succeed (eg - `toNot`)
 - `.fail` - similar to returning "false". Indicates the expectation failed, even if negation was used.

This allows matchers to better indicate improper usages that would incorrectly pass if negated. If you need only the normal boolean-like return, use the alternative `PredicateResult` constructor:

```swift
PredicateResult(bool: true, message: ...)
```

The `message` argument supports a more structured error messaging that composable matchers can rely upon. It is currently limited, but is open for possible expansion if you file an issue.

`Predicate` replaces the following existing Nimble types:

 - `Matcher` - Use `Predicate` instead.
 - `NonNilMatcherFunc` - Use `Predicate` plus the `.requireNonNil` method
 - `MatcherFunc` - Use `Predicate` instead.

Since `Predicate` is not a protocol with an associated type, it makes function definitions much easier without requiring another type like `NonNilMatcherFunc`:

```swift
// OLD METHOD:
//   returning protocol
func equal<M: Matcher, T: Equatable where T == M.ValueType>(_ expected: T?) -> M { ... }
// OLD METHOD:
//   using NonNilMatcherFunc or MatcherFunc
func equal<T: Equatable>(_ expected: T?) -> NonNilMatcherFunc<T> { ... }

// NEW METHOD
func equal<T: Equatable>(_ expected: T?) -> Predicate<T> { ... }
```

Removing the protocol with associated type allows more composability among matchers. Previous these function types made composing them difficult:

```swift
// OLD METHOD:
func firstMatcher<M: Matcher, T: Equatable where T == M.ValueType>(_ expected: T?) -> M { ... }
func secondMatcher<T: Equatable>(_ expected: T?) -> NonNilMatcherFunc<T> { ... }
// can only specify every matcher in the generic
func usesOnlyTwoMatchers<M1: Matcher, M2: Matcher where M1.ValueType == M2.ValueType>(first: M1, second: M2) -> M

// NEW METHOD:
func firstMatcher<T: Equatable>(_ expected: T?) -> Predicate<T> { ... }
func secondMatcher<T: Equatable>(_ expected: T?) -> Predicate<T> { ... }
// can support many matchers
func usesManyMatchers<T>(matchers: [Predicate<T>]) -> Predicate<T>
```

Migrating to Predicate
----------------------

If you're not using custom matchers, there isn't any additional work for you 🎉.

To migrate existing matchers, Nimble v7.0.0 currently provides temporary constructors:

```swift
/// These constructors are for convenience in adopting Nimble v7.0.0, but will be removed in Nimble v9.0.0
// If you already have a Matcher type you need to simply convert to Predicate:
Predicate.fromDeprecatedMatcher(myMatcher)
// Alternatively, you can use the extension:
myMatcher.predicate
// If you want to construct a Predicate using the same arguments as MatcherFunc
Predicate.fromDeprecatedClosure { actualExpression, failureMessage -> Bool in ... }
// If you want to construct a Predicate using the same arguments as NonNilMatcherFunc
Predicate.fromDeprecatedClosure { actualExpression, failureMessage -> Bool in
    ...
}.requireNonNil
```

These are useful to quickly adopt Nimble v7.0.0, but it's better in the long run to adopt the proper `Predicate` API to last beyond Nimble v9.0.0:

```swift
// The simple way to implment a NonNilMatcherFunc matcher in the new Predicate way:
public func equal<T: Equatable>(_ expectedValue: T?) -> Predicate<T> {
    // Alternatively, you can use Predicate.simple if you don't modify `msg`.
    // When a string is given to .define(), then
    // msg = .expectedActualValueTo("equal <\(expectedValue)>")
    // Predicate.define and Predicate.simple imply calling .requireNonNil.
    Predicate.define("equal <\(expectedValue)>") { actualExpression, msg -> PredicateResult in
        let actualValue = try actualExpression.evaluate()
        let matches = actualValue == expectedValue && expectedValue != nil
        if expectedValue == nil || actualValue == nil {
            if expectedValue == nil && actualValue != nil {
                return PredicateResult(
                    status: .fail,
                    message: msg.appendedBeNilHint()
                )
            }
            return PredicateResult(status: .fail, message: msg)
        }
        return PredicateResult(status: PredicateStatus(bool: matches), message: msg)
    }
}

// For a MatcherFunc:
public func beNil<T>() -> Predicate<T> {
    // Alternatively, you can use Predicate.defineNilable
    return Predicate.simpleNilable("be nil") { actualExpression -> PredicateStatus in
        let actualValue = try actualExpression.evaluate()
        return PredicateStatus(bool: actualValue == nil)
    }
}
```

To ease the migration process, Nimble will be removing `Matcher` in after several major versions:

 - **v7.x.x** will introduce a new replacement to `Matcher` family of types via the `Predicate` type.
     - `Matcher`, `NonNilMatcherFunc`, `MatcherFunc` are marked as deprecated
     - Introduces temporary, migration-friendly constructors on `Predicate` to help suppress warnings for now.
 - **v8.x.x** will deprecate the temporary, migration friendly constructors.
 - **v9.x.x** will remove the old matcher types and temporary migration-friendly constructors.

New features that are released pre-v9.x.x will cater to the newer `Predicate` style.
Also, all built-in Nimble matchers currently use `Predicate` and `Predicate` also implemented the `Matcher` type until it's removal.

Other Changes
=============

`toSucceed` Matcher
-------------------

For quick, inline matchers, you can use `toSucceed` with the `ToSucceedResult` enum:

```swift
expect {
    return .succeeded
}.to(succeed())

expect {
    return .failed(reason: "expected a closure, got <nil> (use beNil() to match nils)")
}.to(succeed())
```

Changelog
---------

- ([Quick#390](Quick#390)) Introduce new Matcher API (aka, Predicates)
- ([Quick#417](Quick#417)) Fix optional binding violation for SwiftLint (thanks @ysk-tngc)
- ([Quick#410](Quick#410)) Adds `toSucceed` matcher (thanks @Rivukis)
- ([Quick#420](Quick#420)) Fix invalid reference to CwlCatchBadInstructionPOSIX.swift for case-sensitive file systems (thanks @dagio)

As always, happy testing 😎!