Skip to content

Support generic test function #202

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Kyle-Ye opened this issue Feb 4, 2024 · 1 comment
Closed

Support generic test function #202

Kyle-Ye opened this issue Feb 4, 2024 · 1 comment
Labels
enhancement New feature or request wontfix ❌ This will not be worked on

Comments

@Kyle-Ye
Copy link
Contributor

Kyle-Ye commented Feb 4, 2024

Description

We have some generic interface in the codebase. And I'd request generic function support for @Test macro.

The following is a simplified version of my use case.

protocol Key {
	associated Value
	static var defaultValue: Value
	static func reduce(value: inout Value, nextValue: () -> Value)
}
struct AddIntKey: Key {
    static var defaultValue: Int { 0 }
    
    static func reduce(value: inout Int, nextValue: () -> Int) {
        value += nextValue()
    }
}
struct MultipleIntKey: Key {
    static var defaultValue: Int { 0 }
    
    static func reduce(value: inout Int, nextValue: () -> Int) {
        value *= nextValue()
    }
}

Expected behavior

@Test(arguments: [ // ✅
    (AddIntKey.self, [1, 2], 3)
	(MultipleIntKey.self, [1, 2], 2)
])
func reduce<Key: PreferenceKey>(
    type: Key.Type, values: [Key.Value], expectedValues: Key.Value
) {
	...
}

Actual behavior

@Test(arguments: [ // ❌: The @Test attribute cannot be applied to a generic function.
    (AddIntKey.self, [1, 2], 3)
	(MultipleIntKey.self, [1, 2], 2)
])
func reduce<Key: PreferenceKey>(
    type: Key.Type, values: [Key.Value], expectedValues: Key.Value
) {
	...
}

Steps to reproduce

No response

swift-testing version/commit hash

No response

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

No response

@Kyle-Ye Kyle-Ye added the enhancement New feature or request label Feb 4, 2024
@grynspan
Copy link
Contributor

grynspan commented Feb 5, 2024

The expression:

[
  (AddIntKey.self, [1, 2], 3)
  (MultipleIntKey.self, [1, 2], 2)
]

Would have the type [Any] rather than something like [some PreferenceKey] as you presumably intended. The types of a test's parameters must be explicitly specified in the test function's declaration because during macro expansion, we can only rely on the syntax (the specific characters the developer typed and saved into the source file) and do not have semantic type information for the test function's arguments.

Even if we assume for a moment that the syntax above were valid anyway, swift-testing discovers tests at runtime. A generic function may have an unbounded number of specializations at runtime, and the Swift runtime would require swift-testing to know how to specialize the test function before it could be called.

If you really wanted to do something like this, consider an abstraction over a common implementation function instead of using parameterization:

func commonReduce<Key: PreferenceKey>(
  type: Key.Type,
  values: [Key.Value],
  expectedValues: Key.Value
) {
  ...
}

@Test func reduceByAdding(values: [Int], expectedValues: Int) {
  commonReduce(AddIntKey.self, [1, 2], 3)
}

@Test func reduceByMultiplying(values: [Int], expectedValues: Int) {
  commonReduce(MultiplyIntKey.self, [1, 2], 2)
}

@grynspan grynspan closed this as not planned Won't fix, can't repro, duplicate, stale Feb 5, 2024
@grynspan grynspan added the wontfix ❌ This will not be worked on label Feb 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request wontfix ❌ This will not be worked on
Projects
None yet
Development

No branches or pull requests

2 participants