step1: 開好測試 class 後,將 TapCounterViewController 設成 sut,把 FakeUserDefaults 設定好變數。在 setup 和 tear down 的部分,將物件寫好。
在單元測試中,SUT 代表的是 “System Under Test”,也就是被測試的系統1。從單元測試的角度來看,被測試的系統代表了在測試中所有不是預定義的程式碼片段,如 stubs 或 mocks 的類別1。換句話說,SUT 是你想要測試的對象2。1
/// TapCounterViewControllerTests.swift
import XCTest
@testable import TwStockTools
final class TapCounterViewControllerTests: XCTestCase {
private var sut: TapCounterViewController!
private var defaults: FakeUserDefaults!
override func setUpWithError() throws {
try super.setUpWithError()
sut = TapCounterViewController()
defaults = FakeUserDefaults()
sut.userDefaults = defaults
}
override func tearDownWithError() throws {
sut = nil
defaults = nil
try super.tearDownWithError()
}
}
step2: 開始測 sut 的 label,請務必要呼叫 loadViewIfNeeded(),不然 sut 會有預期以外的行為。先寫個”0”,來保證測試會 failed
func testLabelWith6() {
defaults.set(6, forKey: "tapCount")
/// 要呼叫 loadViewIfNeeded() 不然 UI 元件反應會不如預期
sut.loadViewIfNeeded()
XCTAssertEqual(sut.countLabel.text, "0")
}
待測試 failed 後,再將正確的值補上去
step3: 除了正確的 Label 以外,我們還有一個 UIButton 要測試。可以使用 sendActions(:) 來觸發 button 本來設定好的 action,這邊就直接跳到正確的結果了,不再貼上錯誤的第一次。
func testButtonTapped() {
/// 要呼叫 loadViewIfNeeded() 不然 UI 元件反應會不如預期
sut.loadViewIfNeeded()
/// 在 unit testing 中讓 button 發動 touchUpInside Action
sut.addButton.sendActions(for: .touchUpInside)
XCTAssertEqual(sut.countLabel.text, "已經點擊了 1 下")
}
Voilà,你測試了 UserDefaultsProtocol,也測完了 TapCounterViewController 與 UserDefaultsProtocol 的互動。