1 单元测试重要吗?
重要!单元测试的重要性,不言而喻,在迭代开发Framework 的过程中,好的单元测试,能及早发现问题。
WWDC上是这样解释的
Why Test?
• Catch crashes
• Catch logic errors
• Help you write your code
• Catch regressions
• Cover more configurations • Cover everyone, all the time
SDWebImage的单元测试覆盖率
SDWebImage.png 测试类
对于测试用例覆盖度多少合适这个话题,也是仁者见仁智者见智,其实一个软件覆盖度在50%以上就可以称为一个健壮的软件了。自己通过写测试用例能很好的反应问题,极大程度的避免了通过‘人肉’测试发现问题。
2 持续集成的工作流程
持续集成的工作流程.png3.开始测试
3.1 一般方法
+ (void)setUp {
[super setUp];
NSLog(@"i am a setup");
}
+ (void)tearDown {
[super tearDown];
NSLog(@"I am a terDown");
}
- (void)setUp {
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
//重置一个对象。初始化
}
- (void)tearDown {
// Put teardown code here. This method is called after the invocation of each test method in the class.
// 置空
[super tearDown];
}
- (void)testAddMethod {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
//单元测试的基本结构 BBD 三段式
//1. Given 测试的条件
int numberA = 1;
int numberB = 2;
//2. When 进行测试
int result = [self add:numberA with:numberB];
//3. Then 测试结果判断
XCTAssertEqual(result, 3);
//小结:1.测试三段式结构 Given When Then
// 2. 方法开头要用test开头
}
//测试方法
- (int )add:(int )numberA with:(int )numberB {
return numberA + numberB;
}
3.2 自定义类测试方法
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@protocol PersonDelegate <NSObject>
- (NSString *)becomeSuperMan;
@end
@interface Person : NSObject
@property (nonatomic, weak) id<PersonDelegate> delegate;
- (int)calculateNumberOne:(int)numberA NumberTwo:(int)numberB;
- (NSString *)tellOthersName;
- (UIImageView *)getMyPhotoView;
- (void)doSomeTasksAsynchronous:(void(^)(NSString *doneInfo)) doneBlock;
@end
#import "Person.h"
@implementation Person
- (int)calculateNumberOne:(int)numberA NumberTwo:(int)numberB {
return numberA + numberB;
}
- (NSString *)tellOthersName {
return @"my name is Adolf";
}
- (UIImageView *)getMyPhotoView {
UIImageView *photoView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"001" inBundle:[NSBundle mainBundle] compatibleWithTraitCollection:nil]];
return photoView;
}
//模拟网络请求一个过程。
- (void)doSomeTasksAsynchronous:(void (^)(NSString *))doneBlock {
//主线程
NSLog(@"the mian thread is :%@", [NSThread currentThread]);
//Submits a block for asynchronous execution on a dispatch queue and returns immediately.
//接受一个block在一个派发队列里面异步执行,执行完毕,立刻返回!注意,这里要填写main queue!,返回的时候才是在主队列
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(globalQueue , ^{
NSLog(@"I am executing in main queue via Asynchronous : %@", [NSThread currentThread]);
[NSThread sleepForTimeInterval:3];
NSString *tagString = @"finished task Asynchronous";
//异步方式,回到主线程,进行回调 【这里的block为什么可以直接获取变量?】
dispatch_async(dispatch_get_main_queue(), ^{
doneBlock(tagString);
});
});
}
@end
#import <XCTest/XCTest.h>
#import "Person.h"
@interface PersonTests : XCTestCase
@end
@implementation PersonTests
- (void)setUp {
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
}
- (void)tearDown {
// Put teardown code here. This method is called after the invocation of each test method in the class.
[super tearDown];
}
- (void)testCalculate {
// 1. Given
Person *p = [Person new];
// 2. When
int result = [p calculateNumberOne:9 NumberTwo:8];
// 3. Then
XCTAssertEqual(result, 17);
}
- (void)testExample {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
//1. 简单测试
//三段式: 1. Given 2.When 3.Then
Person *p = [Person new]; // 1.Given
NSString *nameString = [p tellOthersName]; //2. When
// XCTAssertEqual(nameString, @"my name is Adolf");
XCTAssertNotNil([p tellOthersName]); //3. Then
//
//2. 加载bundle资源时需要注意一个点,通过 bundleForClass 来进行加载!
XCTAssertTrue([[p getMyPhotoView] isMemberOfClass:[UIImageView class]]);
NSBundle *bundle = [NSBundle bundleForClass:[PersonTests class]];
NSBundle *main = [NSBundle mainBundle];
NSLog(@"%@ ============ %@", bundle, main);
}
//3.异步测试里面可能会包含 通知、block、代理等 回调方式
- (void)testAsynchronousBlock {
//测试异步加载步骤:
//3.1创建一个异步测试异常
// 1. Given
XCTestExpectation * asyncTestExpec = [self expectationWithDescription:@"Asynchronous testing have done"];
//3.2创建对象并且调用方法
Person *p = [Person new];
//2.When
[p doSomeTasksAsynchronous:^(NSString *doneInfo) {
//3.3 测试是否 "按时" 回调成功
[asyncTestExpec fulfill];
//3.4测试回调的结果是否正确
//. Then
XCTAssertEqualObjects(@"finished task Asynchronous", doneInfo);
}];
//3.5 设定时间
[self waitForExpectationsWithTimeout:5 handler:^(NSError * _Nullable error) {
NSLog(@"successful");
}];
}
//3.6 代理
- (void)testAsynchronousWithDelegate {
Person *p = [Person new];
// p.delegate = self;
// if (p.delegate) { //测试里面尽量不要有判断
// }
// XCTAssertNotNil([p.delegate becomeSuperMan]);
}
- (NSString *)becomeSuperMan {
[NSThread sleepForTimeInterval:2];
return @"I am a sleep super man";
}
- (void)testPerformanceExample {
[self measureBlock:^{
//性能测试
[self testAsynchronousBlock];
}];
}
@end
UI测试成本和回报相差太大就不进行讲解了 可以看下面资料
网友评论