Running Swift unit tests from the CLI
August 16, 2018
Estimated reading time 4 minutes
Lately I’ve been playing around with serverside Swift and Swift via the CLI and unit testing. One of the problems I’ve run into is getting the SPM (Swift Package Manager) to run tests via the CLI.
Starting a new Swift project.
Via the CLI you can create a new project via the SPM with swift package init --type executable
.
This creates a certain folder structure with a Sources
and Tests
folder. Open up Package.swift
from your root project folder and make sure your Package.swift
does contain the tool directive in comments (no idea what the official name of this is):
// swift-tools-version:4.0
.
If you omit this directive it compiles via swift build
. However when you add this directive, SPM returns different error messages. When I then run either swift build
or swift test
(like it says in your guide) the SPM(Swift Package Manager) returns with a warning: no targets to build in package
to me. So we need to add this to the Package file.
Adding a testTarget.
Piecing everything together and adding the testTarget
to the file, the complete Package.swift
should look simething like this:
When running the tests now SPM gives me an error: "xcrun: error: unable to find utility "xctest", not a developer tool or in PATH"
. Running xctest
can be done via xcrun xctest
in the Terminal. This give a bunch of output and shows a path in the Arguments
node.
Fixing it.
So following the the hint from the error I’ve added the "/Applications/Xcode.app/Contents/Developer/usr/bin/"
to my path via export PATH="$PATH:/Applications/Xcode.app/Contents/Developer/usr/bin/"
. To confirm that it works check it with an echo $PATH
.
Now when calling swift test
I get to see the correct output, tests pass and it all works!
If that still does not work; After searching github and Stackoverflow I’ve found this which talks about Why isn’t swift build able to link XCTest?.
They say this:
The XCTest framework on Darwin isn’t a proper SDK framework, and is located at a different location within the Platform directory structure than frameworks like Foundation.
So we need to add the search paths to swift build
like so:
When doing the same but for swift test
I get to see the correct output, tests pass and it all works!
What I’ve also done (and later removed because swift test
worked regardless of adding the search paths) is to create an alias which includes the search paths so you only have to type swift test
and be done with it.
Hope this helps anyone who has run into the same problems. Or maybe add this to your docs if people have the same problem.
Make it pretty.
The output that swift test
generates is fairly hard to read, but we can do something about that. xcpretty to the rescue! However when just piping the output to xcpretty
does absolutely nothing. Weird… So searching through the Swift Forums I’ve found this:
This case with xcpretty is actually because swiftpm outputs test output to stderr, not stdout.
Ok let’s try again; Now we need to run swift test 2>&1 | xcpretty
. Now we have a much more readable output. Me likes 🤓.
Conclusion
So you can run swift test
from the commmandline we only need to make sure we are linking to the correct framework. And we can pipe xcpretty
to stderr
to make it’s output more readable.