If you have used SPM to create the command line application before Swift 5.9.0
, the project structure used to be as follows:
Package.swift
README.md
.gitignore
Sources/
Sources/SamplePackage/main.swift
Tests/
Tests/LinuxMain.swift
Tests/SamplePackageTests/
Tests/SamplePackageTests/SamplePackageTests.swift
Tests/SamplePackageTests/XCTestManifests.swift
The test target and the basic scaffolding for it were available on the package creation.
With the recent changes to simplify the templating of the package --type
, test target is only added to the package --type library
and not to --type tool
and --type executable
.
tool
is the newly added type that creates the package of type executable
with the dependency for SwiftArgumentParser already added to the package.
The new file structure looks as follows:
// --type executable
./executable
./executable/.gitignore
./executable/Package.swift
./executable/Sources
./executable/Sources/executable.swift
// --type tool
./tool
./tool/.gitignore
./tool/Package.swift
./tool/Sources
./tool/Sources/tool.swift
// --type empty
./empty
./empty/Package.swift
// --type library
./library
./library/Tests
./library/Tests/libraryTests
./library/Tests/libraryTests/libraryTests.swift
./library/.gitignore
./library/Package.swift
./library/Sources
./library/Sources/library
./library/Sources/library/library.swift
You can find more details about the change in this PR.
Now, if you want to add the test target to the package of --type tool
or --type executable
with newer tool-chain of Swift 5.9.0
, you can follow these steps:
Create the package:
$ mkdir SamplePackage $ cd SamplePackage $ swift package init --type executable
Creating executable package: SamplePackage Creating Package.swift Creating .gitignore Creating Sources/ Creating Sources/main.swift
Open
Package.swift
. It should look like this:// swift-tools-version: 5.9 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription let package = Package( name: "SamplePackage", targets: [ // Targets are the basic building blocks of a package, defining a module or a test suite. // Targets can depend on other targets in this package and products from dependencies. .executableTarget( name: "SamplePackage"), ] )
Update
Package.swift
as below:// swift-tools-version: 5.9 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription let package = Package( name: "SamplePackage", targets: [ // Targets are the basic building blocks of a package, defining a module or a test suite. // Targets can depend on other targets in this package and products from dependencies. .executableTarget( name: "SamplePackage", path: "Sources" ), .testTarget( name: "SamplePackageTests", dependencies: ["SamplePackage"], path: "Tests" ) ] )
Add
.testTarget
to the array oftargets
and add the main targetSamplePackage
to its dependencies list. Also, add the path to theTests
folder.Add a sample test file with
@testable import <main module>
to validate that the tests can resolve the main module.Example test file:
import XCTest @testable import SamplePackage class ExampleTests: XCTestCase { func testExample() { } }
The updated file structure should look as below:
SamplePackage SamplePackage/.gitignore SamplePackage/Package.swift SamplePackage/Sources SamplePackage/Sources/main.swift SamplePackage/Tests/ExampleTests.swift
Validate if tests are running successfully via Xcode
โ + U
and via the command lineswift test
Let me know if you found this helpful. Feel free to tweet me on Twitter if you have any additional tips or feedback.
Thanks.