Skip to content

Feature request: @ChildSuite for breaking down Suites in to namespaced subdomains #296

Closed as not planned
@adammcarter

Description

@adammcarter

Description

I'm just looking at integrating Swift Testing in to my new project to avoid the weight of XCTest so apologies if this is covered in the documentation but I can't see it.

I'm breaking down a test suite in to subdomains - a common pattern of a Suite relating to a type and subdomains to break down the components of that type to avoid long winded test names with the pattern SUT.functionName.given.when.then() and instead breaking this down in to child suites namespaced for the SUT and the function name.

For example, if my Suite is for a notifications service, I want to break this down to subdomains per function/variable to neatly break up my tests:

struct NotiicationsService {
    var isNotificationsAvailable: Bool { /*logic*/ == true }

    func queueNotifications() { /*queue notifications if needed*/ }
}

Then in my tests I want to break this up per var/func above in to it's own child suite...

@Suite
struct NotificationsServiceTests {
    var sut: NotificationsService
    
    init() {
        self.sut = .production()
    }
    
    @Suite
    struct IsNotificationsAvailable {
        var sut: NotificationsService
        
        init() {
            self.sut = .production()
        }
    }
    
    @Suite
    struct QueueNotifications {
        var sut: NotificationsService
        
        init() {
            self.sut = .production()
        }
    }
}

extension NotificationsServiceTests.IsNotificationsAvailable {
    @Test
    func returnsTrue_whenAuthorisationStatusIsAuthorized()
        #expect()
    }
    
    @Test
    func returnsFalse_whenAuthorisationStatusIsDenied() {
        #expect()
    }
}

extension NotificationsServiceTests.QueueNotifications {
    @Test
    func addsNotificationRequests_whenNewContentIsAvailable() {
        #expect()
    }
    
    @Test
    func addsNotificationRequests_whenUpdatedContentIsAvailable() {
        #expect()
    }
}

This works in my code but the obvious code smell to anyone looking at this is the need to pass down the sut to each "child" suite.

Is there a better way to do this using the existing Swift Testing framework or is this a potential for a new feature - @ChildSuite?

Looking at the current documentation around organising tests:
https://swiftpackageindex.com/apple/swift-testing/main/documentation/testing/organizingtests

... It's implied that child Suites are encouraged:

In addition to containing test functions and any other members that a Swift type might contain, test suite types can also contain additional test suites nested within them. To add a nested test suite type, simply declare an additional type within the scope of the outer test suite type.

But unless I'm missing something (likely) I can't see any more information in these docs around nesting the Suites - especially for my use case of namespacing the different functionality to group tests on a per function basis.

Proposed solution

It would be nice if we could create a macro for @ChildSuite so it inherits the properties and initialiser/deinit by default to clean this up.

This would look like the below:

@Suite
struct NotificationsServiceTests {
    var sut: NotificationsService
    
    init() {
        self.sut = .production()
    }
    
    @ChildSuite
    struct IsNotificationsAvailable {}
    
    @ChildSuite
    struct QueueNotifications {}
}

extension NotificationsServiceTests.IsNotificationsAvailable {
    @Test
    func returnsTrue_whenAuthorisationStatusIsAuthorized()
        #expect()
    }
    
    @Test
    func returnsFalse_whenAuthorisationStatusIsDenied() {
        #expect()
    }
}

extension NotificationsServiceTests.QueueNotifications {
    @Test
    func addsNotificationRequests_whenNewContentIsAvailable() {
        #expect()
    }
    
    @Test
    func addsNotificationRequests_whenUpdatedContentIsAvailable() {
        #expect()
    }
}

Expected behavior

No response

Actual behavior

No response

Steps to reproduce

No response

swift-testing version/commit hash

0.6.0

Swift & OS version (output of swift --version && uname -a)

swift-driver version: 1.90.11.1 Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4)
Target: arm64-apple-macosx14.0
Darwin AT-ALK6L5VQ 23.3.0 Darwin Kernel Version 23.3.0: Wed Dec 20 21:30:44 PST 2023; root:xnu-10002.81.5~7/RELEASE_ARM64_T6000 arm64

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestwontfix❌ This will not be worked on

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions