BLOG ABOUT

Now you can test Xcode apps and Swift packages in Zed

2025-10-17

This is a followup to Build, run and debug iOS and Mac apps in Zed instead of Xcode, so you'll want to start there unless you're only working on Swift packages.

Here's how to:

Used in the real world

This isn't just an article about what you could do in theory – I built my new app, DelayDrop, mainly in Zed. It's a pleasure to work in a genuinely good code editor, and switching into Xcode for things like previews really isn't an imposition.

DelayDrop is an iOS and Mac app for sending anything to your other Apple devices – even if they're locked, off or elsewhere – in two taps. It beats AirDrop because your other device can be anywhere in the world; and even if it is nearby, you're still winning because you don't have to get up and unlock it.

And if that sounds like a plug for DelayDrop, that's because it is!

Update Zed's Swift plugin

For now, you need to replace a couple of files manually. Don't worry, you don't need to recompile the plugin or anything. (I've created a PR for these changes. Hopefully these will be incorporated into a new plugin version before too long!)

Grab runnables.scm and tasks.scm from my fork (they're text files, so you can examine the contents first if you like), and replace the existing files in $HOME/Library/Application Support/Zed/extensions/installed/swift/languages/swift You don't even need to restart Zed.

Now you should see runnable triangles next to your tests. These will work for Swift packages (but not Xcode projects yet), so if you have a package with tests, open it and try it out.

Tip: If you're using Swift Testing, annotate your test structs/classes with @Suite, otherwise Zed won't see them as runnable.

If you're only interested in Swift packages, that's it – you can stop reading. The rest of the article is about Xcode projects.

Update xcede

If you've been using xcede for a while, make sure you've got the latest version.

If you're upgrading, note there are some breaking changes. build.sh will tell you about those when you run it.

Define tasks

The following assumes you're set up to build and run your app in Zed as described in the first article, including having a .xcrc file specifying your scheme etc.

Run zed: Open tasks and add the following:

{
    "label": "$ZED_CUSTOM_SWIFT_TEST_CLASS test",
    "command": "xcede",
    "args": ["test", "$ZED_CUSTOM_SWIFT_TEST_CLASS"],
    "tags": ["swift-xctest-class", "swift-testing-suite"]
},
{
    "label": "$ZED_CUSTOM_SWIFT_TEST_CLASS.$ZED_CUSTOM_SWIFT_TEST_FUNC test",
    "command": "xcede",
    "args": [
        "test",
        "$ZED_CUSTOM_SWIFT_TEST_CLASS",
        "$ZED_CUSTOM_SWIFT_TEST_FUNC"
    ],
    "tags": ["swift-xctest-func", "swift-testing-member-func"]
},
{
    "label": "$ZED_CUSTOM_SWIFT_TEST_FUNC test",
    "command": "xcede",
    "args": ["test", "-", "$ZED_CUSTOM_SWIFT_TEST_FUNC"],
    "tags": ["swift-testing-bare-func"]
}

How this works: The runnables you see in Zed are created by the Swift plugin. Each one has an associated tag, and also sets variables ($ZED_CUSTOM_*) for things we need to know – test class and test function. The plugin also defined tasks to execute these runnables using swift test; here, we're replacing the plugin's tasks with versions that use xcede instead.

Note that you haven't lost the ability to run Swift package tests – if you've opened a package rather than an Xcode project, xcede will see that and run the appropriate swift test command.

A little more setup

That's it – now try out one of those triangles.

As ever, the output can be ugly, and xcbeautify or similar will make it nicer. See the previous article for details.

Run all tests

Running xcede test without any arguments will run all the tests in your target. It's easy enough to create a task for that.

What about packages within Xcode projects?

If you've moved your app's code into packages (I do this), in Xcode you'd include the packages' tests in a scheme or schemes. Whether it's your main app scheme or a different one is up to you. Just make sure you've set testtarget to the package's test target, and set testscheme if you need to.

If you want to run your package tests using swift not xcodebuild, just open the package directory as its own Zed project.

The end

If you have any feedback, join the discussion on Zed's github, or add an issue to the xcede repo.

@lxmn@mastodon.social.