Skip to content

Allow inheriting test functions from superclasses used as test suites#1633

Open
grynspan wants to merge 6 commits intomainfrom
jgrynspan/inherited-tests
Open

Allow inheriting test functions from superclasses used as test suites#1633
grynspan wants to merge 6 commits intomainfrom
jgrynspan/inherited-tests

Conversation

@grynspan
Copy link
Contributor

This PR adds experimental functionality that allows you to write a test function in a test suite of class type, and then inherit that test function in subclasses of the test suite automatically. For example:

class AnimalTests {
  func makeNoise() -> Noise? {
    return nil // nothing by default
  }

  @Test open func `Animal makes noise`() {
    #expect(self.makeNoise() != nil)
  }
}

class DogTests: AnimalTests {
  override func makeNoise() -> Noise? {
    return .bark
  }
}

class CatTests: AnimalTests {
  override func makeNoise() -> Noise? {
    return .meow
  }
}

We leverage the open keyword for this purpose for a few reasons:

  1. It has no semantic meaning in test suites today, so it's unlikely to be in use already.
  2. It implies that there will be subclasses of the class in which it is found.
  3. The compiler enforces that it can only be applied to member functions of classes, and can do so with type system knowledge rather than just syntax.

We could spell it differently, e.g. with another attribute macro like @inherited, but we wouldn't be able to statically determine when it is incorrectly applied to something that isn't a member function of a class. So for the purposes of the experimental feature, open it is!

This makes the override keyword ambiguous, so I've blocked it when used with @Test, but there is probably a way to resolve that so we should consider that constraint to be temporary.

To try this feature out, set the Swift build condition SWIFT_TESTING_EXPERIMENTAL_TEST_INHERITANCE_ENABLED in your test target.

Checklist:

  • Code and documentation should follow the style of the Style Guide.
  • If public symbols are renamed or modified, DocC references should be updated.

This PR adds experimental functionality that allows you to write a test function
in a test suite of class type, and then inherit that test function in subclasses
of the test suite automatically. For example:

```swift
class AnimalTests {
  func makeNoise() -> Noise? {
    return nil // nothing by default
  }

  @test open func `Animal makes noise`() {
    #expect(self.makeNoise() != nil)
  }
}

class DogTests: AnimalTests {
  override func makeNoise() -> Noise? {
    return .bark
  }
}

class CatTests: AnimalTests {
  override func makeNoise() -> Noise? {
    return .meow
  }
}
```

We leverage the `open` keyword for this purpose for a few reasons:

1. It has no semantic meaning in test suites today, so it's unlikely to be in
   use already.
2. It implies that there will be subclasses of the class in which it is found.
3. The compiler enforces that it can only be applied to member functions of
   classes, and can do so with type system knowledge rather than just syntax.

We could spell it differently, e.g. with another attribute macro like
`@inherited`, but we wouldn't be able to statically determine when it is
incorrectly applied to something that isn't a member function of a class. So for
the purposes of the experimental feature, `open` it is!

This makes the `override` keyword ambiguous, so I've blocked it when used with
`@Test`, but there is probably a way to resolve that so we should consider that
constraint to be temporary.
@grynspan grynspan added this to the Swift 6.4.0 (main) milestone Mar 18, 2026
@grynspan grynspan self-assigned this Mar 18, 2026
@grynspan grynspan added the enhancement New feature or request label Mar 18, 2026
@grynspan grynspan added the macros 🔭 Related to Swift macros such as @Test or #expect label Mar 18, 2026
@grynspan grynspan added the discovery 🔎 test content discovery label Mar 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

discovery 🔎 test content discovery enhancement New feature or request macros 🔭 Related to Swift macros such as @Test or #expect

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant