Every time I work with iOS developers as they create a new test file, they do the same thing. They select the built-in template and get junk they should delete (but often don’t). And their initial test code doesn’t compile because they need to add an import statement.
Stay in the flow, folks. Use my template instead. (This one’s for XCTest — I also have a template for Swift Testing.)
Say you have a project named SampleProject. And you want to create a new unit test suite. So you Command-N to make a new file, and select “XCTest Unit Test”.

If we give it the name AppleTests, here’s what Apple provides:
//
// AppleTests.swift
// SampleProjectTests
//
// Created by Jon Reid on 6/17/23.
//
import XCTest
final class AppleTests: XCTestCase {
override func setUpWithError() throws {
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDownWithError() throws {
// Put teardown code here. This method is called after the invocation of each test method in the class.
}
func testExample() throws {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
// Any test you write for XCTest can be annotated as throws and async.
// Mark your test throws to produce an unexpected failure when your test encounters an uncaught error.
// Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards.
}
func testPerformanceExample() throws {
// This is an example of a performance test case.
self.measure {
// Put the code you want to measure the time of here.
}
}
}It’s instructive… the first time. After that, it’s only noisy. So I use a customized file template for new unit test suites. Command-N and select “XCTest Swift (Jon Reid)”.

It suggests a file name ending with Tests. If we move the cursor to the beginning and set the name QualityCodingTests, here’s what I provide:
@testable import SampleProject
import XCTest
@MainActor
final class QualityCodingTests: XCTestCase, Sendable {
func test_zero() throws {
XCTFail("Tests not yet implemented in QualityCodingTests")
}
}Isn’t that better? You can download it here:
Curious about the problems I have with Apple’s template and the decisions I made for my custom template? Read on…
What's In Apple’s Template?
Let’s look more closely at what each file template provides. We’ll start with Apple’s “Unit Test Case Class” template.
Prompting for Unnecessary Inputs
If you select the template, Xcode displays a large dialog:

It feels like this large, clunky dialog handles various dynamic options. For test suites:
- It asks for a class name but doesn’t suggest any pattern.
- It asks if we want it to be a subclass of XCTestCase, which of course we do.
- It asks for the programming language.
What do we get next? Another dialog. Xcode prompts us for the location, group, and target.
File Comment Block
Then we get the file content. It starts with a file comment block:
//
// AppleTests.swift
// SampleProjectTests
//
// Created by Jon Reid on 6/17/23.
//What do you do with these? I delete them, every time. They serve no useful purpose in a project. Even if you work at a company that requires a standard file comment block at the top of each file, it doesn’t look like this. Delete.
Import Lacking Production Code
Next, we have the import statements. Or rather, import statement, singular:
import XCTestThis is incomplete. To access your production code, you need to @testable import the module.
Placeholders for Set-Up and Tear-Down
After the class declaration, we get placeholders for set-up and tear-down:
override func setUpWithError() throws {
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDownWithError() throws {
// Put teardown code here. This method is called after the invocation of each test method in the class.
}These are instructive, with explanatory comments. But I prefer not to create set-up and tear-down when I start creating a new test suite. I don’t want to make assumptions about what belongs there. Instead, I code a test, then another test. Then I can begin to see what might belong in set-up.
Set-up is there to serve the tests. Wait until you have tests so you can discover what belongs there. Delete them, comments and all.
…Wait, Really Delete Those Placeholders?
You may resist the idea of deleting these function placeholders. You may want them there because you don’t want to type them in later. That’s where my test-oriented code snippets come in. I’m lazy, and don’t enjoy typing the same things over and over. So my code snippets define:

These code snippets are available separately by subscribing to Quality Coding:
Two Test Placeholders, Including a Performance Test
Finally, we get a place to put our test. But again, they are mini-tutorials:
func testExample() throws {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
// Any test you write for XCTest can be annotated as throws and async.
// Mark your test throws to produce an unexpected failure when your test encounters an uncaught error.
// Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards.
}
func testPerformanceExample() throws {
// This is an example of a performance test case.
self.measure {
// Put the code you want to measure the time of here.
}
}Instructive code with explanatory comments is nice the first time. After that, it’s noise. I want to start writing a new test case by typing something new, not by deleting comments.
And can I tell you how many performance test cases I’ve written? Zero. They probably have their place, just not for my microtesting needs. Delete.
I want less code, not more.
What’s In My Template?
Now let’s look at the workflow of my “Swift XCTest Test Case” template.
Simple Prompt Suggesting Naming Pattern
Here’s what Xcode shows when you select my template:

First, notice that it suggests a naming pattern. I use the suffix Tests to name test suites because a test suite holds a group of test cases. Just hit Up-Arrow to move the cursor to the beginning of the field, and start typing the rest.
Note that it doesn’t ask you what to subclass, or what programming language to use. You already selected “Swift XCTest Test Case” so we know. (The download also includes an Objective-C version.)
Then specify the location, group, and target.
No File Comment Block
The file doesn’t start with a file comment block. There’s nothing to delete. Move along, move along.
Useful import Statements
The first thing in the file is not one, but two import statements:
@testable import SampleProject
import XCTestThe file template makes an educated guess about the name of your production code module. It assumes it’s the same as your project name.
This isn’t always true, of course. But even when it’s wrong, at least it shows that you should use @testable import to access the production code.
@MainActor and Sendable
The declaration of the test suite is different from Apple’s template:
@MainActor
final class QualityCodingTests: XCTestCase, Sendable {The class is declared @MainActor, which we can do in Xcode 16. This makes it much easier to deal with any objects that are isolated to the main actor, especially view controllers.
It also conforms to Sendable, which prevents warnings when using the async throws versions of setUp and tearDown.
For more on these changes, see XCTest Meets @MainActor: How to Fix Strict Concurrency Warnings.
Test Zero
Before I write the first test, I like to execute what I call Test Zero:
func test_zero() throws {
XCTFail("Tests not yet implemented in QualityCodingTests")
}This is a trick I describe in my book iOS Unit Testing by Example. Test Zero helps check that the new test suite does nothing well. It’s the first check of our new infrastructure.
Once the test fails correctly, I delete it. Then using my test-oriented code snippets, I type “test” to begin writing a test case. The test suite is gloriously empty.
I’m a lazy programmer and don’t want to waste my time deleting things I don’t need, and typing things I do need. I hope you find my XCTestCase file template useful!

Great writeup, Jon!
I’ve been creating my own file templates ever since I learned about them from your wonderful Objective-C example. :]
One suggestion for improving the Swift template would be to make the template icon a different color than the Objective-C version. I went with orange to feel more Swifty, and it really makes a big difference in quickly identifying it from the other templates.
Great idea, Joshua. …Done!
This is a great post and very helpful in cutting time down doing repetitive work. Thanks Jon!
Yay! You’re welcome, Tim.