我正在编写单元测试以查找某个笔尖上是否存在元素。例如,我想遍历一个 nibs 视图并检查是否存在一个引用插座“commentTextView”,以检查该文本视图是否存在。
现在,我只看到检查目标是否存在的方法(例如检查按钮是否会在单击时调用某个选择器),而不是检查我需要什么。
我正在编写单元测试以查找某个笔尖上是否存在元素。例如,我想遍历一个 nibs 视图并检查是否存在一个引用插座“commentTextView”,以检查该文本视图是否存在。
现在,我只看到检查目标是否存在的方法(例如检查按钮是否会在单击时调用某个选择器),而不是检查我需要什么。
与其检查他们是否有出口,不如为他们分配一个唯一的标签。选择 Interface Builder 中的按钮,然后转到右侧的 Attributes Inspector。朝向底部应该是一个框来设置对象的标签属性。然后,当您逐步浏览 nib 的视图时,您可以检查每个标签并使用它来确定它是什么视图。
我在这里做了几个假设,所以如果我是基地,请告诉我。
1)您有一个将连接插座的对象列表,以及这些插座的列表。(例如,File 的所有者是一个MyViewController
类并且有 outlets view
、label
、button
等;有一个UITableView
带有 outletsdelegate
和dataSource
等)
2) 您的 nib 旨在使查找 1 中的所有对象变得切实可行。例如,如果某些UIControl
对象没有被顶级对象或代理对象引用,则它已被赋予标签值以使其容易找到viewWithTag:
假设这些都是真的,那么您可以通过基本上执行以下操作来测试笔尖是否被加载(在伪代码中)
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? */)
}
}
我开始尝试实现这一点。由于 iOS nib 很大程度上基于键值编码,我认为在测试 nib 方面有很多潜力值得探索。我没有处理从笔尖中的对象发送的动作,因为我必须下车学习,但我会分享我到目前为止所做的。
这是我在SenTestCase
子类中编写的测试方法代码:
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);
}
}
这是我的ReferencingObject
和ReferencedOutlet
类的接口/实现。
@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
希望这个答案会对您或其他人有所帮助。如果您有任何问题,请告诉我。