You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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")
    }
}

补充你原代码的两个小问题

  1. 遗漏添加label到视图:你原来的createSubviews方法里创建了label,但没有调用addSubview(dashboardLabel),导致label永远不会显示在界面上,测试时也无法找到,一定要补上。
  2. 重复设置背景色:原代码里连续设置了label.backgroundColor = .green和label.backgroundColor = .lightGray,后者会覆盖前者,建议只保留一个。

内容的提问来源于stack exchange,提问作者sjm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:18:33