当前位置: 首页 > news >正文

iOS Framework 单元测试(一)-- XCTests

写在前面

单元测试的重要性,不言而喻,在迭代开发 Framework 的过程中,好的单元测试,能及早发现问题。

关于 iOS Framework 的单元测试,常见的工具,当属官方提供的 XCTests,但它也有些局限,所以笔者写了个小工具,对其进行补充。

本文会简单介绍 XCTests 的使用。

创建工程

新建一个 SDKDemo 工程,记得勾上 Include Unit Tests

生成工程如图,会有一个SDKDemoTests的 Target 和相应的目录

新建 NetworkRequest,作为测试对象,代码如下:

@interface NetworkRequest : NSObject
- (BOOL)configure;
@end

@implementation NetworkRequest
- (BOOL)configure {
    return YES;
}
@end
复制代码

使用 XCTests 进行单元测试

在新建模板里选择 Unit Tests Case Class,创建 NetworkRequestTests 如图:

添加代码:

#import <XCTest/XCTest.h>
#import "NetworkRequest.h"

@interface NetworkRequestTests : XCTestCase
@property (nonatomic, strong) NetworkRequest *request;
@end

@implementation NetworkRequestTests

- (void)setUp {
    [super setUp];
    // Put setup code here. This method is called before the invocation of each test method in the class.
    self.request = [NetworkRequest new];
}

- (void)tearDown {
    // Put teardown code here. This method is called after the invocation of each test method in the class.
    [super tearDown];
}

- (void)testExample {
    // This is an example of a functional test case.
    // Use XCTAssert and related functions to verify your tests produce the correct results.
}

- (void)testPerformanceExample {
    // This is an example of a performance test case.
    [self measureBlock:^{
        // Put the code you want to measure the time of here.
    }];
}
// 添加的测试方法
- (void)testConfigure {
    XCTAssertTrue([self.request configure]);
}
@end
复制代码

对于每个 test 开头的方法,Xcode 会在其左边显示一个圆点,点一下它,就可以运行这个测试方法,使用快捷键 command+u 会执行所有测试。

同时 XCTests 提供许多断言,如上面使用的 XCTAssertTrue。

当断言成立时,圆点会显示为绿色,否则为红色。

若有 Block,如何测试?

在 NetworkRequest 中添加代码:


@interface NetworkRequest : NSObject
- (void)loginWithCompletionHandler:(void (^)(BOOL success))handler;
@end

@implementation NetworkRequest
- (BOOL)configure {
    return YES;
}
- (void)loginWithCompletionHandler:(void (^)(BOOL))handler {
    NSLog(@"Begin login");
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        handler(YES);
    });
}
@end
复制代码

对于 Block 的测试,得使用 XCTestExpectation,并且在 Block 里调用 fullfill 方法。否则测试不会等到 Block 执行,就直接退出。

测试代码:

@implementation NetworkRequestTests
- (void)testLogin {
    // 声明一个 XCTestExpectation 对象
    XCTestExpectation *expectation = [[XCTestExpectation alloc] initWithDescription:@"login expectation"];
    [self.request loginWithCompletionHandler:^(BOOL success) {
        XCTAssertTrue(success);
        // 调用 fullfill,告知 XCTestExpectation 已出现
        [expectation fulfill];
    }];
    // 等待 XCTestExpectation
    [self waitForExpectationsWithTimeout:5 handler:nil];
}
@end
复制代码

代码覆盖率

默认没有打开,可以编辑 Test Scheme,如图,勾选该功能

再次运行测试,然后如图,查看结果

如何在单元测试中引用 Framework?

在开发 Framework 过程中,典型场景就是 A 引用了 B,对 A 进行测试时,正如下文所说的

Because unit test targets are missing the Linked Frameworks and Libraries section in their General settings tab, you must instead drag the built frameworks to the Link Binaries With Libraries build phase.

