I'm making a couple of assumptions here, so if I'm base, let me know.
1) You have a list of objects which will have outlets connected, and a list of those outlets. (e.g., File's owner is a MyViewController
class and has outlets view
, label
, button
, and so on; there is a UITableView
with outlets delegate
, and dataSource
, etc.)
2) Your nibs are designed to make it practical to find all of the objects in 1. For example, if some UIControl
isn't referenced by a top-level object or a proxy object, it has been given a tag value to make it easy to find with viewWithTag:
Assuming these are true, then you could test that a nib gets loaded by basically doing the following (in pseudo code)
for each referencingObject in nibObjects
{
for each outletName in referencingObject.outletNames
{
assertExistence(/* is an object referenced by this outlet? */)
assertProperties(/* does the object conform to the properties expected for this referencing object / outlet pairing? */)
}
}
I started making a stab at an implementation of this. Since iOS nibs are based heavily on key-value coding I think there is a lot of potential to be explored in testing nibs, for what its worth. I didn't get into handling sent actions from objects in the nib as I have to get off SO and study, but I'll share what I did so far.
Here's the test method code I wrote in my SenTestCase
subclass:
ViewController *vc = [[ViewController alloc] init];
UINib *nib1 = [UINib nibWithNibName:@"ViewController1" bundle:nil];
NSArray *topLevelObjects = [nib1 instantiateWithOwner:vc options:nil];
ReferencingObject *filesOwnerReferencingObject = [[ReferencingObject alloc] init];
filesOwnerReferencingObject.object = vc;
//Make a referenced object outlet for the view
ReferencedOutlet *viewOutlet = [[ReferencedOutlet alloc] init];
viewOutlet.name = @"view";
viewOutlet.propertyAssertionBlock = ^(id object) {
UIView *theView = (UIView *)object;
STAssertEquals(1.0f, theView.alpha, @"shouldn't have any transparency");
};
//Make a referenced object outlet for the label
ReferencedOutlet *labelOutlet = [[ReferencedOutlet alloc] init];
labelOutlet.name = @"label";
labelOutlet.propertyAssertionBlock = ^(id object) {
UILabel *theLabel = (UILabel *)object;
NSString *expectedLabelText = @"ViewController1.xib";
STAssertTrue([expectedLabelText isEqualToString:theLabel.text], nil);
};
filesOwnerReferencingObject.outlets = @[ viewOutlet, labelOutlet ];
NSArray *referencingObjects = @[ filesOwnerReferencingObject ];
for (ReferencingObject *referencingObject in referencingObjects)
{
for (ReferencedOutlet *outlet in referencingObject.outlets)
{
id object = [filesOwnerReferencingObject.object valueForKey:outlet.name];
STAssertNotNil(object, nil);
outlet.propertyAssertionBlock(object);
}
}
And here is my interface / implementation of the ReferencingObject
and ReferencedOutlet
classes.
@interface ReferencingObject : NSObject
@property (nonatomic, strong) id object;
@property (nonatomic, strong) NSArray *outlets;
@end
@implementation ReferencingObject
@end
typedef void (^ReferencedOutletPropertyAssertionBlock)(id);
@interface ReferencedOutlet : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) ReferencedOutletPropertyAssertionBlock propertyAssertionBlock;
@end
@implementation ReferencedOutlet
@end
Hopefully this answer will be help to you or someone else. Let me know if you have any questions.