iOS开发——单元测试(2)

发表于:2016-06-07来源:cocoa China作者:Sindri的小巢点击数: 标签:单元测试
NSMutableDictionary * dict = [[NSJSONSerialization JSONObjectWithData: [json dataUsingEncoding: NSUTF8StringEncoding] options: kNilOptions error: nil] mutableCopy]; LXDTestsModel * model = [[LXDTestsM

  NSMutableDictionary * dict = [[NSJSONSerialization JSONObjectWithData: [json dataUsingEncoding: NSUTF8StringEncoding] options: kNilOptions error: nil] mutableCopy];

  LXDTestsModel * model = [[LXDTestsModel alloc] initWithDictionary: dict];

  XCTAssertNotNil(model);

  XCTAssertTrue([model.name isEqualToString: @"SindriLin"]);

  XCTAssertTrue([model.age isEqual: @(22)]);

  XCTAssertEqual(model.flags, 987654321);

  XCTAssertTrue([model isKindOfClass: [LXDTestsModel class]]);

  model = [LXDTestsModel modelWithName: @"Tessie" age: dict[@"age"] flags: 562525];

  XCTAssertNotNil(model);

  XCTAssertTrue([model.name isEqualToString: @"Tessie"]);

  XCTAssertTrue([model.age isEqual: dict[@"age"]]);

  XCTAssertEqual(model.flags, 562525);

  NSDictionary * modelJSON = [model modelToDictionary];

  XCTAssertTrue([modelJSON isEqual: dict] == NO);

  dict[@"name"] = @"Tessie";

  dict[@"flags"] = @(562525);

  XCTAssertTrue([modelJSON isEqual: dict]);

  }

  逻辑测试的目的是为了检测在代码执行前后发生的变化是否符合预期,因此可以说80%左右的单元测试都是逻辑测试。最开始笔者学习单元测试的时候总有一种无从下手的感觉,但是当你从无形抽象的逻辑操作找到了数据变化的规律的时候,对应的单元测试就能很快的写出来了。

  性能测试

  相较于上面的逻辑测试,性能测试的地位有些尴尬。在现今的开发环境下,我们已经能通过 instrument工具很好的查找到项目中的代码耗时点,性能测试就有种弃之可惜,食之无味的感觉了。但是为了本文的完整性,还是将这个补充完毕。笔者在测试model类中添加了类方法,用来随机生成100个类实例对象,并且在每次创建对象后让线程休眠一段时间来模拟耗时操作:

  + (NSArray

  *)randomModels

  {

  NSMutableArray * models = @[].mutableCopy;

  NSArray * names = @[

  @"SindriLin", @"Bison", @"XiongZengHui", @"ZengChengChun", @"Tessie"

  ];

  NSArray * ages = @[

  @15, @20, @25, @30, @35

  ];

  NSArray * flags = @[

  @123, @456, @789, @012, @234

  ];

  for (NSUInteger idx = 0; idx < 100; idx++) {

  LXDTestsModel * model = [LXDTestsModel modelWithName: names[arc4random() % names.count] age: ages[arc4random() % ages.count] flags: [flags[arc4random() % flags.count] unsignedIntegerValue]];

  [models addObject: model];

  [NSThread sleepForTimeInterval: 0.01];

  }

  return models;

  }

  运行测试用法后控制台会输出下面的信息,其中红框中表示执行代码总耗时,在此demo中总共运行了11.015秒的时长

  性能测试输出

  虽然性能测试的定位确实有些鸡肋,但是另一方面,直接使用单元测试来获取某段代码的执行时间要比使用instrument快的多。通过性能测试直观的获取执行时间后,我们可以根据需要来决定是否将这些代码放到子线程中执行来优化代码(很多时候,数据转换会占用大量的CPU计算资源)

  异步测试

  由于单元测试是在主线程中进行的,因此异步操作的测试在执行完毕之前,往往已经结束了。为了实现异步测试,笔者采用while()的方式无限循环等待,为了实现这个效果,我在LXDTestsModel头文件中添加了一个NSData类型的属性以及一个异步操作的接口方法,通过判断这个属性值来实现效果:

  - (void)asyncConvertToData

  {

  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

  NSDictionary * modelJSON = nil;

  for (NSInteger idx = 0; idx < 20; idx++) {

  modelJSON = [self modelToDictionary];

  [self setValuesWithDictionary: modelJSON];

  [NSThread sleepForTimeInterval: 0.001];

  }

  _data = [NSJSONSerialization dataWithJSONObject: modelJSON options: NSJSONWritingPrettyPrinted error: nil];

  });

  }

  上面的代码在系统创建的默认等级的子线程中执行了一段耗时代码,最后把json转换成NSData数据保存在自身的属性中。对应的异步测试代码如下:

原文转自: http://www.cocoachina.com/ios/20160607/16612.html