iOS开发中的单元测试:URLManager中的测试用例解析(4)

发表于:2013-11-12来源:sf作者:gaosboy点击数: 标签:单元测试
开发自定义规则一般建议同时定义SHORTHAND,即使当前单元测试中不会用到(例如本文中的测试),但这个规则被其他复用的时候,可能会用到SHORTHAND命名。

  开发自定义规则一般建议同时定义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