UITabBarController 中的测试方法正确设置标题

Posted

技术标签:

【中文标题】UITabBarController 中的测试方法正确设置标题【英文标题】:Testing method in UITabBarController sets title correctly 【发布时间】:2018-09-30 16:21:17 【问题描述】:

我目前正在尝试了解 Swift 4 中的单元测试。 我有一个类,它有一个设置我的视图控制器的方法。

我想确保此方法正确设置 ViewController 上的标题。

但是我不明白如何编写这个测试?

这是我目前的代码和测试。

目前我的测试失败了:

XCTAssertEqual failed: ("nil") is not equal to ("Optional("Favourites")") - 

如何测试这种行为?任何帮助将非常感激。

控制器

class MainTabBarController: UITabBarController 

    override func viewDidLoad() 
        super.viewDidLoad()

        setupTabBar()
        setupViewControllers()
    

    // MARK:- Setup

    fileprivate func setupViewControllers() 
        viewControllers = [
            generateNavigationController(with: UIViewController(), title: "Favourites", image: UIImage(imageLiteralResourceName: "favorites")),
            generateNavigationController(with: UIViewController(), title: "Search", image: UIImage(imageLiteralResourceName: "search")),
            generateNavigationController(with: UIViewController(), title: "Downloads", image: UIImage(imageLiteralResourceName: "downloads"))
        ]
    

    fileprivate func setupTabBar() 
        tabBar.tintColor = .purple
    

    // MARK:- Helpers

    fileprivate func generateNavigationController(with rootViewController: UIViewController, title: String, image: UIImage) -> UIViewController 

        let controller = UINavigationController(rootViewController: rootViewController)

        controller.tabBarItem.title = title
        controller.tabBarItem.image = image

        rootViewController.navigationItem.title = title
        navigationController?.navigationBar.prefersLargeTitles = true

        return controller
    

测试

import Foundation
import XCTest

@testable import Podcasts

class MainTabBarControllerTests: XCTestCase 

    func testTheInitialViewControllerShouldHaveTitleFoo() 
        let sut = MainTabBarController()

       let _ = sut.viewDidLoad()

        XCTAssertEqual(sut.navigationItem.title, "Favourites")
    

【问题讨论】:

【参考方案1】:

在您的代码 sn-p 中访问正确的视图存在一些问题。顺便说一句,我为您的标签栏控制器编写了一个额外的测试,希望它会有所帮助:) 试试这个以通过测试:

class MainTabBarControllerTests: XCTestCase 

    func testFirstTabTitleIsCorrectAfterInitialSetup() 
        // Given
        let sut = MainTabBarController()

        // When
        sut.viewDidLoad()

        // Then
        let viewController = sut.viewControllers?.first
        let title = viewController?.tabBarItem.title
        XCTAssertEqual(title, "Favourites")
    

    func testNavigationTitleIsCorrectAfterInitialSetup() 
        // Given
        let sut = MainTabBarController()

        // When
        sut.viewDidLoad()

        // Then
        let viewController = sut.viewControllers?.first as? UINavigationController
        let title = viewController?.viewControllers.first?.navigationItem.title
        XCTAssertEqual(title, "Favourites")
    

您已经使用了 Given-When-Then,这很好,但如果您改进测试的命名,那就更好了。有很多约定,例如,我更喜欢 test_SubjectUnderTest_doSomething_whenConditionsAreCorrect 之类的东西

这是另一个提示。尝试弄清楚如何分离视图和视图控制器之间的逻辑。如果您至少涉足 MVP(Model-View-Presenter),那么您会发现它的可测试性更好。

顺便说一句,考虑 UI 测试 来代替这种测试更合理。 UI 测试主要依赖于可访问性 ID。最流行的测试自动化工具是 Appium 或 XCUITests/Earlgrey,如果你更喜欢原生的话。

【讨论】:

非常感谢。你帮了我很多,我真的很感激 补充几点说明: 1) 我们可以使用sut.loadViewIfNeeded() 触发完整加载机制,而不是直接调用sut.viewDidLoad()。 2) cmets 贴错标签。我们从 Given(也称为 Arrange)开始。 Then When(也称为 Act)。最后然后(也称为断言)。所以它是 Given-When-Then,而不是 When-Given-Then。 3)通过视图控制器进行单元测试是合法的。 UI 测试最好只进行有限的检查,检查是否已连接好。这是测试金字塔:底部很多,顶部很少。 @JonReid 感谢您注意到 Given-When-Then 不正确的顺序,我只是复制粘贴了错误的 cmets!我编辑了我的答案。我同意你的 UI 测试。测试金字塔是关键思想。

以上是关于UITabBarController 中的测试方法正确设置标题的主要内容,如果未能解决你的问题,请参考以下文章

UITabBarController中的坑

嵌入在 NavigationController 中的 UITabBarController

ios 6 中的 UITabBarController 旋转问题

xamarin.ios 中的 UITabBarController 不使用 StoryBoard

UITabBarController 中每个选项卡有多个 UIViews?

UITabBarController - 如何访问视图控制器?