Hi @smontgomery,
Thanks for the quick and detailed feedback — very helpful!
As written, this code doesn't compile because
MyTraitdoesn't conform toSuiteTrait. Only trait types which conform toSuiteTraitmay be applied to suites via the@Suite(...)attribute. I'll assume in your "real" code you did have this conformance, though.
Yes, you're absolutely right — I forgot to include the SuiteTrait conformance in the example, but I do have it in the actual code.
I would generally agree with this. Although note that in your example,
MyTraitis a struct, and value semantics will generally prevent you from sharing data in the way you might be thinking.
Understood. But as you mentioned, tests inside the suite inherit a copy of the MyTrait instance from the suite. So if we were to include a mutable property in MyTrait (which I didn’t show in the example), it could lead to data races or unexpected shared state — especially in concurrent scenarios.
I'm not certain what kind of fresh data you mean. Perhaps it would help to explain what your overall goal is.
Sorry for not being clear — by "fresh data", I meant that instead of storing test dependencies as properties inside MyTrait, I can pass in closures that generate new instances per test.
For example:
struct MyTrait: TestTrait, SuiteTrait, TestScoping {
let makeMockAPI: @Sendable () -> MockAPI
func provideScope(...) async throws {
let api = makeMockAPI() // ← fresh instance for each test
...
}
var isRecursive: Bool = true
}
This approach ensures isolation and avoids shared state, while still allowing common setup at the suite level.
My overall goal is to simplify test setup by providing common mock dependencies (e.g., mock services, configurations) at the suite or sub-suite level using a shared trait. At the same time, I’d like to allow individual tests to override those dependencies when needed by attaching their own customized version of MyTrait. This mirrors the pattern we’ve used in Quick/Nimble with beforeSuite, beforeEach, and so on, and we’re now looking to migrate those test cases to Swift Testing.
If there are any recommended best practices or alternative approaches for handling this pattern — especially around trait composition, overriding, or scoped setup — I’d really appreciate any guidance.
Thanks again for the clarification — this really helped solidify my understanding of how traits are constructed and propagated!