I am currently trying to understand Unit Testing in Swift 4. I have a class, with a method that setups my view controllers.
I would like to ensure that this method sets the title on the ViewController correctly.
However I cannot understand how to write this test?
This is my code and test so far.
Currently my tests fails with:
XCTAssertEqual failed: ("nil") is not equal to ("Optional("Favourites")") -
How is it possible to test this behaviour? Any help would be much appreciated.
Controller
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
}
}
Tests
import Foundation
import XCTest
@testable import Podcasts
class MainTabBarControllerTests: XCTestCase {
func testTheInitialViewControllerShouldHaveTitleFoo() {
let sut = MainTabBarController()
let _ = sut.viewDidLoad()
XCTAssertEqual(sut.navigationItem.title, "Favourites")
}
}
There are some issues with accessing proper views in your code snippet. Btw I wrote an additional test for your tab bar controller, hope it will help :) Try this to pass the test:
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")
}
}
It's good that you've already used Given-When-Then, but it would even great if you improve naming of the test. There are a lot of conventions, for example, I prefer something like test_SubjectUnderTest_doSomething_whenConditionsAreCorrect.
Here is another tip. Try to figure out how to separate the logic between view and view controller. It you get your hands dirty into at least MVP (Model-View-Presenter), then you'll figure out that its testability is better.
By the way, instead of this kind of tests it's more reasonable to consider UI tests. UI tests mostly rely on accessibility IDs. The most popular tools for test automation are Appium or XCUITests/Earlgrey if you prefer to go with native.