Adding test target to Swift Package (--type executable)

👋 Hi, I'm Javal Nanda, a Mobile Application Developer based in India. I've been in the world of mobile app development since 2010, and this blog is my space to share experiences and thoughts.
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 executableCreating executable package: SamplePackage Creating Package.swift Creating .gitignore Creating Sources/ Creating Sources/main.swiftOpen
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.swiftas 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
.testTargetto the array oftargetsand add the main targetSamplePackageto its dependencies list. Also, add the path to theTestsfolder.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.swiftValidate if tests are running successfully via Xcode
⌘ + Uand 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.



