As your app scales in complexity, manually clicking through every single screen to verify that a new feature didn't break an old one becomes impossible.
Apple provides the XCTest framework, natively integrated into Xcode, to automate this entire process.
Writing unit tests ensures your business logic is bulletproof and gives you the confidence to refactor code later.
Test files are separate from your main application code. They live in a special Testing Target.
Every test suite is a class that inherits from XCTestCase. Every individual test must be a function that begins with the word test.
import XCTest @testable import MyApp // Imports your main app logicfinal class MathUtilityTests: XCTestCase { func testAdditionLogic() { // The 3 pillars of testing: Arrange, Act, Assert // 1. Arrange: Set up the scenario let utility = MathUtility() // 2. Act: Perform the function you want to test let result = utility.add(5, to: 10) // 3. Assert: Verify the outcome is exactly what you expect! XCTAssertEqual(result, 15, "Adding 5 to 10 should equal 15") } }
If your code fetches data from the internet, a standard test will finish executing before the network request completes, leading to a false failure.
With modern Swift Concurrency, testing asynchronous code is miraculously easy. You just mark your test function as async throws!
final class NetworkTests: XCTestCase {
// The test function can pause and await results!
func testUserDownload() async throws {
let api = APIClient()
// Wait for the network logic to finish
let user = try await api.fetchUser()
// Verify the parsed data is valid
XCTAssertNotNil(user)
XCTAssertEqual(user.name, "Akash")
}
}
XCTest also allows you to measure how long a specific block of code takes to execute.
You use the measure {} block. Xcode will run the block 10 times, calculate the standard deviation, and warn you if future code changes make the function significantly slower.
func testSortingPerformance() {
let largeArray = (1...100_000).shuffled()
self.measure {
// The compiler will meticulously time this sorting operation
_ = largeArray.sorted()
}
}
What prefix must you add to a function name inside an XCTestCase class so that Xcode recognizes it as a runnable test?