一、单元测试
单元测试是一种通过代码检测代码的开发手段,常用于“敏捷开发”和“测试驱动开发”
测试驱动开发是:红灯(有错误)/ 绿灯(无错误)式的迭代开发!代码检测通常是需要(预先/预想)设置边界条件,因为UI测试的时候,很多边界条件不容易满足
单元测试主要针对“业务逻辑”代码进行测试!不适合做UI(ViewController)的测试!
1、单元测试的简单使用
创建项目时,勾选“单元测试文件”
创建一个Person模型
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property (nonatomic, copy)NSString *name;
@property (nonatomic, assign)NSInteger age;
@property (nonatomic, assign)NSInteger height;
+ (instancetype)persionWithDict:(NSDictionary *)dict;
@end
#import "Person.h"
@implementation Person
+ (instancetype)persionWithDict:(NSDictionary *)dict{
Person *obj = [[self alloc] init];
[obj setValuesForKeysWithDictionary:dict];
obj.age++; //单元测试该方法是否正确
return obj;
}
- (void)setValue:(id)value forUndefinedKey:(NSString *)key{
}
@end
创建Person类对应的单元测试文件
在Person类对应的单元测试文件中写测试代码
/*
1、单元测试是以代码测试代码
2、红灯/绿灯迭代开发
3、在日常开发中,数据大部分来自于网络,很难出现“所有的”边界数据(如果没有测试所有的数据就上架,在运行时造成闪退!)
4、单元测试不是用NSLog测试,而是使用‘断言’来测试的。断言:提前预判条件必须满足
*/
//测试新建的Person模型,测试方法必需以'test'开头
/* 注意:
1、不是所有的方法都需要测试
暴露在.h中的方法需要测试,私有方法不需要测试,面向对象的“开闭原则”
2、所有跟UI有关的都不需要测试
*/
- (void)testNewPerson {
//自己建立测试使用的数据,检查边界数据
[self checkPersionWithDict:@{@"name":@"zhangsan", @"age":@18, @"height":@185}];
[self checkPersionWithDict:@{@"name":@"zhangsan", @"height":@185}];
[self checkPersionWithDict:@{@"age":@18, @"height":@185}];
}
//根据字典检查新建的Person信息
- (void)checkPersionWithDict:(NSDictionary *)dict {
Person *per = [Person persionWithDict:dict];
//获取字典信息
NSString *name = dict[@"name"];
NSInteger age = [dict[@"age"] integerValue];
//通过断言检查名称
XCTAssert([name isEqualToString:per.name] || per.name == nil, @"姓名不一致");
XCTAssert(age == per.age, @"年龄不一致");
}
“断言”测试的结果
2、性能测试
有两种方式:1、时间差值;2、单元测试的性能测试方法中测试
3、单元测试测试异步
在Person类中创建一个异步方法,然后在单元测试中测试该方法的性能
+ (void)loadPersionAsync:(void (^)(Person *person))completion{
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[NSThread sleepForTimeInterval:1.0];
Person *per = [Person persionWithDict:@{@"name":@"zhangsan", @"age":@18}];
dispatch_async(dispatch_get_main_queue(), ^{
if (completion == nil) {
completion(per);
}
});
});
}
在PersonTests.m单元测试方法中,测试Person类的异步方法性能
//ios的单元测试是串行的,中间不会等待异步回调的完成。
//测试异步加载Persion
- (void)testLoadPersonAsync {
//通过XCTestExpectation:“预期”来解决异步测试
XCTestExpectation *expectation = [self expectationWithDescription:@"测试异步加载person"];
[Person loadPersionAsync:^(Person *person) {
NSLog(@"%@", person.name);
//标注预期达成
[expectation fulfill];
}];
//等待预期异步执行完,若在10秒内完成,则认为正常
[self waitForExpectationsWithTimeout:10.0 handler:nil];
}
测试覆盖率,有很多人会讨论到底多少代码应该测试:
需要针对业务逻辑的对外开发的函数重点测试!如果有“局部复杂”的业务逻辑小函数,可以临时测试!
通常公司的代码测试覆盖率从50% ~ 70%不等
Xcode的单元测试,还能够做性能测试
Xcode可以利用性能测试,对某一段代码,重复测试10次!
为什么很多公司讨厌单元测试,因为其代码的覆盖率不好确认。
二、UI测试
1、创建项目时勾选UI测试
注:所有view都要设置颜色,否则在跳转时会闪一下
2、开始UI测试
三、猴子测试
测试程序的抗压性,模拟在屏幕上自动点击,进行自动化测试
https://github.com/jonathanpenn/ui-auto-monkey
使用方法:
1.选择Instrument中的Automation,清空里面的js代码。
2.把 UI AutoMonkey 中的 UIAutoMonkey.js 文件里面的400多行js代码拷贝,粘贴到Automation里面。(或者直接拷贝下面的js代码)
3.点击左上角的红色按钮运行,模拟器就开始工作了,可以看到屏幕自动出现快速乱点的效果。