Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce the require dsl. For when you need the assertion to pass before continuing #1103

Merged
merged 12 commits into from
Dec 20, 2023

Conversation

younata
Copy link
Member

@younata younata commented Nov 30, 2023

Fixes #1102

This is essentially expect, but it returns the result of the expression if the matcher passes (and throws if it doesn't). Very useful for cases where you want to make sure the matcher passes before continuing with a test.

Also, in addition to the require dsl, this also adds unwrap and pollUnwrap, which are shorthands for require(...).toNot(beNil()) and require(...).toEventuallyNot(beNil()).

This also marks Expectation.onFailure as deprecated, as the require DSL entirely replaces that API.

Todo for this PR:

  • Backfill more tests.
  • Polling functionality (toEventually and the like).
  • unwrap but for polling functionality (a shorthand for require(...).toEventuallyNot(beNil()).
  • Support async expressions and matchers.
  • require's to/toNot/toEventually/etc. methods should be tagged with @discardableResult.
  • Documentation.

Future Work

  • Get better at caching expression such that the last call to an expression is cached. It makes no sense that we evaluate the expression at least twice in both expect and require - in the matcher, and when putting together the error information.
  • Clean up Expression so that it's () -> Value instead of () -> Value?.
  • Clean up the polling code so that there's a whole lot less duplication.

…xpression

As implied, this is basically a copy-paste of the functionality of expect. It's not complete, and it's not well-tested. But it gets the idea across.
Future work is cleaning this up, backfilling tests for features (such as the unwrap function), and adding support for polling requirements (i.e. toEventually).

Other than functionality, require also files the errorThrown issue type with XCTest, whereas expect files the assertionFailed issue type. This has minor differences that are mostly semantics.

Also, in addition to the require dsl, this also adds unwrap, which is a shorthand for `require(...).toNot(beNil())`.
Support async, but not yet polling.
Oh, gosh. This is terrible. I think a cleaner way to do this would be to change MatcherResult to also store the most recent value.
But that would be a breaking change, and might require updating existing matchers, so... no.
@younata
Copy link
Member Author

younata commented Dec 14, 2023

In my own dogfooding of this, I realized that it'll be a fairly common usecase to use require simply as a gate, and not to return the value from an expression once it passes a matcher.

Rename requireAsync to requirea - matching the example set forth by expecta.
Adds requires, which is requirea, but for specifying SyncRequirement.
Update the table of contents with doctoc.
…corded as test assertion failures, which is what they are anyway.
Also actually mark the non-polling require dsl as discardableResult
@younata younata marked this pull request as ready for review December 18, 2023 16:26
@younata younata changed the title Introduce the require dsl. Which is like expect, but it returns the result of the expression Introduce the require dsl. For when you need the assertion to pass before continuing Dec 18, 2023
@younata younata merged commit c60d66d into main Dec 20, 2023
14 checks passed
@younata younata deleted the require_dsl branch December 20, 2023 15:46
cgrindel-self-hosted-renovate bot referenced this pull request in cgrindel/rules_swift_package_manager Dec 22, 2023
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [Quick/Nimble](https://togithub.com/Quick/Nimble) | minor | `from:
"13.0.0"` -> `from: "13.1.1"` |

---

### Release Notes

<details>
<summary>Quick/Nimble (Quick/Nimble)</summary>

### [`v13.1.1`](https://togithub.com/Quick/Nimble/releases/tag/v13.1.1):
- The Require DSL, but now with a fixed cocoapods build

[Compare
Source](https://togithub.com/Quick/Nimble/compare/v13.1.0...v13.1.1)

### Highlights

See [the previous
release](https://togithub.com/Quick/Nimble/releases/tag/v13.1.0) for
more on the require DSL.

#### BugFixes

-   Fix cocoapods release.

### Automated Release Notes

#### What's Changed

- Fix build on cocoapods by specifying the correct location for the
CocoaWithLove exception helper libraries by
[@&#8203;younata](https://togithub.com/younata) in
[https://github.com/Quick/Nimble/pull/1109](https://togithub.com/Quick/Nimble/pull/1109)

**Full Changelog**:
Quick/Nimble@v13.1.0...v13.1.1

### [`v13.1.0`](https://togithub.com/Quick/Nimble/releases/tag/v13.1.0):
- The Require DSL

[Compare
Source](https://togithub.com/Quick/Nimble/compare/v13.0.0...v13.1.0)

### Highlights

#### New Features

- Introduce the `require` dsl. This throws an error (a `RequireError`,
or a custom one) if the matcher used with it fails. If the matcher
doesn't fail, then the require dsl will return the result of the
expression.
- For example, `try require([1, 2, 3]).to(haveCount(3))` will return
`[1, 2, 3]`. However `try require(2).toEqual(1))` will throw a
`RequireError`.
- When the matcher fails, `require` will still register the assertion
failure with XCTest.
- This also adds `unwrap` and `pollUnwrap`, which are work as `try
require(...).toNot(beNil())` and `try
require(...).toEventuallyNot(beNil())`. With both sync and async
variants. They either throw, or return non-optional versions of the
expression.
- See the [documentation
here](https://togithub.com/Quick/Nimble/tree/v13.1.0#using-require-to-demand-that-a-matcher-pass-before-continuing)
for more.

#### Deprecations

- Removes `Expectation.onFailure`, as the new `require` dsl entirely
replaces that API. This deprecation will persist through Nimble 14,
before being marked as removed in Nimble 15 and fully removed in Nimble
16.

#### Breaking Changes

- The `throwAssertion` matcher no longer supports watchOS and tvOS in
the cocoapods distribution of Nimble. This is because Nimble no longer
directly embeds the CwlCatchException CwlPreconditionTesting libraries
used in that matcher and instead Nimble pulls in those libraries
transitively through the package manager used.

### Automated Release Notes

#### What's Changed

- Bump cocoapods from 1.13.0 to 1.14.2 by
[@&#8203;dependabot](https://togithub.com/dependabot) in
[https://github.com/Quick/Nimble/pull/1094](https://togithub.com/Quick/Nimble/pull/1094)
- Introduce the require dsl. For when you need the assertion to pass
before continuing by [@&#8203;younata](https://togithub.com/younata) in
[https://github.com/Quick/Nimble/pull/1103](https://togithub.com/Quick/Nimble/pull/1103)
- Pull in CwlCatchException and CwlPreconditionTesting transitively. by
[@&#8203;younata](https://togithub.com/younata) in
[https://github.com/Quick/Nimble/pull/1108](https://togithub.com/Quick/Nimble/pull/1108)

**Full Changelog**:
Quick/Nimble@v13.0.0...v13.1.0

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config help](https://togithub.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Renovate
Bot](https://togithub.com/renovatebot/renovate).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNi4xMDAuMCIsInVwZGF0ZWRJblZlciI6IjM2LjEwMC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiJ9-->

Co-authored-by: Self-hosted Renovate Bot <361546+cgrindel-self-hosted-renovate[bot]@users.noreply.github.enterprise.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
1 participant