tezvyn:

XCTestCase: One Fresh Instance Per Test

AI-drafted, machine-checkedintermediate

A XCTestCase subclass is a lab bench for isolated experiments. Each test method is a fresh invocation checked by the runner. The silent killer is shared mutable state on the case: without setUp, tests flake because execution order is never guaranteed.

WHY IT EXISTS: Before XCTest, Mac and iOS developers relied on manual validation or third-party frameworks with heavy boilerplate. Apple needed a first-party runner integrated into Xcode that could discover tests automatically, report results in the IDE, and guarantee isolation so one crash does not kill the entire suite. XCTestCase is the vessel for that guarantee.

THE MENTAL MODEL: Treat each XCTestCase subclass as a disposable lab bench. You do not keep the bench dirty after an experiment. Instead, the test runner walks your class, finds every method that begins with the lowercase word test, and instantiates a brand new case object for each one. Shared helpers go in the class, but the data under inspection belongs in the method or in setUp.

HOW IT WORKS: When you press Command-U, the XCTest runner uses Objective-C runtime reflection to enumerate test methods on your XCTestCase subclass. For each method, it allocates a new instance, calls setUp, invokes the test method, then calls tearDown. If a test method throws or records a failure, the runner captures it and moves to the next fresh instance. The prefix rule is strict; a method named verifyData is ignored unless you explicitly ask the runner to treat it as a test. Asynchronous work uses expectations that you create and wait for inside the test method.

WHEN TO USE IT: Use an XCTestCase subclass for every cohesive unit you are validating, such as a network client, a view model, or a parsing routine. Use individual test methods to check one specific behavior, like decoding a 200 response or rejecting malformed JSON. Keep the class small enough that you can read all its tests without scrolling excessively.

WHEN NOT TO USE IT: Do not use XCTestCase to host application launch logic or long-running integration flows that belong in UI tests. Do not put expensive one-time setup in setUp; use setUpWithError or a one-time class setUp if the cost is unavoidable. Avoid asserting logic inside helper methods without calling XCTFail or related macros directly, because the failure line number will point to the helper and obscure the actual test.

ONE CANONICAL EXAMPLE: A LoginViewModelTests case might contain testEmptyPasswordShowsError and testValidCredentialsEmitsSuccess. The first instantiates the view model, sends an empty string, and asserts the published error string is non-nil. The second feeds valid credentials and expects the isLoading flag to become false. Each method runs on its own instance, so even if the second test crashes, the first result is already recorded.

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.