Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write unit test for button tap?

Here I'm trying to check unit test cases for view controller. - I have a view controller with button and label. - When you click on the button, it will call another method. which feeds the data to the button action label text change.
- I want to check that button triggered that method or not? without adding any boolean or return type of the function.

Here is my code.

class ViewController: UIViewController {

    @IBOutlet weak var buttonFetch: UIButton?

    @IBOutlet weak var nameLabel: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()

    }

    @IBAction func fetchUser() {
        self.nameLabel.text = self.getUser()
    }

    func getUser() ->String {
        return User.data()
    }
}

struct User  {
    static func data()->String{
        return "Apple"
    }
}

Here is my test case

func testFetchUserAction() {
        controller.buttonFetch?.sendActions(for: .touchDown)
        // I want to test the method getUser from viewcontroller gets called or not
        // some thing like this XCTAssert(self.controller.getUser(),"not called")
        XCTAssertEqual(self.controller.nameLabel.text!, "Apple")

    }
like image 474
Damodar Avatar asked Dec 13 '18 06:12

Damodar


2 Answers

Have you tried as like below..

func testFetchUserAction() {

    self.controller.nameLabel.text = nil

    //Use this line, If you assigned touchUpInside to your button action
    controller.buttonFetch?.sendActions(for: .touchUpInside)

    //Use this line, If you assigned touchDown to your button action
    controller.buttonFetch?.sendActions(for: .touchDown)

    XCTAssert(self.controller.nameLabel.text != nil, "not called")

}

Note: To make test case failed purposely, you can change UIControl.Event in sendActions

like image 141
Natarajan Avatar answered Sep 18 '22 21:09

Natarajan


What you're missing:

Make sure to call loadViewIfNeeded() somewhere.

This can be in the test, or in setUp(). This will load your outlets, and call viewDidLoad().

Then, as much as possible, test the result of invoking an action, instead of whether or not a method was called. You've done this in your example assertion.

I'd also add that the correct action for buttons is almost always .touchUpInside, not .touchDown. This allows the user to press a button, then drag away to change their mind. "I don't want to push this after all."

like image 45
Jon Reid Avatar answered Sep 19 '22 21:09

Jon Reid