Test Driven Development (TDD) is a discipline in agile software development. There are three laws of TDD:
The development flow of TDD is:
(Iteration start) -> Red -> Green -> Refactor -> (Next iteration)
Do as many quick iterations as needed until all requirements are met.
(P.s.: As we always get new requirements, this usually never ends 🤣)
import XCTest
@testable import UnitTestProject
class UnitTestProjectTests: 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.
}
continueAfterFailure: Bool
and executionTimeAllowance: TimeInterval
measure()
methodsexpectation()
methods for this.wait()
methodsXCTAssert()
methods for testing, e.g. boolean, nil and non-nil, equality, value comparison and other assertions, e.g.func testExample() throws {
let x = 0
XCTAssertTrue(x == 0, "Unexpected: x should be 0")
}
Testing asynchronous operations example (see here):
func testDownloadWebData() {
// Create an expectation for a background download task.
let expectation = XCTestExpectation(description: "Download apple.com home page")
// Create a URL for a web page to be downloaded.
let url = URL(string: "https://apple.com")!
// Create a background task to download the web page.
let dataTask = URLSession.shared.dataTask(with: url) { (data, _, _) in
// Make sure we downloaded some data.
XCTAssertNotNil(data, "No data was downloaded.")
// Fulfill the expectation to indicate that the background task has finished successfully.
expectation.fulfill()
}
// Start the download task.
dataTask.resume()
// Wait until the expectation is fulfilled, with a timeout of 10 seconds.
wait(for: [expectation], timeout: 10.0)
}
The Swift Testing framework is the new testing framework for Swift applications since Sept 2024. It is a modern testing framework that is easy to use and provides a lot of features for testing Swift code.
@Test func testExample() {
#expect(1 + 1 == 2)
}
It supports parameterized testing using @Test with arguments:
@Test("Continents mentioned in videos", arguments: [
"A Beach",
"By the Lake",
"Camping in the Woods"
])
func mentionedContinents(videoName: String) async throws {
let videoLibrary = try await VideoLibrary()
let video = try #require(await videoLibrary.video(named: videoName))
#expect(video.mentionedContinents.count <= 3)
}
You can customize the behavior of tests or test suites using traits specified in your code. Traits can describe the runtime conditions for a test, like which device a test should run on, or limit a test to certain operating system versions. Traits can also help you use continuous integration effectively by specifying execution time limits for your tests.
@Test(.enabled(if: AppFeatures.isCommentingEnabled))
func videoCommenting() async throws {
let video = try #require(await videoLibrary.video(named: "A Beach"))
#expect(video.comments.contains("So picturesque!"))
}
To check that the code under test throws a specific error, or to continue a longer test function after the code throws an error, pass that error as the first argument of expect(throws:_:sourceLocation:performing:)
, and pass a closure that calls the code under test:
@Test func cannotAddToppingToPizzaBeforeStartOfList() {
var order = PizzaToppings(bases: [.calzone, .deepCrust])
#expect(throws: PizzaToppings.Error.outOfRange) {
try order.add(topping: .mozarella, toPizzasIn: -1..<0)
}
}
When working with a large selection of test functions, it can be helpful to organize them into test suites.
@Suite("Food truck tests")
struct FoodTruckTests {
@Test func foodTruckExists() { ... }
}
Source: Apple
In order to get your app through the Apple validation process, you should make sure that you meet Apples requirements concerning app behaviour (using only allowed frameworks) and also the Human Interface Guidelines: