Skip to content

test(integration): migrate IntegrationTests to Swift Testing (Phase 6)#1097

Open
grdsdev wants to merge 1 commit into
mainfrom
test/sdk-1253-integrationtests-swift-testing-migration
Open

test(integration): migrate IntegrationTests to Swift Testing (Phase 6)#1097
grdsdev wants to merge 1 commit into
mainfrom
test/sdk-1253-integrationtests-swift-testing-migration

Conversation

@grdsdev

@grdsdev grdsdev commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Summary

Migrates all 10 files in Tests/IntegrationTests from XCTest to Swift Testing (@Suite/@Test), per the SDK-435 migration plan and the Phase 0 conventions decided in SDK-1247. This target has the heaviest setUp/tearDown usage in the repo (11 total) and orchestrates a real local Supabase instance rather than mocking, so it needed its own lifecycle patterns rather than reusing Phase 2-4's Mocker→Replay work (unrelated — no Mocker/Replay usage here at all).

Changes

  • XCTSkipUnless(INTEGRATION_TESTS) in every setUp becomes a @Suite(.enabled(if:)) trait, evaluated once per suite instead of once per test method.
  • setUp/tearDown become init()/deinit(). Files with only read-only shared state per test (the 4 Postgrest files, PostgrestIntegrationTests, AuthClientIntegrationTests, StorageClientIntegrationTests) convert to structs — no teardown needed.
  • StorageFileIntegrationTests and RealtimeIntegrationTests need real async teardown (delete a test bucket / disconnect realtime channels), so they stay final class with a deinit that fires cleanup in a best-effort detached Task, mirroring the original try?-swallowed tearDown semantics (documented inline — this is an accepted tradeoff for ephemeral local test resources, not correctness-critical).
  • RealtimeIntegrationTests additionally needs @Suite(.serialized) because it swaps the process-global _clock seam (Sources/Helpers/_Clock.swift) per test — mirrors the Phase 4 PostgrestBuilderTests precedent — plus Sendable conformance on the class since withMainSerialExecutor's closure parameter is @Sendable outside DEBUG/Concurrency-availability builds under Swift 6 strict checking.
  • AuthClientIntegrationTests' custom XCTAssertAuthChangeEvents helper (built on XCTestExpectation) is replaced with a LockIsolated + short polling loop, since Swift Testing has no direct expectation-fulfillment equivalent.
  • Moves IntegrationTests out of the blanket Swift 5 language-mode pin (Package.swift) into full Swift 6 mode, matching production targets' swiftSettings. No other Sendable/isolation diagnostics needed fixing beyond the RealtimeIntegrationTests case above.

Test plan

  • swift build --target IntegrationTests compiles clean under full Swift 6 mode.
  • swift test --filter IntegrationTests: all 8 INTEGRATION_TESTS-gated suites (Postgrest x4, PostgrestIntegrationTests, AuthClientIntegrationTests, StorageClientIntegrationTests, StorageFileIntegrationTests) correctly skip via the new .enabled(if:) trait — confirms that gate is equivalent to the old per-test XCTSkipUnless.
  • RealtimeIntegrationTests fails in this environment with CancellationError (no local Supabase instance reachable) — this is pre-existing: its XCTSkipUnless was already commented out in the original XCTest file (predates this PR), so it has always attempted a live connection unconditionally. Not a regression from this migration. Full live verification (./scripts/test-integration.sh against supabase start) needs a local Supabase instance and wasn't run in this environment.

Linear

Closes SDK-1253

Converts all 10 files in Tests/IntegrationTests from XCTest to Swift
Testing (@Suite/@test), per the SDK-435 migration plan and the Phase 0
conventions decided in SDK-1247.

- XCTestCase setUp's XCTSkipUnless(INTEGRATION_TESTS) becomes a
  @suite(.enabled(if:)) trait, evaluated once per suite instead of
  once per test.
- setUp/tearDown become init()/deinit() throughout. Files with only
  read-only shared state (Postgrest x4, PostgrestIntegrationTests,
  AuthClientIntegrationTests, StorageClientIntegrationTests) convert
  to structs. StorageFileIntegrationTests and RealtimeIntegrationTests
  need real async teardown (delete a bucket / disconnect channels), so
  they stay classes with a deinit that fires the cleanup in a
  best-effort detached Task, mirroring the old try?-swallowed
  tearDown semantics.
- RealtimeIntegrationTests additionally needs @suite(.serialized)
  because it swaps the process-global `_clock` seam per test (mirrors
  the Phase 4 PostgrestBuilderTests precedent), and Sendable
  conformance on the class since withMainSerialExecutor's closure
  parameter is @sendable outside DEBUG/Concurrency-availability
  builds.
- No Mocker/Replay involved — these tests hit a real local Supabase
  instance, so Phase 5's (AuthTests) still-in-progress Replay work is
  unrelated to this phase.
- Moves IntegrationTests out of the blanket Swift 5 language-mode pin
  into full Swift 6 mode, matching production targets' strict-
  concurrency settings. No Sendable/isolation diagnostics required
  fixes beyond RealtimeIntegrationTests above.

Linear: SDK-1253
@grdsdev grdsdev requested a review from a team as a code owner July 8, 2026 22:26
@coveralls

Copy link
Copy Markdown

Coverage Report for CI Build 28980049471

Coverage increased (+0.03%) to 83.252%

Details

  • Coverage increased (+0.03%) from the base build.
  • Patch coverage: No coverable lines changed in this PR.
  • No coverage regressions found.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 9470
Covered Lines: 7884
Line Coverage: 83.25%
Coverage Strength: 1133872.16 hits per line

💛 - Coveralls

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants