如何使用XCTest测试代码创建的UIView中的UILabel
解决XCTest访问DashBoardView中dashboardLabel的问题
你的核心问题是dashboardLabel是DashBoardView的createSubviews方法内的局部变量,外部代码(包括测试用例)完全无法访问它。下面给你两种常用的解决方案,你可以根据测试场景选择:
方案1:将dashboardLabel改为实例属性(推荐单元测试使用)
这种方式直接把label暴露为DashBoardView的实例属性,通过@testable import让测试用例可以访问内部属性,适合单元测试场景。
修改DashBoardView.swift
import UIKit class DashBoardView: UIView { // 将label声明为实例属性,默认internal权限,测试target可通过@testable访问 let dashboardLabel: UILabel = { let label = UILabel() label.text = "Dashboard Label" label.textColor = .black label.frame = CGRect(x:60, y:80, width: 200, height: 30) label.backgroundColor = .lightGray label.font = UIFont(name: "Avenir-Oblique", size: 13) label.textAlignment = .center return label }() override init(frame: CGRect) { super.init(frame: frame) createSubviews() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) fatalError("init(coder:) has not been implemented") } // MARK: - Create Subviews func createSubviews() { backgroundColor = .white // 别忘了把label添加到视图上(你原来的代码漏掉了这一步!) addSubview(dashboardLabel) } }
编写测试用例
import XCTest @testable import DashBoard class DashBoardTests: XCTestCase { func test_if_title_is_DashBoard() { let vc = DashBoardViewController() let _ = vc.view XCTAssertEqual(vc.navigationItem.title, "DashBoard") } // 直接测试DashBoardView的label文本 func test_dashboardLabel_text() { let dashboardView = DashBoardView() XCTAssertEqual(dashboardView.dashboardLabel.text, "Dashboard Label") } // 通过ViewController间接测试label文本 func test_dashboardLabel_text_via_viewController() { let vc = DashBoardViewController() let _ = vc.view // 触发loadView,完成视图初始化 XCTAssertEqual(vc.dashboardview.dashboardLabel.text, "Dashboard Label") } }
方案2:使用Accessibility标识符(适合UI测试或不想暴露内部属性的场景)
如果你不想把内部视图暴露给外部,可以给label设置一个唯一的accessibilityIdentifier,然后在测试中通过视图层级查找它,这种方式更贴近用户实际交互,适合UI测试。
修改DashBoardView.swift
import UIKit class DashBoardView: UIView { override init(frame: CGRect) { super.init(frame: frame) createSubviews() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) fatalError("init(coder:) has not been implemented") } // MARK: - Create Subviews func createSubviews() { backgroundColor = .white let dashboardLabel : UILabel = { let label = UILabel() label.text = "Dashboard Label" label.textColor = .black label.frame = CGRect(x:60, y:80, width: 200, height: 30) label.backgroundColor = .lightGray label.font = UIFont(name: "Avenir-Oblique", size: 13) label.textAlignment = .center // 设置唯一的accessibility标识符 label.accessibilityIdentifier = "DashboardLabel" return label }() // 必须添加到视图上才能显示和被找到 addSubview(dashboardLabel) } }
编写测试用例
import XCTest @testable import DashBoard class DashBoardTests: XCTestCase { func test_if_title_is_DashBoard() { let vc = DashBoardViewController() let _ = vc.view XCTAssertEqual(vc.navigationItem.title, "DashBoard") } func test_dashboardLabel_text_via_accessibility() { let vc = DashBoardViewController() let _ = vc.view // 加载视图 // 通过accessibilityIdentifier查找label guard let dashboardLabel = vc.view.subviews.first(where: { $0.accessibilityIdentifier == "DashboardLabel" }) as? UILabel else { XCTFail("无法找到标识符为DashboardLabel的UILabel") return } XCTAssertEqual(dashboardLabel.text, "Dashboard Label") } }
补充你原代码的两个小问题
- 遗漏添加label到视图:你原来的
createSubviews方法里创建了label,但没有调用addSubview(dashboardLabel),导致label永远不会显示在界面上,测试时也无法找到,一定要补上。 - 重复设置背景色:原代码里连续设置了
label.backgroundColor = .green和label.backgroundColor = .lightGray,后者会覆盖前者,建议只保留一个。
内容的提问来源于stack exchange,提问作者sjm
相关产品推荐
相关产品推荐

