首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Mac UT实践小结

Mac UT实践小结

作者头像
腾讯移动品质中心TMQ
发布2019-06-25 16:10:14
8900
发布2019-06-25 16:10:14
举报

开发UT实现:朱浩禹

测试UT实现:韩小晴、余轶斐

FT其他参与者:陈智、熊琦楠

(名字均按首字母排序)

一、为何要做单元测试?

腾讯视频Mac项目研发质量较高,为了进一步提高代码质量,增强代码健壮性,从根源最早发现问题并及时解决,单元测试是个值得去实践的方向。

二、单元测试SDK选型

本次将范围锁定在Mac腾讯视频开源库XXXOpenSource,相比主工程,XXXOpenSource的优势在于

1)开源库工程,包含了所有腾讯视频依赖的第三方开源组件工程和源代码;

2)无依赖关系,不像mainProject相互依赖关系复杂;

3)独立编译,以framework形式存在。

本次选用XXXOpenSource里的pluginKit从开发侧做UI,弹幕SDK从测试侧做UT。

三、开发侧单元测试实践——PluginKit

开发UT最初问题:

1)覆盖率不全,缺少message相关ut case;

2)异常处理不足,只有通用参数的校验。

通过增加case和异常逻辑校验,最终覆盖率提升到80.3%:

四、测试侧UT

OC 单元测试整体流程梳理如下:

step 1)定义测试范围:

选型:本次测试侧做的单元测试选用了Mac腾讯视频项目里用到的一个独立的弹幕SDK进行单元测试,采用基于XCTest的测试框架。

选型原因:弹幕SDK 是一个灵活,轻量级的弹幕渲染库,是个独立的组件,和庞大的腾讯视频主工程没有依赖关系。

step 2)编写测试类和方法:

测试用例编写三部曲:

根据上面对代码的分析,有两个负责控制的类,一个主要对外提供接口,一个控制完成主逻辑。测试用例的编写先从这两个控制类入手,对公有函数设计测试case。

case举例:

1、danmuView:一条弹幕所在view ,check frame & origin 具体校验点如下:

1)高度:固定值

2)X坐标:小于canvasViewWidth

3)Y坐标:屏幕内

根据这三个校验点,写出对应的单测用例:

2、特殊弹幕时(如emoji表情,挂件),danmuView的状态 frame origin

构造特殊弹幕,针对上面三个检查点再进行一次检查。特殊弹幕举例:

3、检查activedHolders (当前活跃弹幕):

activedHolders 是字典类型,它的key是NSString类型,value是由Holder类型组成的数组,此数组和当前活跃弹幕一一对应。从activedHolders中获取当前正在活跃的弹幕view,对view的属性进行校验。

4、弹幕速度异常校验给弹幕速度设置正常值和异常值,在这两种情况下校验弹幕view的有效性。

五、过程问题与解决方案

1、如何更好的阅读开发代码

通过梳理调用关系,画出UML类图,便于理清代码结构和继承关系,理清思路。

2、如何选择testcase编写入手点

首先查看工程的对外接口public函数,再找到代码的核心控制类,从此类的接口函数入手。

3、测试覆盖率的提升:50%-75.7%-76.5%

本单测覆盖率的瓶颈在于:

1)UI操作 比如鼠标操作和单击、双击事件;

2)私有函数。

最初对外接口函数设计的用例检查只有50%的覆盖率,通过逐个分析没调用到的函数和语句,构造调用场景,将覆盖率提升到75.7%,最后继续深挖,构造分支条件,提高分支覆盖和条件覆盖 ,把整体覆盖率提升到76.5%。

4、设计case中的难点:解决单线程,没有回调和通知:加定时器

manager初始化设置定时刷新(1s 60次),每次刷新后触发回调:

控制类中触发更新:

需要针对刷新后的弹幕进行校验,但是由于初始化是单线程,定时器刷新后的结果在原代码里没有回调和通知,初始后就像脱缰的野马,线程内之前获得只能得到初始化时候的弹幕状态。

解决方法:

用例中加入定时器,3s后通过定时器调用一个新函数timerPoll,在新函数里完成检查。

设置总时间10s,10s后在当前线程结束runloop

5、设计case中的难点:多条case同时用NSTimer定时器会发生crash

多条TestCase中都启用了NSTimer定时器,在指定的时间内重复调用以实现循环生成danmu的逻辑,但各TestCase执行完循环任务后timer未释放掉,测试代码造成了必现崩溃。

timer不能同时重复调用,如果在不同case里都启用NSTimer,必须在各自case及时释放。

6、SDK本身需求不明确,UT发现的问题不好界定

明显的边界问题认为是bug,其他的异常处理不当认为是优化点,均可以通过单测运行结果进行判断。

六、发现的问题

【问题1】 speed为负数时,X坐标范围出现报错:

 XCTAssertTrue(danmuViewFrame.origin.x < CanvasViewWidth);——Fail

调试后发现danmuViewFrame.origin.x远超过canvasViewWidth 。

【原因】下图框内需要传入时间参数,应为非负数,但当speed为负数时,参数整体为负。

【解决】开发需要对speed参数进行合法校验

【问题2】codereview的问题:

NSMutableDictionary中的元素赋值:

对于NSMutableDictionary要使用原生函数-setObject:forKey:而不是KVC-setValue:forKey 。它们的区别是,

setObject: forkey: 中 object 是不能够为 nil 的,不然会报错。setValue:的value可以为nil。

【解决】更推荐写 [dictionary setObject:holderArray forKey:identifier];

【问题3】函数可测性差,控制类接口函数很多返回空值,无法做有效校验

七、可测性的提升

通过本次的单元测试尝试,发现不是所有的代码都可以做单元测试,本次单测覆盖率的瓶颈之一——UI操作无法覆盖,这种是不适合做UT的。

另外,开发代码需要有足够的可测性,函数返回值要能够校验,且需要更清晰的代码架构和优美的设计模式,来提升可测性,要设计更严谨的接口函数,便于进行校验和有效断言。

后期我们会根据每个维度陆续写相关的测试文章,如果你有兴趣,请关注我们哦。

长按指纹识别图中的二维码,获取更多测试干货分享!

 将我们公众号置顶 

 不会漏掉我们的原创干货哦!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-06-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 腾讯移动品质中心TMQ 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档