[GSoC 2026] Globally Scoped Traits For Swift Testing Design Questions

Hi Swift !

I’m GyeongMo Yoo (Demian) from South Korea, and I’m interested in the Globally Scoped Traits for Swift Testing project for GSoC 2026.

I recently completed Apple Developer Academy @ POSTECH, where I built several iOS apps with Swift and SwiftUI.

While working with XCTest and, more recently, Swift Testing’s macro and trait-based model, I became particularly interested in how common test behavior can be expressed and propagated cleanly. That interest led me to look more closely at this project idea.

I’ve forked the swift-testing repository and have been reading through Trait.swift, Runner.swift, Configuration.swift, and implementations such as TimeLimitTrait and ParallelizationTrait. I’ve also been reading ST-0007: Test Scoping Traits to better understand Swift Testing’s scoping model.

My current understanding is that traits already work at the test and suite levels, and suite traits can in some cases apply recursively to child tests. By contrast, the GSoC idea of “globally scoped traits” seems closer to applying traits through runtime configuration at the package or CI execution level, rather than through source-level declarations alone. Because of that, I assume the implementation likely belongs more in the runtime pipeline (Configuration / Runner) than in macro expansion itself. I also suspect global traits should follow the same lifecycle as existing traits including prepare(for:) and scope-provider-based execution rather than becoming a separate path.

Based on that understanding, I had a few questions.

  • When global traits and per-test traits both exist, should per-test traits override by default? For example, timeLimit seems naturally override-based, while tags might make more sense as a union depending on the trait kind.
  • Should globally scoped traits extend the existing configuration schema, or would a separate file / entry point make more sense?
  • Should “global” initially mean package-wide, or should per-target customization be considered from the start?
  • Should global traits participate in the same lifecycle as existing traits in both planning and execution phases?

This is my first serious attempt to engage with Swift open source, so I’d really appreciate any corrections or pointers on where I should look next.

Thank you @jerryjrchen , for sharing this project idea! It gave me a great reason to study Swift Testing more deeply.

Hi Demian, and welcome to the Swift forums!

As you've noted, there are examples of both behaviours. It might make sense to support both, depending on what would make the most sense to an end user of the feature.

Picking either for the proposal is fine, and I don't expect it to be a huge sticking point. If you do foresee issues with one approach, it would be worth calling that out in the proposal. :slight_smile:

Even if you decide to start with package-wide, I think it would be helpful to leave the option of per-target customisation open in the future.

Is this referring to stuff like Trait.prepare()? If so I'd say generally yes, global traits should behave similarly. Imagine something like a global ConditionTrait: it would need to run before all test cases to check for early cancellation.

2 Likes

Hi Jerry, thank you for the detailed responses ! This project is so much Fun for me haha :)

To confirm my design direction is →

  • timeLimit → override + hard cap
  • tags → union
  • serialized → override (local wins over global)

I'll extend the existing --configuration-path schema, starting package-wide with per-target open for later.

Your ConditionTrait example really pushed my thinking further. I've been digging into the relevant code paths and found an interesting edge case → I'll address it in the proposal rather than here.

While exploring the codebase I came across issue #686, and the DB serialization problem resonated with me personally.
Writing UI tests, I hit the exact same root cause shared state plus parallel execution equals unpredictable results. Network mock servers, UserDefaults, singletons : all the same pattern underneath. I'm still actively building projects to find more edge cases like these.

One question I'd love your thoughts on: if a developer wants to intentionally opt out of a global trait for a specific test, should an explicit opt-out mechanism be a first-class part of the design?
Or is the existing override model sufficient?

I've also found an interesting angle on how the tooling layer connects to swift-testing internals I'll save that for the proposal.

Looking forward to sharing the full design!

1 Like

That kind of depends on what the mechanism is. But, a big advantage of relying on the existing override model is that it's one less thing for a user to learn about. It's always worth keeping in mind how new features like this impact those who aren't necessarily keeping up with every single latest update.

1 Like

That makes a lot of sense!
From a user's perspective, writing @Test(.timeLimit(.minutes(10))) is already an opt-out in itself no new concept needed.

I'll go with the override model and make the precedence rules clear in the proposal so it stays intuitive.

Thank you so much for taking the time to share your thoughts despite your busy schedule. I really hope we get the chance to work together!

1 Like