Jack Of Diamonds
Jack Of Diamonds

Reputation: 129

Unit Test button added to view

I am a unit test newbie, I am testing if my button has been added to the view.

My first test passes correctly:

XCTAssertNotNil(vc.button, "button Not Initialised")

But my second test fails when i have the view.addSubview(button) in the code

XCTAssertNotNil(vc.button.superview, "button Not added to view")

My question is how do i test to see if the button has been added to the view, I am not using storyboards, everything is coded. Because the first test will pass regardless of if i have addSubview in the code or not.

Thanks

In my ViewController class i initialise the button:

 private(set) lazy var myButton: UIButton = {
    let myButton = UIButton(frame: CGRectZero)
    return myButton
}()

and in viewDidLoad i add it to subview and give it constraints:

view.addSubview(myButton)

My test function is:

func testAddRoomButtonInRoomsViewController() {
    let vc = myViewController()
    XCTAssertNotNil(vc.myButton, "Button Not Initialised")
    XCTAssertNotNil(vc.myButton.superview, "Button Not Added To View")
}

Upvotes: 1

Views: 1654

Answers (2)

tanz
tanz

Reputation: 2547

It is absolutely valid to write a test to check if a view has been added to a superview. I have just tried the following and it passes successfully:

- (void)testView
{
    UIView *superview = [UIView new];
    UIView *view = [UIView new];

    [superview addSubview:view];
    XCTAssertNotNil(view.superview);
}

If your assertion XCTAssertNotNil(vc.button.superview, "button Not added to view")fails it is either because you don't add the subview to the superview (which is likely what you want to test) or because your superview gets deallocated before you can complete your test.

If the latter you need to make sure that you keep a strong reference to the superview to perform your test - a superview keeps a strong reference to each of its subviews but not the other way round (as that would generate a retained cycle). So view.superview is really a weak property and it would be set to nil if/when the superview is deallocated.

- (void)testView
{
    UIView *superview = [UIView new];
    UIView *view = [UIView new];

    [superview addSubview:view];

    superview = nil;

    XCTAssertNil(view.superview);//superview will be deallocated by now - this value is nil
}

I hope this helps.

//UPDATE:

Looking at the code it is now clear that you were not calling addSubview: before the test as the viewDidLoad was not called. @figs suggested how to work around this.

Upvotes: 0

fiks
fiks

Reputation: 1055

The viewDidLoad is not called in your test case, therefore it fails. You have to call it manually.

1. Introduce an extension

    extension UIViewController {

        func startViewLifecycle() {
            view.setNeedsLayout()
            view.layoutIfNeeded()
        }
    }

2. Call it in your test case:

func testAddRoomButtonInRoomsViewController() {
    let vc = myViewController()
    vc.startViewLifecycle()

    XCTAssertNotNil(vc.myButton, "Button Not Initialised")
    XCTAssertNotNil(vc.myButton.superview, "Button Not Added To View")
}

Upvotes: 2

Related Questions