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
Swift Async/Await Support #1160
Conversation
Generated by 🚫 Danger |
2cd7897
to
2b1f7ca
Compare
For those following along, changes that I just pushed include:
|
Whoops. Putting this back to a draft while I figure out the issues with 13.3.1. Not quite ready to drop that version of Xcode yet. |
@younata I'd like to use async/await in Quick. Is there any plan to merge this PR soon? |
This PR still has a number of issues with it. Notably getting Afterwards, I plan to close out the other Quick 6.0 tasks and then release. |
8bbe28e
to
327dc59
Compare
@younata Thanks for letting me know the status. I look forward to this new async support! |
I just tried this in our codebase, new async tests work like a charm! but some of our old RxSwift tests are failing now, this seems to be related to that this pr executes as much as possible on the main thread icm with an RxSwift observable also executing code on the main thread Here is an example failing rxswift test, where this one would succeed before this pr, and it also succeeds after removing the dispatching result on the main thread
Edit1:
|
Thanks for the feedback @stefanrenne! You'll note that in the changes I just pushed, I got rid of most of the |
Ok, this has been fun. Apparently, while I fixed the |
Cool I just discovered that you can mark beforeEach / it to be run on the mainActor
I like it but for me this introduces some rework for our testsuite, so I would suggest to still make this a major release. Also I think nimble needs an upgrade because now I'm getting this crash |
Warning: This does not work as-is. Additionally, aroundEach is dropped. I'll be fixing both in future commits.
…or aroundEach on objective-C.
…TestTimeout, and fulfill the sync test expectation on the main thread
However, this requires that beforeEach and afterEach (and aroundEach) run off the main thread. Which is not the direction we aim to go in. Next commit will effectively be removing this, but also adding tests that beforeEach, afterEach and aroundEach all run on the main thread
… thread This, unfortunately, re-breaks aroundEach in objective-c
Figured this out while writing explanation for why we need to drop Swift 5.6 support. lol.
There are fundamental problems getting synchronous aroundEach required by objective-c to work in the now-async world. The only 'solution' I saw to this was maintaining two implementations of 'World', one for sync and the other for async, which is too much of a maintenance burden for this.
030d07e
to
2c1ef24
Compare
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [Quick/Quick](https://togithub.com/Quick/Quick) | major | `from: "5.0.1"` -> `from: "v7.1.0"` | --- ### Release Notes <details> <summary>Quick/Quick (Quick/Quick)</summary> ### [`v7.1.0`](https://togithub.com/Quick/Quick/releases/tag/v7.1.0) [Compare Source](https://togithub.com/Quick/Quick/compare/v7.0.2...v7.1.0) ### Highlights #### New Features - You can now use `throw` in `beforeEach`, `justBeforeEach`, and `afterEach` blocks. - Quick now suggests to XCTest that tests run in the order they are defined in. #### Fixes - `beforeEach` blocks specified in configurations are now run in AsyncSpec tests. - `xitBehavesLike(_ name: String)` is now available in `QuickSpec` and `Behavior`. ### Autogenerated ChangeLog #### What's Changed - Bump danger from 9.3.0 to 9.3.1 by [@​dependabot](https://togithub.com/dependabot) in [Quick/Quick#1224 - Ensure beforeEach in Configuration run for AsyncSpec by [@​junmo-kim](https://togithub.com/junmo-kim) in [Quick/Quick#1228 - Allow beforeEach, justBeforeEach, and afterEach in Swift to throw by [@​younata](https://togithub.com/younata) in [Quick/Quick#1229 - Improve documentation for installing Quick and Nimble via Cocoapods in the README. by [@​younata](https://togithub.com/younata) in [Quick/Quick#1231 - Make a public xitBehavesLike(\_ name: String) for SyncDSLUser by [@​younata](https://togithub.com/younata) in [Quick/Quick#1230 - Attempt to run tests within a QuickSpec or AsyncSpec in the order they are defined in by [@​younata](https://togithub.com/younata) in [Quick/Quick#1232 #### New Contributors - [@​junmo-kim](https://togithub.com/junmo-kim) made their first contribution in [Quick/Quick#1228 **Full Changelog**: Quick/Quick@v7.0.2...v7.1.0 ### [`v7.0.2`](https://togithub.com/Quick/Quick/releases/tag/v7.0.2) [Compare Source](https://togithub.com/Quick/Quick/compare/v7.0.1...v7.0.2) This is a bug fix release that primarily fixes a conflict in how Nimble defines `FileString` and how Quick defines `FileString` when you use both via Swift Package Manager. It also fixes a number of warnings people who install Quick via Swift Package Manager on Darwin will receive. #### What's Changed - Correct a few places where we falsely assume "SWIFT_PACKAGE" == not darwin by [@​younata](https://togithub.com/younata) in [Quick/Quick#1223 **Full Changelog**: Quick/Quick@v7.0.1...v7.0.2 ### [`v7.0.1`](https://togithub.com/Quick/Quick/releases/tag/v7.0.1): 7.0.1 - re-allow async calls in AsyncSpec's xit [Compare Source](https://togithub.com/Quick/Quick/compare/v7.0.0...v7.0.1) This fixes an oversight where you couldn't use async closures with `xit`. Thanks [@​stonko1994](https://togithub.com/stonko1994) for calling this out! #### What's Changed - Allow xit in the Async DSL to take in async closures by [@​younata](https://togithub.com/younata) in [Quick/Quick#1220 **Full Changelog**: Quick/Quick@v7.0.0...v7.0.1 ### [`v7.0.0`](https://togithub.com/Quick/Quick/releases/tag/v7.0.0): - AsyncSpec and Human-Readable Test Selectors [Compare Source](https://togithub.com/Quick/Quick/compare/v6.1.0...v7.0.0) ### Highlights #### Async Test Changes Quick 7 changes how Async tests are run. Instead of forcing all tests to run in an async context, Quick 7 provides a separate Spec class for Async Tests. Create an `AsyncSpec` subclass, and all tests inside of that subclass will run in an async context. Tests inside of `QuickSpec` subclasses will have a similar behavior to what was in Quick 5. Additionally, Quick 7 changes how the DSL is defined slightly. In Quick 6 and before, the DSL was defined as a series of global functions, available to be called anywhere. In Quick 7, these functions were moved to be static methods on the new `SyncDSLUser` (which `QuickSpec`, `Behavior`, and `QuickConfiguration` conform to) and `AsyncDSLUser` (which `AsyncSpec` and `AsyncBehavior` conform to) protocols. This allows us to make sure that you are using the correct DSL for the context, and was necessary for this approach. For example: ```swift class SynchronousSpec: QuickSpec { override class func spec() { it("runs synchronously, as you'd expect") { var ocean: [String] = [] DispatchQueue.main.async { ocean.append("dolphins") ocean.append("whales") } expect(ocean).toEventually(contain("dolphins", "whales")) } } } class AsynchronousSpec: AsyncSpec { override class func spec() { it("runs the test in an async context") { var ocean: [String] = [] DispatchQueue.main.async { ocean.append("dolphins") ocean.append("whales") } await expect(ocean).toEventually(contain("dolphins", "whales")) } } } ``` #### Unencoded Test Selectors Furthermore, Quick 7 changes how test selectors are generated for `QuickSpec`. Now, both `AsyncSpec` and `QuickSpec` will use the unencoded test names as the test selectors. Test selectors are now generated by joining the `describe`/`context` blocks leading up to the `it` block with ", ". This makes test names immensely easier to read. For example, with the following spec: ```swift class MySpec: QuickSpec { override class func spec() { describe("some feature") { context("in one case") { it("has a behavior") {} } context("in another case") { it("doesn't have the earlier behavior") {} } } } } ``` will generate the following test selectors: - `some feature, in one case, has a behavior` - `some feature, in another case, doesn't have the earlier behavior` You can disable this change by setting the `QUICK_USE_ENCODED_TEST_SELECTOR_NAMES` environment variable. #### Migrating Suggestions Quick 7 is not a drop-in migration from either Quick 5 or Quick 6. Quick 5 users will have a slightly easier time upgrading, but due to `spec` being defined as a class method instead of an instance method, there will still be changes. Doing a Find & Replace of `override func spec` with `override class func spec` will take care of the low-hanging fruit. If you have any test helpers that exist as properties or methods of your QuickSpec subclasses, the you will need to either move them inside of the `spec` function, or outside to another scope. For Objective-C users, this is, for the most part, a drop-in replacement. You will only need to do anything if you do not use the `QuickSpecBegin` and `QuickSpecEnd` macros (in which case: do a find & replace of the regex `-(\s*)\(void\)(\s*)spec` with `+$1(void)$2spec`). For migrating from Quick 6 to Quick 7, it would be easiest to also do a Find & Replace of `: QuickSpec` to `: AsyncSpec`, then migrate tests that do not need to run in async contexts to be `QuickSpec`s themselves. ### Auto-Generated Changelog #### What's Changed - Bump git from 1.12.0 to 1.13.0 by [@​dependabot](https://togithub.com/dependabot) in [Quick/Quick#1191 - (Temporarily) Remove async support from Quick by [@​younata](https://togithub.com/younata) in [Quick/Quick#1192 - Bump activesupport from 6.1.5 to 6.1.7.1 by [@​dependabot](https://togithub.com/dependabot) in [Quick/Quick#1196 - Bump danger from 9.1.0 to 9.2.0 by [@​dependabot](https://togithub.com/dependabot) in [Quick/Quick#1198 - Transition QuickSpec.spec to be a static method. by [@​younata](https://togithub.com/younata) in [Quick/Quick#1200 - Add async duplicate-world based support. by [@​younata](https://togithub.com/younata) in [Quick/Quick#1199 - Bump cocoapods from 1.11.3 to 1.12.0 by [@​dependabot](https://togithub.com/dependabot) in [Quick/Quick#1201 - Bump activesupport from 7.0.4.2 to 7.0.4.3 by [@​dependabot](https://togithub.com/dependabot) in [Quick/Quick#1203 - Bump fkirc/skip-duplicate-actions from 5.2.0 to 5.3.0 by [@​dependabot](https://togithub.com/dependabot) in [Quick/Quick#1188 - \[Translation] AsyncAwait.md Korean translation by [@​tisohjung](https://togithub.com/tisohjung) in [Quick/Quick#1204 - Update Nimble to v12 by [@​younata](https://togithub.com/younata) in [Quick/Quick#1206 - Demangle QuickSpec test names as much as possible by [@​younata](https://togithub.com/younata) in [Quick/Quick#1207 - Add mechanism to fallback to legacy test selector names by [@​younata](https://togithub.com/younata) in [Quick/Quick#1211 - Bump cocoapods from 1.12.0 to 1.12.1 by [@​dependabot](https://togithub.com/dependabot) in [Quick/Quick#1210 - Bump danger from 9.2.0 to 9.3.0 by [@​dependabot](https://togithub.com/dependabot) in [Quick/Quick#1209 - Don't imply that we plan to remove the option to force encoded test selector names by [@​younata](https://togithub.com/younata) in [Quick/Quick#1212 - Merge branch quick\_7 into main. by [@​younata](https://togithub.com/younata) in [Quick/Quick#1213 - \[doc] Corrected to class method by [@​coffmark](https://togithub.com/coffmark) in [Quick/Quick#1214 - Update the english documentation for Quick 7 by [@​younata](https://togithub.com/younata) in [Quick/Quick#1215 - Provide a way to get the currently running spec, regardless of if we're executing an AsyncSpec or a QuickSpec by [@​younata](https://togithub.com/younata) in [Quick/Quick#1216 #### New Contributors - [@​tisohjung](https://togithub.com/tisohjung) made their first contribution in [Quick/Quick#1204 - [@​coffmark](https://togithub.com/coffmark) made their first contribution in [Quick/Quick#1214 **Full Changelog**: Quick/Quick@v6.1.0...v7.0.0 ### [`v6.1.0`](https://togithub.com/Quick/Quick/releases/tag/v6.1.0) [Compare Source](https://togithub.com/Quick/Quick/compare/v6.0.1...v6.1.0) ### Highlighted Changes - New `TestState` property wrapper (Thanks [@​CraigSiemens](https://togithub.com/CraigSiemens)!). You can now wrap properties with `@TestState` to have them automatically set to nil. - Objective-C API is no longer available in Swift, this should reduce confusion whether a test is being executed in an async context or not. - This release drops support for Swift 5.6/Xcode 13.3.1. ### Auto-generated Release Notes #### What's Changed - Bump danger from 9.0.0 to 9.1.0 by [@​dependabot](https://togithub.com/dependabot) in [Quick/Quick#1184 - Make Objective-C API unavailable in Swift. by [@​younata](https://togithub.com/younata) in [Quick/Quick#1185 - Update Nimble to 11.2.1, remove now-unnecessary usage of awaits in tests. Drop support for swift 5.6/Xcode 13.3.1 by [@​younata](https://togithub.com/younata) in [Quick/Quick#1187 - Added a `TestState` property wrapper. by [@​CraigSiemens](https://togithub.com/CraigSiemens) in [Quick/Quick#1186 #### New Contributors - [@​CraigSiemens](https://togithub.com/CraigSiemens) made their first contribution in [Quick/Quick#1186 **Full Changelog**: Quick/Quick@v6.0.1...v6.1.0 ### [`v6.0.1`](https://togithub.com/Quick/Quick/releases/tag/v6.0.1) [Compare Source](https://togithub.com/Quick/Quick/compare/v6.0.0...v6.0.1) #### What's Changed - Force async in `fit`, `xit`, `pending` and `justBeforeEach` by [@​younata](https://togithub.com/younata) in [Quick/Quick#1183 **Full Changelog**: Quick/Quick@v6.0.0...v6.0.1 ### [`v6.0.0`](https://togithub.com/Quick/Quick/releases/tag/v6.0.0) [Compare Source](https://togithub.com/Quick/Quick/compare/v5.0.1...v6.0.0) This closes the [v6.0.0 milestone](https://togithub.com/Quick/Quick/milestone/8). ### Highlights See additional details under the auto-generated release notes below. #### Fixed - No more sporadic crashes attempting to detect subclasses [Quick/Quick#1156 - Rerunning an individual test [Quick/Quick#1166 - Skipped tests are reported to Xcode [Quick/Quick#1098 #### New - Async/await support. All tests now run in an async context. [Quick/Quick#1160 - You can now throw a `StopTest` error to end a test prematurely without it being reported as an error. [Quick/Quick#1165 - Added the `justBeforeEach` operator, which takes a closure and runs it immediately prior to the relevant `it` tests. [Quick/Quick#1169 For example ```swift var ordering: [Int] = [] beforeEach { ordering.append(1) } justBeforeEach { ordering.append(3) } beforeEach { ordering.append(2) } it("runs justBeforeEach after the other beforeEach's") { expect(ordering).to(equal([1, 2, 3])) } ``` #### Breaking - This version raises minimum required version to Swift 5.6, and required OS to macOS 10.15, iOS 13, and tvOS 13. - `aroundEach` is removed from the Objective-C API [Quick/Quick#1160 - Again, with the async support, all tests now run in an async context. This will require you to make changes, especially if you use Nimble. ### Auto-Generated Release Notes #### What's Changed - Create funding.yml by [@​jessesquires](https://togithub.com/jessesquires) in [Quick/Quick#1147 - Report skipped tests to Xcode by [@​amomchilov](https://togithub.com/amomchilov) in [Quick/Quick#1098 - Bump danger from 8.6.0 to 8.6.1 by [@​dependabot](https://togithub.com/dependabot) in [Quick/Quick#1148 - Renamed Configuration -> QCKConfiguration on documentation by [@​takehilo](https://togithub.com/takehilo) in [Quick/Quick#1152 - Fix sporadic crashes caused by finding classes that don't play well with isSubclass(of:) by [@​younata](https://togithub.com/younata) in [Quick/Quick#1156 - Raise minimum supported versions to macOS 10.15, iOS 13, tvOS 13 by [@​younata](https://togithub.com/younata) in [Quick/Quick#1146 - version up Nimble in Package.swift by [@​kimxwan0319](https://togithub.com/kimxwan0319) in [Quick/Quick#1153 - Update Nimble submodule checkout to refer to the Nimble v10.0.0 commit by [@​younata](https://togithub.com/younata) in [Quick/Quick#1157 - Fix tests broken by Nimble 10 update by [@​younata](https://togithub.com/younata) in [Quick/Quick#1158 - Add [@​younata](https://togithub.com/younata) to funding.yml by [@​younata](https://togithub.com/younata) in [Quick/Quick#1164 - Bump danger from 8.6.1 to 9.0.0 by [@​dependabot](https://togithub.com/dependabot) in [Quick/Quick#1168 - Allow throwing in a test without producing an unexpected error by [@​bnickel](https://togithub.com/bnickel) in [Quick/Quick#1165 - Allow rerunning individual examples in Xcode by [@​bnickel](https://togithub.com/bnickel) in [Quick/Quick#1166 - Bump fkirc/skip-duplicate-actions from 4.0.0 to 5.1.0 by [@​dependabot](https://togithub.com/dependabot) in [Quick/Quick#1171 - Introduce an `assignBefore` operator by [@​esilverberg](https://togithub.com/esilverberg) in [Quick/Quick#1169 - Bump fkirc/skip-duplicate-actions from 5.1.0 to 5.2.0 by [@​dependabot](https://togithub.com/dependabot) in [Quick/Quick#1172 - Add support for xcode 14 and swift 5.7 by [@​younata](https://togithub.com/younata) in [Quick/Quick#1174 - Swift Async/Await Support by [@​younata](https://togithub.com/younata) in [Quick/Quick#1160 - Update Nimble to V11 by [@​younata](https://togithub.com/younata) in [Quick/Quick#1175 #### New Contributors - [@​amomchilov](https://togithub.com/amomchilov) made their first contribution in [Quick/Quick#1098 - [@​takehilo](https://togithub.com/takehilo) made their first contribution in [Quick/Quick#1152 - [@​kimxwan0319](https://togithub.com/kimxwan0319) made their first contribution in [Quick/Quick#1153 - [@​bnickel](https://togithub.com/bnickel) made their first contribution in [Quick/Quick#1165 - [@​esilverberg](https://togithub.com/esilverberg) made their first contribution in [Quick/Quick#1169 **Full Changelog**: Quick/Quick@v5.0.1...v6.0.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. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/cgrindel/rules_swift_package_manager). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNS4xNTkuNyIsInVwZGF0ZWRJblZlciI6IjM1LjE1OS43IiwidGFyZ2V0QnJhbmNoIjoibWFpbiJ9--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR provides basic swift concurrency support. Now, you can
await
functions inside ofbeforeEach
,afterEach
,aroundEach
,it
,fit
, andxit
blocks.Note: The various itBehavesLike closures will not take in async closures. These closures should not have any logic in them and should instead just be simple assignment/passing in pre-assigned variables.
For example, the following tests are now possible:
Breaking Changes
Where possible, I took efforts to try to ease this transition as much as possible. However, this will almost certainly require you to make changes to your test suite.
it
,beforeEach
,afterEach
andaroundEach
blocks) no longer run on the main thread by default.@MainActor
in the relevant closure to get the code to run on the main thread, like so:aroundEach
must nowawait
the runExample closure, like so:aroundEach
is no longer available in Objective-C tests.aroundEach
in Objective-C to work, I decided that it wasn't worth the effort and dropped it. My apologies to those who usearoundEach
in Objective-C.Todo
Future Work