Skip to content

Improve reusable TestCase and Swift Testing integration - #2

Open
kudit wants to merge 29 commits into
mainfrom
agent/improve-test-infrastructure
Open

Improve reusable TestCase and Swift Testing integration#2
kudit wants to merge 29 commits into
mainfrom
agent/improve-test-infrastructure

Conversation

@kudit

@kudit kudit commented Jul 26, 2026

Copy link
Copy Markdown
Owner

What changed

This draft PR keeps the work in two reviewable commits:

  1. Consolidate TestCase execution and preserve diagnostics

    • Routes execute() and the live-UI run() path through one lifecycle implementation.
    • Preserves async setup/test/teardown behavior without attempting to await inside defer.
    • Adds .parallel and .serialized execution modes for tests that mutate process-global state.
    • Introduces TestFailure, retaining file, function, line, column, and detailed expectation values.
    • Logs expectation failures at .ERROR before throwing so command-line runs retain useful diagnostics.
  2. Add reusable Swift Testing module adapter

    • Adds a Compatibility Testing Library product in the same package and .swiftpm project.
    • Adds ModuleTestEntry, one Swift Testing argument per Compatibility TestCase.
    • Uses CustomTestStringConvertible for readable Xcode names such as Device › Battery Tests › Reports current battery state.
    • Uses CustomTestArgumentEncodable for stable argument identity and selective reruns.
    • Lets consuming modules reduce their adapter to ModuleTestEntry.entries(including:) and entry.execute().

Design decisions

  • TestCase remains @MainActor because it owns observable UI progress and a mutable test closure. A sendable execution snapshot keeps detached execution safe and prevents the UI model from crossing actors.
  • main {} remains distinct from await MainActor.run {}: the former schedules fire-and-forget work, while the latter awaits completion and can return a value.
  • The broader main/background/sleep/WASM overload consolidation belongs to follow-up PR Add awaited main and WebAssembly async threading fallbacks #3.

Open draft review items

Before this PR is marked ready for review:

  • make .serialized execution truly exclusive against both serialized and parallel reusable tests;
  • mark the debug-configuration test serialized;
  • restore debug configuration with test-local synchronous defer rather than automatically resetting all Compatibility settings around every test;
  • compile and run the package tests in Xcode and SwiftPM across the supported platform matrix.

Validation so far

  • New Swift files were syntax-parsed with Swift 6.2.1.
  • Full package compilation and platform validation remain required before merge.

Dependent follow-up

After this API is finalized and released, create a Device pull request that imports CompatibilityTesting and replaces its duplicated Entry/module lookup adapter with ModuleTestEntry.

@kudit
kudit force-pushed the agent/improve-test-infrastructure branch from 20d8a11 to c6c86f1 Compare July 26, 2026 02:08
kudit added 27 commits July 27, 2026 10:32
Fix test infrastructure availability
Simplified code duplication and context description.
Refactor lastPathComponent to support Windows-style paths and remove Foundation dependency.
Added guidelines for collaborative coding workflow to improve interaction with maintainers.
Added testing requirements and TODOs for release preparation.
fix @available where macOS 12 was paired with watchOS 8
@kudit
kudit marked this pull request as ready for review August 4, 2026 17:12

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ae7c4eef2e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Sources/Core/Debug.swift
Comment on lines +358 to 362
#if hasFeature(Embedded) || !canImport(Foundation)
let isMainThread = true
#endif
#else
let isMainThread = Thread.isMainThread // capture before we switch to main thread for printing
let message = String(describing: message) // convert to sendable item to avoid any thread issues.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Stringify debug values on non-Foundation runtimes

In a full-runtime configuration where Foundation is unavailable but Embedded Swift is not enabled, DebugMessage is Any, yet this branch only initializes isMainThread and skips the String(describing:) conversion. The call on line 364 then passes Any to the overload whose message parameter is String, so supported non-Foundation WASM or similar builds fail to compile; separate the Embedded and non-Foundation branches and stringify values in the latter.

Useful? React with 👍 / 👎.

Comment thread Sources/Core/Test.swift
test: @escaping TestClosure,
tearDown: TestClosure? = nil
tearDown: TestClosure? = nil,
source: SourceContext = SourceContext()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Capture TestCase source at its caller

When callers omit source, Swift evaluates the nested SourceContext defaults where SourceContext() appears in this initializer rather than where the TestCase is created. A TestCase("foo") { ... } created in another file therefore records Test.swift:338 (and direct calls to this initializer record line 324), so normalization of any thrown non-TestFailure points diagnostics to the framework initializer instead of the test declaration. Capture #file, #function, #line, and #column as initializer defaults and construct the context in the body.

Useful? React with 👍 / 👎.

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.

1 participant