SwiftUI 的 View 測試完了,接下來繼續進行 UIViewController 的測試
step1: 先開一個 UIKit 的 UIViewControlelr
/// 會進行測試的 FooViewController
class FooViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
}
step2: 在 Storyboard 上推拉出 VC,並設定 Storyboard ID,建議這個用 Class Name,可保持唯一性,而且也好找。
step3: 在 Storyboard 上建立一個 UILabel,並進行 IBOutlet 的 connection
step4: 寫測試
func testFooVCLoading() throws {
let sb = UIStoryboard(name: "Main", bundle: nil)
let sut: FooViewController = sb.instantiateViewController(identifier: String(describing: FooViewController.self))
XCTAssertNotNil(sut.fooLabel)
}
會發現,這並不會通過測試,因為在 init 的時候, UILabel 是讀不到的,在 iOS App 中,要取得與更改,一般都建議在 viewDidLoad() 之後。所以,要使用 loadViewIfNeeded()
step5: 在 vc 拿到後,要用 loadViewIfNeeded()
func testFooVCLoading() throws {
let sb = UIStoryboard(name: "Main", bundle: nil)
let sut: FooViewController = sb.instantiateViewController(identifier: String(describing: FooViewController.self))
sut.loadViewIfNeeded()
XCTAssertNotNil(sut.fooLabel)
}
加上後,就可以通過測試
step1: 宣告 VC
class CodeBasedViewController: UIViewController {
let dataString: String
init(dataString: String) {
self.dataString = dataString
super.init(nibName: nil, bundle: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
step2: 補上 required init?(coder:)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
step3: 測試 VC
import XCTest
@testable import LaunchProj
final class CodeBaseViewControllerTests: XCTestCase {
var sut: CodeBasedViewController!
override func setUpWithError() throws {
sut = CodeBasedViewController(dataString: "foo")
}
override func tearDownWithError() throws {
sut = nil
}
func testFooBaseVC() {
XCTAssertEqual(sut.dataString, "foo")
}
}
使用 Code 來寫的 VC,測試要寫的程式碼,反而是比較少的。