专栏名称: 51Testing软件测试网
51Testing软件测试网,人气最旺的软件测试技术门户,提供软件测试社区交流,软件测试博客,人才服务,测试沙龙,测试杂志,测试资料下载等全方位信息服务,是国内最专业的软件测试就业培训、企业服务供应商...
目录
相关文章推荐
51好读  ›  专栏  ›  51Testing软件测试网

单元测试Tests的简介及使用

51Testing软件测试网  · 公众号  · 测试  · 2017-02-06 17:31

正文


  单元测试的代码都要以 Tests开头,这样才会有左侧的菱形块,鼠标点击就能运行单元测试代码:

  1. 单元测试是以代码测试代码 ;

  2. 红灯,绿灯迭代开发 ;

  3. 在日常开发中,数据大部分来自于网络,很难出现所有的边界数据(比如:年龄非法,过大或者为负时) ,此时如果没有测试所有的条件就上架,那么在运行时会造成闪退!用户体验不好!

  4. 单元测试里可以自主建立"测试用例",以用于专门检查边界条件!

  5. 在单元测试中打印 NSLog函数,发现交互并不好~显示的东西太多了,那是因为单元测试中并不是以 NSLog 函数为测试方法的! NSLog 函数是程序猿用眼睛看自己判断的方法,单元测试用的是'断言 --> XCTAssert '来测试,"提前预判"条件必须满足!

  6. 为什么有些公司不进行单元测试: 代码覆盖度不好!有些公司认为只要是函数就要测试,这样需要测试的代码非常非常多!很麻烦!逻辑不断重构之后好多写好的测试代码来不及调整!

  提示:

  1、不是所有的代码都需要进行单元测试! 面向对象的方法有一个原则:开闭原则 " 对外开发,对内封闭"

  类里的私有方法不用进行测试!

  .h文件(接口文件)中的代码的实现需要测试!

  所有和 UI 有关的代码都不需要进行测试,同时也不好测试!因为 UI 测试需要用户交互,我们用代码检测的是一些极端的边界条件的测试,并不包含用户的鬼神操作!

  2、MVVM 的设计模式中:它把小的业务逻辑代码封装出来放到 ViewModel 中,把它们了可以测试的代码,让程序的健壮性得以实现!

  3、单元测试的代码的覆盖度一般要求在70%以内!这已经算是非常优秀的程序了!基本能够保证超过你虚的健壮性!

  我们可以打开 AFNetworking, 会发现 AFN 的图片下册有一行导航栏模块,第二个模块中写着 Codecov--->这就是 代码的单元覆盖度!

  郭曜源的 YYModel 中的代码的单元覆盖度达到了惊人的99%,足以见得他本人开源这份代码下了多少时间和精力!

  注意一些主要方法:

  1、XCTAssert 断言 ;

  2、XCTAssert(age == person.age , @"年龄不正确") 他的意思是 : 如果 age == person.age 这个条件不满足,那就显示"年龄不正确":

  3、在性能测试中老的方法是NSTimeInterval start = CACurrentMediaTime() 配合 NSLog(@"^^ --> %f

  在单元测试里用的是新方法!!!一定注意看我的 testPerformanceExample 部分的代码~这里系统会自动执行10遍我的 for 循环,并输出每一次的时间和平均时间(详见代码和下图)

  4、异步加载任务时候的单元测试用到了新方法:

  expectation-->预期 ;

  XCTestExpectation *expectation = [self expectationWithDescription:@"异步加载 Person"] ; //创建一个expectation 预期 ;

  [expectation fulfill] ;//标注预期完成 ;

  [self waitForExpectationsWithTimeout: 1.0f handler:^(NSError * _Nullable error) {

  }] ;//等待预期达成://我认为的认为 1.0f 秒之内预期达成我都认为是合理的。

  PersonTests.m 文件

  #import

  #import "Person.h"

  @interface PersonTests : XCTestCase

  @end

  @implementation PersonTests

  /**

  一次单元测试开始前的准备工作,可以设置全局变量:

  类似于:[[self alloc] init] ;

  */

  #pragma mark - setUp 设置

  - (void)setUp {

  [super setUp];

  // Put setup code here. This method is called before the invocation of each test method in the class.

  //  请在此处键入设置代码.这个方法将在本类中的每一个测试方法(以 test 开头的方法)之前被调用.

  }

  /**

  一次单元测试结束前的销毁工作:

  类似于 dealloc ;

  */

  #pragma mark - tearDown 销毁

  - (void)tearDown {

  [super tearDown];

  // Put teardown code here. This method is called after the invocation of each test method in the class.

  // 请在此处键入销毁代码.这个方法将在本类中的每一个测试方法以 test 开头的方法)之后被调用.

  }

  */

  #pragma mark - 测试 Person 模型

  - (void)testNewPerson {

  [self checkPersonWithDictionary:@{ @"name":@"zhangsan" , @"age":@26 }] ;

  [self checkPersonWithDictionary:@{ @"name":@"zhangsan" }] ;

  //空字典:

  [self checkPersonWithDictionary:@{}] ;

  [self checkPersonWithDictionary:@{ @"name":@"zhangsan" , @"age":@26 , @"title":@"leader" }] ;

  //非法年龄数据:

  [self checkPersonWithDictionary:@{ @"name":@"zhangsan" , @"age":@500 , @"title":@"leader" }] ;

  [self checkPersonWithDictionary:@{ @"name":@"zhangsan" , @"age":@-1 , @"title":@"leader" }] ;

  //至此,单元测试的工厂方法测试基本完成!

  }

  #pragma mark - 检测 Person 信息方法

  - (void)checkPersonWithDictionary:(NSDictionary *)dictionary {

  Person *person = [Person personWithDictionary:dictionary] ;

  NSLog(@"%@" , person) ;

  //获取字典信息:

  NSString *name = dictionary[@"name"] ;

  NSInteger age = [dictionary[@"age"] integerValue] ;

  //XCTAssert:断言 ;

  //1.检查名称:

  //如果 [name isEqualToString:person.name] 这个条件不满足那就显示"姓名不一致":

  XCTAssert([name isEqualToString:person.name] || person.name == nil , @"姓名不一致") ;

  //2.检查年龄:

  //如果 age == person.age 这个条件不满足,那就显示"年龄不正确":

  if (person.age > 0 && person.age

  XCTAssert(age == person.age , @"年龄不正确") ;

  } else {//如果年龄不符合条件那么我认为你的年龄为 0 ,否则年龄超限:

  XCTAssert(person.age == 0 , @"年龄超限") ;

  }

  }

  //Performance: 性能 ; 表现 ;

  /**

  1.相同的代码重复执行 10 次 , 统计计算时间以及平均时间 ;

  2.性能测试代码一旦写好 , 可以随时测试 ;

  注意:

  "要学会测量!不要猜测!" ---> 不要觉得代码怎么样~写得多就复杂?写得少就简单?测试一下!程序猿一定要用数据说话!

  */

  #pragma mark - testPerformanceExample 性能测试

  - (void)testPerformanceExample {

  // This is an example of a performance test case.

  // 这是一个性能测试的用例:

  [self measureBlock:^{

  // Put the code you want to measure the time of here.

  // 将需要测量执行时间的代码放在此处:

  NSTimeInterval start = CACurrentMediaTime() ;

  for (int i = 0; i

  [Person personWithDictionary:@{@"name":@"zhangsan" , @"age":@20}] ;

  }

  NSLog(@"^*^ --> %f

  }];

  }

... ...

 
推荐阅读

点击阅读☞写单元测试是个技术活

点击阅读☞写PHP代码,你搞过单元测试吗?

点击阅读☞谷歌安卓UI自动化测试策略

点击阅读☞先解决思想:为何要写单元测试?

点击阅读☞Android 单元测试那些事情

点击左下角“阅读原文”查看更多内容!