In this XCTest tutorial, you will learn how to write a unit test that will test if UIButton is connected to @IBOutlet and has @IBAction assigned.
For this tutorial, I will create a Single View application project. I will use the default View Controller that XCode creates for all new projects and I will position on a View a single UIButton.
If you are interested in video lessons on how to write Unit tests and UI tests to test your Swift mobile app, check out this page: Unit Testing Swift Mobile App
Create a New Xcode Project
I have created a new Xcode project with a Single View Controller in it. At the center of UIView, I have positioned a single UIButton and have created for this UIButton @IBOutlet and @IBAction. On the image below you can see how my View Controller looks after I have added a UIButton to it.
Create the XCTest Test Case Class
As a next step, I will create a new XCTest Test Case class and will update its default setUp() and tearDown() methods.
The setUp() method
The setUp() method is very simple. For me to be able to access UI elements in a View Controller I first need to instantiate the view controller and make it load the View by calling the loadViewIfNeeded() method.
override func setUp() { let storyboard = UIStoryboard(name: "Main", bundle: nil) sut = storyboard.instantiateViewController(withIdentifier: "ViewController") as? ViewController sut.loadViewIfNeeded() }
The tearDown() method
In the tearDown() method I simply release resources.
override func tearDown() { sut = nil }
Unit Test to Test of UIButton is Connected
Now it is the most important part. I will create a new test method to test if the UIButton is connected and if it has IBAction assigned to it.
func testIfLoginButtonHasActionAssigned() { //Check if Controller has UIButton property let loginButton: UIButton = sut.loginButton XCTAssertNotNil(loginButton, "View Controller does not have UIButton property") // Attempt Access UIButton Actions guard let loginButtonActions = loginButton.actions(forTarget: sut, forControlEvent: .touchUpInside) else { XCTFail("UIButton does not have actions assigned for Control Event .touchUpInside") return } // Assert UIButton has action with a method name XCTAssertTrue(loginButtonActions.contains("loginButtonTapped:")) }
In the test method above I first check if View Controller has a UIButton property “loginButton“.
let loginButton: UIButton = sut.loginButton
When I have a reference to a button I can read all actions assigned to this button.
guard let loginButtonActions = loginButton.actions(forTarget: sut, forControlEvent: .touchUpInside) else { XCTFail("UIButton does not have actions assigned for Control Event .touchUpInside") return }
Now when I have an array of button actions I can check if there are any actions at all or I can check if it contains a specific action(method name).
XCTAssertTrue(loginButtonActions.contains("loginButtonTapped:"))
Complete Test Case Class
import XCTest @testable import Test_IF_UIButton_IS_Connected class Test_IF_UIButton_IS_ConnectedTests: XCTestCase { var sut: ViewController! override func setUp() { let storyboard = UIStoryboard(name: "Main", bundle: nil) sut = storyboard.instantiateViewController(withIdentifier: "ViewController") as? ViewController sut.loadViewIfNeeded() } override func tearDown() { sut = nil } func testIfLoginButtonHasActionAssigned() { let loginButton: UIButton = sut.loginButton guard let loginButtonActions = loginButton.actions(forTarget: sut, forControlEvent: .touchUpInside) else { XCTFail("UIButton does not have actions assigned for Control Event .touchUpInside") return } XCTAssertTrue(loginButtonActions.contains("loginButtonTapped:")) } }
I hope this tutorial will be of some value to you. Have a look at other XCTest unit testing tutorials on this blog. You might find many other interesting tutorials.
Happy unit testing 🙋🏻♂️
Thanks for your writing!