iT邦幫忙

2023 iThome 鐵人賽

DAY 29
0
Mobile Development

在 iOS 專案上加上 Unit testing - 因為 You need testing系列 第 29

D29 - 在 iOS 專案加上測試-You need testing { 測 UIViewController }

  • 分享至 

  • xImage
  •  

SwiftUI 的 View 測試完了,接下來繼續進行 UIViewController 的測試

測試 Storyboard 產的 UIViewController

step1: 先開一個 UIKit 的 UIViewControlelr

/// 會進行測試的 FooViewController
class FooViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

step2: 在 Storyboard 上推拉出 VC,並設定 Storyboard ID,建議這個用 Class Name,可保持唯一性,而且也好找。

https://ithelp.ithome.com.tw/upload/images/20231010/20140622UfRlnNaDnA.png

step3: 在 Storyboard 上建立一個 UILabel,並進行 IBOutlet 的 connection

https://ithelp.ithome.com.tw/upload/images/20231010/2014062262j0tssMK8.png

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()

https://ithelp.ithome.com.tw/upload/images/20231010/201406226PBuqn5tCs.png

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)
    }

加上後,就可以通過測試


測試使用程式碼 init 的 UIViewController

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,測試要寫的程式碼,反而是比較少的。


上一篇
D28 - 在 iOS 專案加上測試-You need testing {使用 ObservableObject 加入測試}
下一篇
D30 - 在 iOS 專案加上測試-You need testing { 測試報告 }
系列文
在 iOS 專案上加上 Unit testing - 因為 You need testing32
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
John Lu
iT邦新手 4 級 ‧ 2023-10-10 15:39:00

你幾乎快寫完了欸

Marvin iT邦新手 1 級 ‧ 2023-10-11 11:29:58 檢舉

還沒啦,測試博大精深,要講測試 300 天的實踐,大概都不夠吧

我要留言

立即登入留言