iOS单元测试(作用及入门提升)

作者: RasonWu | 来源:发表于2015-12-25 20:10 被阅读51007次

    由于只是一些简单实用的东西,学学还是挺不错的。其实单元测试用的好,开发起来也会快很多。单元测试对于我目前来说,就是为了方便测试一些功能是否正常运行,还有调试接口是否能正常使用。有时候你可能是为了测试某一个网络接口,然后每次都重新启动并且经过很多操作之后才测试到了那个网络接口。如果使用了单元测试,就可以直接测试那个方法,相对方便很多。 比如由于修改较多,我们想测试一下分享功能是否正常,这时候就有用了。(而不是重新启动程序,进入到分享界面,点击分享,填写分享内容。)其实单元测试并没有降低我们打代码的效率,我们可以在单元测试通过了,直接用到相应的地方。
    当然也有一些高级的作用,比如自动发布、自动测试(特别在一些大的项目,以防止程序被误改或引起新的问题)。
    现在,让我们先理清一下单元测试到底有些什么东西?
    OCUnit即用XCTest进行测试)其实就是苹果自带的测试框架,我们主要讲的就是这个。GHUnit是一个可视化的测试框架。(有了它,你可以点击APP来决定测试哪个方法,并且可以点击查看测试结果等。)OCMock就是模拟某个方法或者属性的返回值,你可能会疑惑为什么要这样做?使用用模型生成的模型对象,再传进去不就可以了?答案是可以的,但是有特殊的情况。比如你测试的是方法A,方法A里面调用到了方法B,而且方法B是有参数传入,但又不是方法A所提供。这时候,你可以使用OCMock来模拟方法B返回的值。(在不影响测试的情况下,就可以这样去模拟。)除了这些,在没有网络的情况下,也可以通过OCMock模拟返回的数据。UITests就是通过代码化来实现自动点击界面,输入文字等功能。靠人工操作的方式来覆盖所有测试用例是非常困难的,尤其是加入新功能以后,旧的功能也要重新测试一遍,这导致了测试需要花非常多的时间来进行回归测试,这里产生了大量重复的工作,而这些重复的工作有些是可以自动完成的,这时候UITests就可以帮助解决这个问题了。

    最简单的单元测试

    1.新建项目:

    18CA997F-4911-4B99-9A83-2AB44A77E8E8.png
    2.最简单的测试,注意截图路径的问题
    进入到这个类,setUp是每个测试方法调用执行,tearDown是每个测试方法调用执行。testExample是测试方法,和我们新建的没有差别。不过测试方法必须testXXX的格式,且不能有参数,不然不会识别为测试方法。测试方法的执行顺序是字典序排序。
    按快捷键Command + U进行单元测试,这个快捷键是全部测试。
    testExample方法中输入
        NSLog(@"自定义测试testExample");
        int  a= 3;
        XCTAssertTrue(a == 0,"a 不能等于 0");
    

    点击播放按钮,开始单个方法的测试:

    8F503AA4-C630-419A-9F66-C779C81A5581.png

    出现如下结果,由于我们断言a是等于0的,而a等于3,所以测试没有通过。当然有其它的,用到再看,demo里都有。


    图片.png
    进行网络请求的测试

    使用CocoaPods安装AFNetworking和STAlertView(CocoaPods安装和使用教程
    Pofile:

    platform :ios, '7.0'
    target 'UnitTestDemoTests' do
        pod 'AFNetworking', '~> 2.5.0'
        pod 'STAlertView', '~> 1.0.0'
    end
    target 'UnitTestDemoTestsTests' do
        pod 'AFNetworking', '~> 2.5.0'
        pod 'STAlertView', '~> 1.0.0'
    end
    

    iOS9的http安全问题:现在进行异步请求的网络测试,由于测试方法主线程执行完就会结束,所以需要设置一下,否则没法查看异步返回结果。在方法结束前设置等待,调回回来的时候再让它继续执行。(另一种异步函数的单元测试)定义宏如下:

    //waitForExpectationsWithTimeout是等待时间,超过了就不再等待往下执行。
    #define WAIT do {\
    [self expectationForNotification:@"RSBaseTest" object:nil handler:nil];\
    [self waitForExpectationsWithTimeout:30 handler:nil];\
    } while (0);
    
    #define NOTIFY \
    [[NSNotificationCenter defaultCenter]postNotificationName:@"RSBaseTest" object:nil];
    

    增加测试方法testRequest:

    -(void)testRequest{
        // 1.获得请求管理者
        AFHTTPRequestOperationManager *mgr = [AFHTTPRequestOperationManager manager];
        mgr.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/html",nil];
        
        // 2.发送GET请求
        [mgr GET:@"http://www.weather.com.cn/adat/sk/101110101.html" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
            NSLog(@"responseObject:%@",responseObject);
            XCTAssertNotNil(responseObject, @"返回出错");
            NOTIFY //继续执行
        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
            NSLog(@"error:%@",error);
            XCTAssertNil(error, @"请求出错");
            NOTIFY //继续执行
        }];
        WAIT  //暂停
    }
    

    有时候我们想测试一下整个流程是否可以跑通,比如获取验证码、登录、上传头像,查询个人资料。其实只要输入验证码就可以完成整个测试。这时候就需要用到输入框了,以便程序继续执行。使用了一个第三方的弹出输入框STAlertView,前面已经设置。
    STAlertView的使用方法:

            self.stAlertView = [[STAlertView alloc]initWithTitle:@"验证码" message:nil textFieldHint:@"请输入手机验证码" textFieldValue:nil cancelButtonTitle:@"取消" otherButtonTitle:@"确定" cancelButtonBlock:^{
                //点击取消返回后执行
                [self testAlertViewCancel];
                NOTIFY //继续执行
            } otherButtonBlock:^(NSString *b) {
                //点击确定后执行
                [self alertViewComfirm:b];
                 NOTIFY //继续执行
            }];
            [self.stAlertView show];
    
    • 高级自动化单元测试,推荐看LeanCloud 工程师的李智维的自动化单元测试的直播录影
    • 李智维的演示github
      其实讲得非常不错,自动化单元测试,自动化发布都有讲到,不过由于自己的功力不够,只能留着以后慢慢学习。

    演示Demo下载:UnitTestDemoTests

    相关文章

      网友评论

      • b4067f4d3883:你好,请问我在写测试方法的时候,一些NSLog信息没有打印出来,怎么让测试代码中的NSLog打印出来?
        RasonWu:这种一般是被设置了屏蔽,比如 https://www.jianshu.com/p/f199e0887b3a 。又或者被宏定义修改了打印。
      • 小石头JS:大牛你好,想问一下,每个模块的单元测试都需要新建一个基于XCTestCase的测试文件吗?刚接触这个,有好多疑问:flushed:
        小石头JS:@RasonWu 如果是整个项目的单元测试呢?要写的测试文件会很庞大啊,看了一些讲单元测试的文章,感觉云里雾里的,还是要实际上手多练才行~~
        RasonWu:其实这种没有明确的答案,一般都是一个模块一个模块来新建测试文件,如果一个模块测试东西太多,可以进一步分块。原则还是清晰易懂。
      • 男儿心:问下,这个alert怎么显示出来啊?
        麦穗0615:@RasonWu wait
        男儿心:@RasonWu 你说的手动等待是设置sleep么
        RasonWu:用了STAlertView,但是测试里面必须手动设置等待,不然执行完就结束了,就会看不到有停留。
      • Aili_00:你好,现在用swift写的工程,点击某个测试方法的播放按钮,预期只测试这一个方法,实际结果是所有测试方法都执行了,有什么办法每次只测试一个方法
      • iOS小丸子:你好,我根据你 demo,在xcode8 运行,出现以下报错,麻烦看看
        dyld: could not load inserted library '/private/var/containers/Bundle/Application/39D6924A-FAAC-48DF-9B88-802A4FA3BB23/ios单元测试.app/Frameworks/IDEBundleInjection.framework/IDEBundleInjection' because no suitable image found.


        RasonWu:@Gree小丸子 增加一个target看看,我也更新了demo。xcode版本的升级也产生了一些新的问题。Podfile修改一下,修改成类似下面的。
        platform :ios, '7.0'
        target 'UnitTestDemoTests' do
        pod 'AFNetworking', '~> 2.5.0'
        pod 'STAlertView', '~> 1.0.0'
        end
        target 'UnitTestDemoTestsTests' do
        pod 'AFNetworking', '~> 2.5.0'
        pod 'STAlertView', '~> 1.0.0'
        end
      • risk: @RasonWu 我们现在接口都是测试做的自动化测试,不用我们写,我们想写些view和逻辑的单元测试,请问有什么好的事例么?
        risk:@RasonWu 好的。
        RasonWu:@risk超 没有哦。这些也是自己另外学的,公司现在都用不到。
      • AlwaysBlue:你好 现在我遇到了一个问题,由于工程是混编,在UnitTest中,基础工程我是创建的OC的然后需要引入Swift文件,在Swift文件中有用到OC的数据类型,比如CGFloat等,就会报错,说识别不了 这个要如何解决呢
      • Orange橙橙:正在学习ing。。。
      • 酱油不爱醋:我想知道,做网络请求测试的时候,比如某个接口,需要登录之后才能使用,那么这个时候该怎么做测试比较好
        酱油不爱醋:@RasonWu 3q,发现setUp方法会在测试方法跑之前先执行,应该可以用这个
        RasonWu:@酱油不爱醋 如果要加测试方法的话,你可以让它跑账号登录的接口,成功后再调用这个接口。如果用到cookies保存用户登录状态的话,可以登录之后保存对应的cookies。若是通过登录之后的返回信息记录登录状态,您也可以选择保存登录信息到本地。
      • c6e16b2e3a16:看了文章很受用,请教个问题:测试的方法都是公开在.h文件的公开方法,那么如何测试私有方法和私有属性呢?
        小木头:@hello_me 没必要测试私有方法,如果要调用的话,在测试类里面写个category
      • iOS_愛OS:特从公共号过来评价
        49552b6e05d2:@RasonWu 大神 你的公众号是多少啊?我也想关注一下。😁
        49552b6e05d2:@iOS_愛OS 公众号在哪?我也想关注一下 :grin:
        RasonWu:@iOS_愛OS 谢谢,不过最近都比较忙。很多不总结,感觉又忘了。
      • 服了梨:非常感谢这样的文章
      • 三粒黑子球:收藏喽~
      • e2b8faf69d17:😂……曾经学过,然而我并没有听懂老师在说什么
      • shuai1234:正搞不懂单元测试了
      • 郑钦洪_:生哥屌!
      • 煜寒了:赞一个不错

      本文标题:iOS单元测试(作用及入门提升)

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