美文网首页
iOS单元测试

iOS单元测试

作者: spades_K | 来源:发表于2018-05-02 17:33 被阅读7次
    软件测试

    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 持续集成的工作流程

    持续集成的工作流程.png

    3.开始测试

    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测试成本和回报相差太大就不进行讲解了 可以看下面资料

    XCTest基本用法
    单元测试UI测试

    相关文章

      网友评论

          本文标题:iOS单元测试

          本文链接:https://www.haomeiwen.com/subject/rduglftx.html