开发自定义规则一般建议同时定义SHORTHAND,即使当前单元测试中不会用到(例如本文中的测试),但这个规则被其他复用的时候,可能会用到SHORTHAND命名。
#import
OBJC_EXPORT id HC_equalToPoint(CGPoint point);
#ifdef HC_SHORTHAND
#define equalToPoint HC_equalToPoint
#endif
@interface HCIsEqualToPoint : HCBaseMatcher
+ (id)equalToPoint:(CGPoint)point;
- (id)initWithPoint:(CGPoint)point;
@property (nonatomic, assign) CGFloat x;
@property (nonatomic, assign) CGFloat y;
@end
代码14,扩展匹配规则HC_equalToPoint定义
在匹配规则的过程中,有一个点需要特别注意,即对匹配对象类型和完整性的判断。往往开发者把注意力都放在对对象值的匹配上,而忽略了类型和完整性这类判断,最终导致整个用例运行失败,但无法准确定位出错的位置。上面提到的对subviews是否为空的判断也是这样的一个例子。所以在自定义的匹配规则中就需要考虑到这方面的问题,如代码15的matches:方法中,先要对传入的泛型对象item校验是否为字符串,后再转化为CGPoint对象,并进行相应比对。示例中给出的是一种较简单的情况,在更复杂的情况下,除了对泛型对象的类进行校验,还要校验其是否响应某方法,属性类型,空判断,等。
#import "HCIsEqualToPoint.h"
#import
id HC_equalToPoint(CGPoint point)
{
return [HCIsEqualToPoint equalToPoint:point];
}
@implementation HCIsEqualToPoint
+ (id)equalToPoint:(CGPoint)point
{
return [[self alloc] initWithPoint:point];
}
- (id)initWithPoint:(CGPoint)point
{
self = [super init];
if (self) {
self.x = point.x;
self.y = point.y;
}
return self;
}
- (BOOL)matches:(id)item
{
if (! [item isKindOfClass:[NSString class]]) {
return NO;
}
CGPoint point = CGPointFromString((NSString *)item);
return (point.x == self.x && point.y == self.y);
}
- (void)describeTo:(id)description
{
[description appendText:@"Point not equaled."];
}
@end
代码15,扩展匹配规则HC_equalToPoint实现
一个操作多个测试方法
以上提到的几个例子中所测试的都是非常简单的操作,所以一个测试方法覆盖了一个或多个操作,但对于较复杂的操作,往往需要多个测试方法,循序渐进的断言。例如测试通过URL生成UMViewController的用例,生成一个UMViewController实例由简单到复杂可以有三种简单方式:简单的URL生成,带参数的URL生成和带Query字典的URL生成,此外还有URL参数和Query字典共用的方式。所以对于这个操作至少需要使用4个测试方法(代码16)分别进行测试。
(void)testViewControllerForSimpleURL
{
self.viewControllerA = (ViewControllerA *)[self.navigator
viewControllerForURL:
[NSURL URLWithString:@"um://viewa"]
withQuery:nil];
HC_assertThat(self.viewControllerA, HC_instanceOf([UMViewController class]));
HC_assertThat(self.viewControllerA, HC_isA([ViewControllerA class]));
}
- (void)testViewControllerForURLWithArgs
{
self.viewControllerA = (ViewControllerA *)[self.navigator
viewControllerForURL:[NSURL URLWithString:@"um://viewa?
p1=v1&p2=v2"]
withQuery:nil];
HC_assertThat(self.viewControllerA, HC_instanceOf([UMViewController class]));
HC_assertThat(self.viewControllerA, HC_isA([ViewControllerA class]));
HC_assertThat([self.viewControllerA.params allKeys], HC_containsInAnyOrder
(@"p1", @"p2", nil));
GHAssertEqualStrings(self.viewControllerA.params[@"p1"], @"v1", @"param error.");
GHAssertEqualStrings(self.viewControllerA.params[@"p2"], @"v2", @"param error.");
}
- (void)testViewControllerWithQuery
{
self.viewControllerA = (ViewControllerA *)[self.navigator
viewControllerForURL:
[NSURL URLWithString:@"um://viewa"]
withQuery:@{@"k1":@"v1", @"k2":@"v2"}];
HC_assertThat([self.viewControllerA.query allKeys], HC_containsInAnyOrder
(@"k1", @"k2", nil));
原文转自:http://blog.segmentfault.com/gaosboy/1190000000270521