写点什么

最佳实践 | 单元测试 + 回归测试在 SRS 代码提交中的实践总结

发布于: 1 小时前

为了解决 SRS WebRTC 推流, 转 RTMP 后音视频时间戳不同步, 导致的后续 HLS 切片,FLV/RTMP 播放音画不同步等问题,我提交了一个 PR:https://github.com/ossrs/srs/pull/2470


其实就是依赖 SenderReport 来同步 RTP 时间戳和绝对时间戳。做完了以后,简单的跑了下, 发现输出符合预期, 就满心欢喜的提交了 PR, 等待合并。


最先 review 代码的是 SRS 技术委员会的进学, 他提出了一个问题:“如果 Sender Report 乱序了,计算出来的时间戳是对的吗?”因为我测试的时候偶现过这种场景, 我信心满满的回复, ”没问题, 我测过“, 一番讨论后, review 就通过了。


这时候成立冷不丁来了一句:“能用单元测试覆盖吗?”虽然知道单元测试的重要性, 但因为懒惰, 没有尝到甜头等原因, 我一直都不愿意去多做单元测试, 总觉得差不多就得了。但是在当时的场景下, 催生了我的好胜心,就像当年大师兄和我说的差不多, 得把代码搞出来才算。


一不做二不休, 我就开始着手写单元测试, 顺便再补充个回归测试, 干活就要干全套, 不然就白干了!大概花了几天的时候系统的学习了 GTEST 和 GMOCK 以后, 我就把单元测试写完了, 我心想这事情也没有想象中的难嘛,完全是个脏活累活, 不就是构造一些参数, 逐个函数验证嘛。


跑起来以后, 屏幕上出现了大大的红字“TEST FAILED”,当初提交 PR 时候的自信立马就被现实啪啪打脸。



重复跑了几次, 发现错误又没了, 意识到这是一个偶现的 BUG, 打上日志,反复跑了几次后, 捕捉到了想要的错误。对照着单元测试的错误,我修复了几个非常细节的代码错误。具体如下:



补上一个 NTP 的单元测试, 确认了之前的问题:




通过 demo 程序进行验证:



打开 IETF 浮点数在线解释的页面

https://www.h-schmidt.net/FloatConverter/IEEE754.html 进行分析:



到这里基本就知道怎么改了, 加一个 round 函数, 四舍五入, 问题迎刃而解。



改完重新跑测试, 通过!



经过这一次实践, 单元测试给我带来的体会是:

  1. 以后再怎么改代码, 跑一遍单元测试, 起码能让人安心, 知道这一次修改的代码没有基本的函数级别的错误;

  2. 试想一下如果没有用单元测试发现这几处细微的代码错误, 合并到 4.0released 后, 最终问题还是会变成 ISSUE 回来, 而且更隐晦, 更难排查。从长远看, 单元测试节省了开发者的时间。


搞完了单元测试,接下来就是搞回归测试。

为什么需要回归测试,通俗的说, 只保证了单元的正确性, 但是多个正确的单元有可能错误的结合, 所以我们需要回归测试, 来保证业务逻辑代码的正确性。


SRS 里面是怎么做的

https://github.com/ossrs/srs/tree/4.0release/trunk/3rdparty/srs-bench/srs 这个目录下, 提供了压测工具和单元测试工具。


原理也很简单, 用 GO 自带的 TEST, 结合 GO 语言开发快的特点, 用 PION 这个库做了一些简单的回归测试,都有些啥:

  1. DTLS 握手的丢包,乱序, 重复等多种可能的测试;

  2. RTC 推一个自带的阿凡达视频, 验证能不能用 RTC 拉流;

  3. 其他一些基本的流程验证。


在这个基础上, 我补充了一个 RTC 推流, FLV 播放, 验证音视频时间戳是不是对齐的逻辑。截取个代码片段:



写完后,本地多次验证 OK, 安心提交。


得益于 github 完善的机制, 提交后自动跑单元测试,回滚测试,各种环境的编译脚本。全绿!通过!



有了单元测试 + 回归测试这俩牛逼的组合, 对于开发者来说, 提交代码更安心了, 虽然全部测试通过不一定意味着没问题, 因为可能有一些函数和逻辑没有被测试覆盖到, 但是有不通过的测试一定意味着有问题, 这就足够了, 保证了 BUG 尽量在早期被发现, 提升软件的可靠性。


SRS 的未来, 希望每一个 PR, 都能用测试用例覆盖。

发布于: 1 小时前阅读数: 4
用户头像

还未添加个人签名 2020.09.10 加入

涵盖音视频通信基础网络RT-ONE,云直播、云点播、TRTC、即时通信 IM等音视频PaaS产品,以及云游戏、云创多媒体引擎等针对多种场景的音视频解决方案。

评论

发布
暂无评论
最佳实践 | 单元测试+回归测试在SRS代码提交中的实践总结