这种情况下,无法进行测试,这也是笔者一开始想要对 XCTests 进行补充的初衷。

但后来发现

In the Test target under the Build Settings tab, add @loader_path/Frameworks to the Runpath Search Paths if it isn't already present.

还是有解决方案的。

扩展

XCTests 作为官方提供的测试方法,上手简单,十分适合用来做单元测试。

美中不足的是,XCTests 不支持真机测试,所以有些功能无法测试,也无法在真机上测试性能。

这种情况下,又该如何处理,请看《iOS Framework 单元测试(二)-- JDAppTests(XCTests的补充)》

参考资料

Apple Developer

Carthage

转载于:https://juejin.im/post/5ad75d64f265da504c16893a

相关文章:

  • 会话技术
  • java基础-Integer类常用方法介绍
  • linux下的小命令
  • 如何快速成为数据分析师(个人角度)
  • 长三角G60科创走廊智能驾驶产业联盟揭牌成立,近80家企业助力智能驾驶行业发展 ...
  • 用js来实现那些数据结构09(集合01-集合的实现)
  • Jfianl框架定时器使用配置
  • springmvc controller junit 测试
  • 第七周
  • Android 视频解析MediaExtractor
  • vs2012 快捷键
  • [数据结构]链表的实现在PHP中
  • PostgreSQL 快速给指定表每个字段创建索引 - 1
  • 玻璃手机后壳或将成为主流,荣耀专注三年极光玻璃 获赞有眼光!
  • 《数据结构与算法》-3-栈和队列
  • 【5+】跨webview多页面 触发事件(二)
  • 【个人向】《HTTP图解》阅后小结
  • 0基础学习移动端适配
  • AzureCon上微软宣布了哪些容器相关的重磅消息
  • HTML5新特性总结
  • HTTP 简介
  • Mysql数据库的条件查询语句
  • MySQL用户中的%到底包不包括localhost?
  • Spring框架之我见(三)——IOC、AOP
  • Traffic-Sign Detection and Classification in the Wild 论文笔记
  • 从0到1:PostCSS 插件开发最佳实践
  • 理解在java “”i=i++;”所发生的事情
  • 微信支付JSAPI,实测!终极方案
  • CMake 入门1/5:基于阿里云 ECS搭建体验环境
  • 曜石科技宣布获得千万级天使轮投资,全方面布局电竞产业链 ...
  • ​Python 3 新特性:类型注解
  • ​无人机石油管道巡检方案新亮点:灵活准确又高效
  • ​一些不规范的GTID使用场景
  • #define用法
  • (10)STL算法之搜索(二) 二分查找
  • (HAL库版)freeRTOS移植STMF103
  • (pytorch进阶之路)扩散概率模型
  • (Redis使用系列) Springboot 在redis中使用BloomFilter布隆过滤器机制 六
  • (附源码)ssm户外用品商城 毕业设计 112346
  • (强烈推荐)移动端音视频从零到上手(上)
  • **Java有哪些悲观锁的实现_乐观锁、悲观锁、Redis分布式锁和Zookeeper分布式锁的实现以及流程原理...
  • .NET Core WebAPI中封装Swagger配置
  • .net mvc 获取url中controller和action
  • .NET 的程序集加载上下文
  • .NET 反射 Reflect
  • .NET 分布式技术比较
  • .Net的C#语言取月份数值对应的MonthName值
  • .NET企业级应用架构设计系列之结尾篇
  • @Bean注解详解
  • [ C++ ] STL---string类的使用指南
  • [ vulhub漏洞复现篇 ] JBOSS AS 5.x/6.x反序列化远程代码执行漏洞CVE-2017-12149
  • [AutoSar]BSW_Com07 CAN报文接收流程的函数调用
  • [C++进阶篇]STL中vector的使用
  • [caffe(二)]Python加载训练caffe模型并进行测试1
  • [Electron] 将应用打包成供Ubuntu、Debian平台下安装的deb包