为了解决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函数, 四舍五入, 问题迎刃而解。
改完重新跑测试, 通过!
经过这一次实践, 单元测试给我带来的体会是:
- 以后再怎么改代码, 跑一遍单元测试, 起码能让人安心, 知道这一次修改的代码没有基本的函数级别的错误;
- 试想一下如果没有用单元测试发现这几处细微的代码错误, 合并到4.0released后, 最终问题还是会变成ISSUE回来, 而且更隐晦, 更难排查。从长远看, 单元测试节省了开发者的时间。
搞完了单元测试,接下来就是搞回归测试。
为什么需要回归测试,通俗的说, 只保证了单元的正确性, 但是多个正确的单元有可能错误的结合, 所以我们需要回归测试, 来保证业务逻辑代码的正确性。
SRS里面是怎么做的
https://github.com/ossrs/srs/tree/4.0release/trunk/3rdparty/srs-bench/srs 这个目录下, 提供了压测工具和单元测试工具。
原理也很简单, 用GO自带的TEST, 结合GO语言开发快的特点, 用PION这个库做了一些简单的回归测试,都有些啥:
- DTLS握手的丢包,乱序, 重复等多种可能的测试;
- RTC推一个自带的阿凡达视频, 验证能不能用RTC拉流;
- 其他一些基本的流程验证。
在这个基础上, 我补充了一个RTC推流, FLV播放, 验证音视频时间戳是不是对齐的逻辑。截取个代码片段:
写完后,本地多次验证OK, 安心提交。
得益于github完善的机制, 提交后自动跑单元测试,回滚测试,各种环境的编译脚本。全绿!通过!
有了单元测试 回归测试这俩牛逼的组合, 对于开发者来说, 提交代码更安心了, 虽然全部测试通过不一定意味着没问题, 因为可能有一些函数和逻辑没有被测试覆盖到, 但是有不通过的测试一定意味着有问题, 这就足够了, 保证了BUG尽量在早期被发现, 提升软件的可靠性。
SRS的未来, 希望每一个PR, 都能用测试用例覆盖。
腾讯云音视频在音视频领域已有超过21年的技术积累,持续支持国内90%的音视频客户实现云上创新,独家具备 RT-ONE™ 全球网络,在此基础上,构建了业界最完整的 PaaS 产品家族,并以 All in One SDK 的创新方式为客户服务。腾讯云音视频为全真互联网时代,提供坚实的数字化助力。