@@ -30,12 +30,40 @@ public struct AddTarget {
30
30
" cxxLanguageStandard "
31
31
]
32
32
33
+ /// The kind of test harness to use. This isn't part of the manifest
34
+ /// itself, but is used to guide the generation process.
35
+ public enum TestHarness : String , Codable {
36
+ /// Don't use any library
37
+ case none
38
+
39
+ /// Create a test using the XCTest library.
40
+ case xctest
41
+
42
+ /// Create a test using the swift-testing package.
43
+ case swiftTesting = " swift-testing "
44
+
45
+ /// The default testing library to use.
46
+ public static var `default` : TestHarness = . xctest
47
+ }
48
+
49
+ /// Additional configuration information to guide the package editing
50
+ /// process.
51
+ public struct Configuration {
52
+ /// The test harness to use.
53
+ public var testHarness : TestHarness
54
+
55
+ public init ( testHarness: TestHarness = . default) {
56
+ self . testHarness = testHarness
57
+ }
58
+ }
59
+
33
60
/// Add the given target to the manifest, producing a set of edit results
34
61
/// that updates the manifest and adds some source files to stub out the
35
62
/// new target.
36
63
public static func addTarget(
37
64
_ target: TargetDescription ,
38
65
to manifest: SourceFileSyntax ,
66
+ configuration: Configuration = . init( ) ,
39
67
installedSwiftPMConfiguration: InstalledSwiftPMConfiguration = . default
40
68
) throws -> PackageEditResult {
41
69
// Make sure we have a suitable tools version in the manifest.
@@ -49,10 +77,20 @@ public struct AddTarget {
49
77
// content when needed.
50
78
var target = target
51
79
52
- // Macro targets need to depend on a couple of libraries from
53
- // SwiftSyntax.
54
- if target. type == . macro {
80
+ // Add dependencies needed for various targets.
81
+ switch target. type {
82
+ case . macro:
83
+ // Macro targets need to depend on a couple of libraries from
84
+ // SwiftSyntax.
55
85
target. dependencies. append ( contentsOf: macroTargetDependencies)
86
+
87
+ case . test where configuration. testHarness == . swiftTesting:
88
+ // Testing targets using swift-testing need to depend on
89
+ // SwiftTesting from the swift-testing package.
90
+ target. dependencies. append ( contentsOf: swiftTestingTestTargetDependencies)
91
+
92
+ default :
93
+ break ;
56
94
}
57
95
58
96
var newPackageCall = try packageCall. appendingToArrayArgument (
@@ -84,6 +122,7 @@ public struct AddTarget {
84
122
addPrimarySourceFile (
85
123
outerPath: outerPath,
86
124
target: target,
125
+ configuration: configuration,
87
126
to: & auxiliaryFiles
88
127
)
89
128
@@ -124,6 +163,17 @@ public struct AddTarget {
124
163
}
125
164
}
126
165
166
+ case . test where configuration. testHarness == . swiftTesting:
167
+ if !manifest. description. contains ( " swift-testing " ) {
168
+ newPackageCall = try AddPackageDependency
169
+ . addPackageDependencyLocal (
170
+ . swiftTesting(
171
+ configuration: installedSwiftPMConfiguration
172
+ ) ,
173
+ to: newPackageCall
174
+ )
175
+ }
176
+
127
177
default : break ;
128
178
}
129
179
@@ -140,6 +190,7 @@ public struct AddTarget {
140
190
fileprivate static func addPrimarySourceFile(
141
191
outerPath: RelativePath ,
142
192
target: TargetDescription ,
193
+ configuration: Configuration ,
143
194
to auxiliaryFiles: inout AuxiliaryFiles
144
195
) {
145
196
let sourceFilePath = outerPath. appending (
@@ -153,7 +204,17 @@ public struct AddTarget {
153
204
154
205
// Add appropriate test module dependencies.
155
206
if target. type == . test {
156
- importModuleNames. append ( " XCTest " )
207
+ switch configuration. testHarness {
208
+ case . none:
209
+ break
210
+
211
+ case . xctest:
212
+ importModuleNames. append ( " XCTest " )
213
+
214
+ case . swiftTesting:
215
+ // Import is handled by the added dependency.
216
+ break
217
+ }
157
218
}
158
219
159
220
let importDecls = importModuleNames. lazy. sorted ( ) . map { name in
@@ -184,14 +245,35 @@ public struct AddTarget {
184
245
"""
185
246
186
247
case . test:
187
- """
188
- \( imports)
189
- class \( raw: target. name) : XCTestCase {
190
- func test \( raw: target. name) () {
191
- XCTAssertEqual(42, 17 + 25)
248
+ switch configuration. testHarness {
249
+ case . none:
250
+ """
251
+ \( imports)
252
+ // Test code here
253
+ """
254
+
255
+ case . xctest:
256
+ """
257
+ \( imports)
258
+ class \( raw: target. name) : XCTestCase {
259
+ func test \( raw: target. name) () {
260
+ XCTAssertEqual(42, 17 + 25)
261
+ }
262
+ }
263
+ """
264
+
265
+ case . swiftTesting:
266
+ """
267
+ \( imports)
268
+ @Suite
269
+ struct \( raw: target. name) Tests {
270
+ @Test( " \( raw: target. name) tests " )
271
+ func example() {
272
+ #expect(42 == 17 + 25)
273
+ }
192
274
}
275
+ """
193
276
}
194
- """
195
277
196
278
case . regular:
197
279
"""
@@ -298,3 +380,35 @@ fileprivate extension PackageDependency {
298
380
)
299
381
}
300
382
}
383
+
384
+ /// The set of dependencies we need to introduce to a newly-created macro
385
+ /// target.
386
+ fileprivate let swiftTestingTestTargetDependencies : [ TargetDescription . Dependency ] = [
387
+ . product( name: " Testing " , package : " swift-testing " ) ,
388
+ ]
389
+
390
+
391
+ /// The package dependency for swift-testing, for use in test files.
392
+ fileprivate extension PackageDependency {
393
+ /// Source control URL for the swift-syntax package.
394
+ static var swiftTestingURL : SourceControlURL {
395
+ " https://github.com/apple/swift-testing.git "
396
+ }
397
+
398
+ /// Package dependency on the swift-testing package.
399
+ static func swiftTesting(
400
+ configuration: InstalledSwiftPMConfiguration
401
+ ) -> PackageDependency {
402
+ let swiftTestingVersionDefault =
403
+ configuration. swiftTestingVersionForTestTemplate
404
+ let swiftTestingVersion = Version ( swiftTestingVersionDefault. description) !
405
+
406
+ return . sourceControl(
407
+ identity: PackageIdentity ( url: swiftTestingURL) ,
408
+ nameForTargetDependencyResolutionOnly: nil ,
409
+ location: . remote( swiftTestingURL) ,
410
+ requirement: . range( . upToNextMajor( from: swiftTestingVersion) ) ,
411
+ productFilter: . everything
412
+ )
413
+ }
414
+ }
0 commit comments