[webview_flutter] Convert from XCTest to Swift Testing#12243
Conversation
There was a problem hiding this comment.
Code Review
This pull request migrates the unit tests for the WKWebView implementation from the XCTest framework to the Swift Testing framework. The changes include replacing XCTest assertions with #expect, converting test classes to @Suite structs, and updating asynchronous test patterns to use modern Swift concurrency. The review feedback suggests using the Skip error to dynamically skip tests instead of returning early, and using #expect(throws: Never.self) to assert that no error is thrown instead of using withKnownIssue.
LongCatIsLooong
left a comment
There was a problem hiding this comment.
It looks like gemini is making some strange choices around async and throw tests. Most comments aren't blocking except the timeout one.
| registrar.logFlutterMethodFailure( | ||
| PigeonError(code: "code", message: "message", details: nil), methodName: "aMethod")) | ||
| // Method should log a message and not throw an error. | ||
| #expect(throws: Never.self) { |
There was a problem hiding this comment.
Uhm I have not used swift testing that much, but this doesn't look right. How can you throw a Never if you can't construct one in the first place? So from reading this the expectation seems to be "the closure never throws"?
There was a problem hiding this comment.
Oh I see gemini code review suggested that and the expectation is indeed "the closure does not throw". Never mind then. Although the testing framework treats all uncaught exceptions as failures so the Never.self is probably not really needed.
There was a problem hiding this comment.
I dug into this test more, and the structure is even weirder than it seemed at first glance because the method being called isn't throws. So once the throws: Never.self wrapper is removed you get a warning about calling try on something that doesn't throw.
I settled for just calling the method directly in the test, and putting a comment on the test saying not to add throws to it, and why. It's a bit weird, but seemed like the simplest way of expressing what the test is trying to prevent regressing.
| class ScriptMessageProxyAPITests: XCTestCase { | ||
| @MainActor func testName() { | ||
| @Suite struct ScriptMessageProxyAPITests { | ||
| @MainActor @Test func name() throws { |
There was a problem hiding this comment.
nit: this test doesn't actually throw does it? Since we are using try? ?
There was a problem hiding this comment.
Same question for the test below.
There was a problem hiding this comment.
I didn't notice how much the tests in this package used try?. I think in a Swift Testing world what we generally want is to try instead since the test system is designed to support reporting exceptions, so if something throws that was supposed to succeed it's better to get the exception than to just get a nil comparison failure in an #expect.
I scrubbed try? out of everything but the constructor tests. For those the explicit nil check seemed cleaner than a comment saying why there's no check, so I removed throws from just those.
|
|
||
| wait(for: [removeDataOfTypesExpectation], timeout: 10.0) | ||
| XCTAssertNotNil(removeDataOfTypesResult) | ||
| let _ = try await withCheckedThrowingContinuation { |
There was a problem hiding this comment.
IIRC withCheckedThrowingContinuation or @Test never times out by itself unless explicitly given a timeout value. Here if continuation.resume is never called, I suspect the test will hang.
There was a problem hiding this comment.
Also this test reads a bit weird since gemini went out of its way to type the continuation CheckedContinuation<Bool, Error> but never actually uses the return value.
There was a problem hiding this comment.
IIRC
withCheckedThrowingContinuationor@Testnever times out by itself unless explicitly given a timeout value. Here ifcontinuation.resumeis never called, I suspect the test will hang.
Yeah. In theory that's a feature (see here and here), so it's how we've been doing Swift Testing conversions.
I will say I don't love the dev experience, so longer term we may want to have a Flutter-team-level discussion around this. It was already kind of annoying for manual development, but what I discovered while doing this round of conversions using Gemini instead of doing it manually is that it's quite bad for agentic development because the agent will frequently make a bunch of changes, kick of the tests to see how they turn out, and then just say "Now I'll wait for the tests to finish"... and just wait forever until a human intercedes.
There was a problem hiding this comment.
(If we do later decided to move away from tests that can hang forever, I think we would sweep the entire repo and add timeLimit traits to everything at a suite level.)
…er#189782) flutter/packages@611899b...8260a1e 2026-07-20 jmccandless@google.com [cupertino_ui] Publish pre-release 0.0.2 (flutter/packages#12251) 2026-07-20 43054281+camsim99@users.noreply.github.com [camera_android_camerax] Add `AGENTS.md` (flutter/packages#12066) 2026-07-20 jmccandless@google.com [cupertino_ui] Undo unpublished version info (flutter/packages#12252) 2026-07-20 42726313+dao-wkm@users.noreply.github.com [video_player_android] Avoid sending unset duration on initialization (flutter/packages#11709) 2026-07-20 stuartmorgan@google.com [webview_flutter] Convert from XCTest to Swift Testing (flutter/packages#12243) 2026-07-20 stuartmorgan@google.com [various] Convert example boilerplate from Java to Kotlin (flutter/packages#12201) 2026-07-20 jmccandless@google.com [material_ui, cupertino_ui] Update changelogs for the prerelease (flutter/packages#12249) 2026-07-20 engine-flutter-autoroll@skia.org Roll Flutter from 8005793 to cab057d (2 revisions) (flutter/packages#12248) 2026-07-20 shuminlian@gmail.com [in_app_purchase_android] Add obfuscated profile ID purchase param (flutter/packages#12080) 2026-07-20 jmccandless@google.com [material_ui] Unpin material_color_utilities (flutter/packages#12225) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages-flutter-autoroll Please CC flutter-ecosystem@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
Converts all of the webview_flutter unit tests from XCTest to Swift testing. This was mostly done by Gemini (mostly purely mechanical conversion), with some minor cleanup after I reviewed it. As with other conversions, this is focused on converting more or less directly, without adopting new features like parameterization.
Part of flutter/flutter#180787
Pre-Review Checklist
[shared_preferences]///).Footnotes
Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling. ↩ ↩2