还有两天就农历新年了,我也拖家带口,踏上了回重庆老家的列车。按照往年惯例,每年的年终总结必不可少,这是对自己过去一年的交代,也是给未来的自己留点记录和回忆。趁着高铁上的空闲时间,我开始逼迫自己快速回忆这一年来的点点滴滴,整理成为 2019 年终总结。

工作

今年最大的变化就是告别工作三年的大疆来到了字节跳动,从技术管理岗再次转变为一线测试开发工程师岗。关于换工作的想法及历程,我在《写在大疆毕业之际》进行了较多的记录,这里就不再重复。

从大疆离职之前,恰逢之前的接口测试平台做到一定阶段,测试数据方面的需求也越来越重,因此今年春节后就开始计划测试数据服务方面的建设。基本思路还是基于 HttpRunner,通过接口自动化和数据驱动相结合的方式,实现各种类型测试数据的生成,并通过将参数入参和生成结果进行映射存储,最终实现测试数据查询服务。当时我正在学习极客时间的《10 倍程序员工作法》专栏,被其中「以终为始」、「最小可行性产品(MVP)」的理念深深折服,因此在项目启动之初就在团队内部推广这些理念。大家的接受度很高,因此我们的项目迭代方式也尽量遵循这些方法论,用户故事规划、任务拆解都做得有模有样,也算是一段难忘的经历。

来到字节跳动以后,隶属于 Lark 业务线的测试开发团队。相比于之前,一个很大的不同点在于 Lark 这边没有产品测试团队(今日头条、抖音等部门都还是有独立质量团队的),产品质量由研发团队全权负责。我个人是非常认可这种管理模式的,这也是我当初选择加入这边的一个主要因素。在明确“开发对质量负责”的基调下,不管是从流程还是实际操作层面,减少了沟通成本,大大提升了组织效率。并且这也迫使开发人员具有更高的质量意识,在开发过程中会更多地去主动关注代码质量和可测性,毕竟没有测试和运维人员再为自己的工作进行兜底,线上出了问题半夜 oncall 也不是那么好受的。而且我也惊奇地发现,在这种研发管理模式下,开发人员对测试普遍都比较热衷(虽然很无奈),不仅单元测试覆盖率普遍较高,各类自动化测试工具和框架也玩得特别溜,甚至会自行开发一些面向业务特性的测试工具。

当然,这对于测试开发团队也提出了更高的要求。相比于产品测试人员,开发人员对工具更加挑剔,而且他们最不缺的就是开发能力。要是测试开发提供的工具不好用,或者无法很好地解决他们的质量痛点,那么他们很有可能会自己去开发出一套工具。因此对于测试开发人员,扎实的开发能力只能算是最基本的能力要求;对研发质量保障的理解和积累、对测试工具的设计规划(品味)、面向具体业务技术特点的测试规划能力,这些才是更能体现测试开发价值的地方,也是业务开发团队需求更大的方面。

回到我在字节跳动这大半年的工作内容。全球化、跨租户、专私有化部署都是 Lark 业务的显著业务特点,业务开发团队在这些特性上普遍存在大量痛点,因此我们测试开发团队就重点围绕这些领域开展工作。内容太多,这里只重点回顾下全球化测试集群和私有化部署验收测试两个方面吧。

全球化测试这块儿,常见的案例就是某个国家地区的 VIP 用户投诉图片无法加载、文件无法上传、视频电话无法拨通等跨国连通性问题。如何先于用户及时发现问题、如何在用户投诉后快速复现排查问题,这都是业务开发急迫需要的能力。当时也是带着这些问题,我在公司内部的几大部门出差调研了一圈,最后幸运地在 IES(抖音、TikTok 所在的部门)找到了方案。说到国际化,TikTok 可以算是一个非常成功的全球化产品,当前已经在全球一百多个国家地区运营提供服务。与此同时,TikTok 也不可避免地面临着众多国际化带来的质量问题,因此 IES 之前就已经在全球数十个国家地区建设了测试机架(组成部分包括 MacMini + 手机 + 当地运营商 SIM 卡),并基于改进增强的 STF 方案给业务团队提供远程真机服务(该项目负责人黄冶在 MTSC 2019 大会上也有分享)。既然都有 MacMini 了,那可以做的事情就很多了,假如我们将接口自动化测试和 UI 自动化测试跑在这些分布在全球各地的 MacMini 上,地理位置和当地网络都有了,那不就可以实现全球化的自动化拨测和问题复现了么?这里不得不赞下字节跳动的公司文化,部门间协作非常流畅,基本上只要能找到共同目标,都可以很好地达成合作(感谢黄冶团队的大力支持)。于是,我们就在 IES 国际化机架的基础上,建设了全球化测试集群。简单地说,全球化测试集群主要包括两部分,一个是统一的测试调度服务(Task Server),可以将任意类型的任务调度到任意指定的国家地区的设备上运行;另外一个是执行端(Task Worker),部署在全球各机架的 MacMini 上,可以拉取并执行测试任务。我是负责 Task Worker 端的开发(Python + Bash),主要需要解决的难点就是保障节点高可用率和尽量降低运维成本,具体做的事情包括实现在任意设备上一键部署,支持远程升级热更新(或版本回退),支持多种测试任务类型(API、Web UI、Android/iOS UI/Monkey),确保在遇到系统重启、网络中断、进程退出等异常事件后 Worker 能自动恢复正常工作(杀不掉、删不掉,跟病毒颇为相似)。也是因为全球化接口拨测具有普遍需求,因此 HttpRunner 也得以有机会推广到业务线,我也可以有机会投入部分工作时间继续对 HttpRunner 进行迭代开发。

在私有化部署这块儿,这应该算是 to B 业务相比于 to C 业务独有的需求特性,而且也存在较多的痛点。整个 lark 产品,十多个业务上百个系统数百个微服务,要实现私有化部署是非常复杂的事情,部署、配置、集成、验收、运维、onboarding,每个方面都涉及大量工作要做,如果没有完善的自动化能力,人工投入将会非常巨大。我们测试开发团队主要负责验收这一部分。那么多系统模块,那么多配置项,任意环节出问题后都可能造成系统功能的不可用,因此私有化部署后,功能验收必不可少。但很显然,我们团队没有足够的人力和时间自行去做功能测试,我们更多的是担任教练的角色,为各个业务线提供各端的测试工具和方法论,指引业务开发人员去做自动化测试建设,例如服务端团队需要进行接口自动化覆盖,移动端团队需要完成 Android/iOS UI P0 自动化覆盖。这部分工作我主要是负责接口测试工具方向,包括对 HttpRunner 本身拓展支持 Protobuf、Thrift RPC 等内部通讯协议,与公司内现有接口测试平台打通集成,规划建设更适用于 Lark 业务特点的接口测试平台等等。除了需要保障功能正常,私有化部署环境的硬件通常与字节跳动机房的硬件资源具有较大差异,甚至存在不同构的情况,因此私有化部署后的性能验收同样必不可少。我因为之前有过相对较多的服务端性能测试经验,因此就承担起了性能验收这部分的 owner。具体事项方面,压测工具平台是一方面,但不是主要的问题,公司内已经有多个成熟的压测平台,并支持多种压测模式,因此我做的更多的是工具选型,以及结合平台的压测技术方案规划。除了技术方面,更大的挑战在于如何协调那么多业务线开展性能验收,如何确定哪些业务必须要进行性能验收,具体要压测哪些场景,性能测试要压测到多大的并发量才合适,达到多大的吞吐量(QPS)才算是满足要求,这些都是需要在性能验收方案里进行明确的。显然,这些不能都靠拍脑袋,因此我就跟数据团队的同学进行合作,由他们基于当前 SaaS top 租户的数据进行统计,筛选出流量较高的接口,进而确定出需要覆盖的业务线和场景。场景确定了,就可以指导业务开发人员写出压测脚本;但对于压测来说,更难的在于压测数据的准备。因此,我这边还有个重点工作就是基于压测场景,与业务开发人员梳理出涉及到的压测数据类型,并统一规划压测数据的准备,打通测试数据服务等。具体的工作事项还有很多,这里就不再详细展开。对我而言,这些都是很好的锻炼和学习的机会,至少通过压测工作,我可以在短期内熟悉到当前业务线的技术架构,也在“赶鸭子上架”的节奏中,入门了 Go 语言。

不知不觉工作上的事情已经写了这么多。总体来说,入职字节跳动后的体验还是很不错的,公司内部文化非常开放透明,提倡「Context Over Control」,因此一线员工的自由度比较高,可以自己选择去做很多事情。而且由于 Lark 这边的去“QE”研发管理模式,我日常工作更多的是跟各个业务线的一线开发人员进行协作,方案评审、code review 之外,也接触了更多的开发设计和架构领域,这对自己的技术提升都起到了很好的促进作用。当然,我也有过不适应的地方。刚入职的一段时间感觉公司对外较为封闭,例如曾写过一篇《入职字节跳动两个月的个人体验》,由于涉及到一些公司文化方面的内容最终没能发出来;对外技术分享都需要经过严格的审核,因此各个技术大会上字节跳动的分享相对都比较少。但我后来也非常理解公司的做法,并认可公司的理念,「只有对外保密做得好,对内沟通才会更透明」。也是因为这样的制度,在公司内可以定期通过 CEO 面对面了解到公司的发展方向,研发员工可以获得非常开放的知识库和代码仓库开放权限等等,这些对于员工来说都是非常有益的。另外一块儿,就是不知道为啥,虽然公司没有 KPI 文化,没有要求上下班打卡,但大家都很拼,按照某同事的玩笑话说,就是「工作过于饱和」,完全没有摸鱼的闲暇时光。也许,这就是字节跳动这家公司的成功之处吧。

个人成长

接下来说下个人成长部分吧。

其实对于当前我所处的阶段而言,基本上除了生活就是工作了。而这里的个人成长部分,更多指的是抛开公司事务和生活之外的部分。

首先想说的是个人角色的转变,从技术管理岗再次转变成为一线工程师岗。之前跟朋友聊天时,朋友说从团队 leader 转为一线员工后通常会有些不适应,工作内容是一方面,更主要的可能是心理落差方面。其实对我而言还好,因为我本身也清楚当前自己的需求,希望能在一线获得更多的锻炼和积累。虽然说「屁股决定脑袋」,但经历过技术管理,习惯了站在团队整体去思考之后,重回一线后同样可以尝试去换位思考。很多时候站在团队甚至业务线的角度去思考问题,那么对于什么事情重要什么事情优先级更高,就会想得更加清楚。作为团队中的一名成员,我不负责建设团队管理制度,但我也会积极地参与进去。例如团队 OKR 管理、晨会制度、双周报形式这些日常工作方式,与其单纯地作为执行者,不如积极地参与到改进中去,提出优化方案,让自己所处的工作环境更舒适、更高效。其实说白了就是需要有「主人翁」心态,工作时不要觉得是在为公司打工,当做每件事情时保持创业心态,全身心投入后,产出结果和个人获得的成长收获都会大得多。

来到字节跳动后,我继续担任面试官,会参与技术面试工作。都说字节跳动的面试难度很高,同样地,公司对面试官也会有严格的要求。其中一个要求是每场面试都要有详细的面试记录,包括每一个面试问题和候选人的回答内容。这样做的好处非常明显,后续面试官可以查看到之前的面试内容,避免重复问题,而 HR 和终面面试官也可以更清晰地还原面试现场,对候选人进行更充分准确的评估。显然,一字不差地将候选人的回答记录下来不现实,也是没有必要的。而且很多时候候选人的回答思路比较混乱,我曾试过使用讯飞语记将语音实时转换为文字,发现也是完全没法看。因此这需要我在面试的过程中抓住候选人回答的要点进行记录,并同时聆听候选人的回答跟上思路。虽然之前在大疆已经前前后后参与了上百次面试,但刚在字节跳动实习面试的时候还是会有些不适应,记录速度跟不上是一方面,面试全程保持高度专注,精力消耗估计也不比候选人低。不过经过几次实习练习后,我总算可以正常适应了,后面也逐步习惯了这样的面试形式。在面试这块儿我还有个需要改进的点,就是对面试时间的把握,当前每场面试基本都要花费 1 个小时甚至更多时间。但实际上,在保障面试效果的基础上,面试时间是可以进行压缩的,而这本质上就是提问和识人的能力,这些方面我也需要持续进行锻炼和提升。

不同于往年,我今年基本上没有再去大会上进行分享。工作忙是一方面,更多的原因还是觉得自己当前的重心在于输入,需要在技术深度和项目能力上进行更多的沉淀和积累。但也有个例外,今年 MSTC 2019 新开了个 TTF 开源项目专场,HttpRunner 作为 TTF 首批孵化的重点项目,缺席肯定是不合适了。因此我今年就去北京参加了 MSTC 2019,分享主题为《HttpRunner 2.0 技术架构与接口测试应用》,重点介绍了 HttpRunner 2.0 方面的内容。出乎意料的是,最终经过听众投票,我的分享以 46% 的投票获得了「TTF & 质量保障 2 专场」的第一名,这是我第二次获得专场最高票数了,实在是受宠若惊,在此也非常感谢大家的认可和鼓励。关于大会的参会经历,我还写了一篇博客,《我的 MTSC 2019 分享经历》

再说下我的个人开源项目「HttpRunner」。从 2017 年 6 月开始发布第一个版本,到现在已经快三年了,很庆幸这个项目还活着。截至当前,HttpRunner 的 GitHub star 数约 1.8k,并位于「TesterHome 开源项目榜单」第一位。今年思寒成立 TTF 基金会,HttpRunner 有幸成为了首批被赞助的项目。同时,HttpRunner 通过申请,获得了 Sentry 的开源项目支持。当然,收获认可越多,面临的压力也会更大。特别是当前 HttpRunner contributor 数虽然有 12 位,但基本都还是我个人在迭代和维护,当我工作比较忙之后,的确是很难再投入时间和精力在开源项目上。说到这里,前段时间才被用户骂了一次,「兼容性稀烂,发版前你做过 Windows 兼容性测试么???」,说实话还真没有;心里那个苦啊,自己没有 Windows 兼容性需求,周边也没有 Windows 设备可以用于进行验证,但 Windows 用户基数那么大,放弃兼容又不合适,只有硬撑着。看着 issues 数量逐步上升,我也越发地感觉到时间精力跟不上。庆幸的是,HttpRunner 在字节跳动内部逐步被部分业务线接受,我也有机会继续投入工作时间对 HttpRunner 进行迭代开发。另外,今年恒捷开始负责 TTF 开源项目,跟达峰和我一起筹划 TTF 开源项目运作机制,期望能吸引更多的人加入进来。开源项目只有形成了良好的社区和拥有稳定的核心开发者小组,才能可持续地发展下去,这也是 HttpRunner 接下来要努力的方向。

最后,对于博客公众号这块儿,今年基本上是荒废了,实在惭愧。原因有很多,但更多的都是借口,当内心懈怠懒成习惯以后,再捡起来就很难了。很久没写东西,手也生了不少,本篇年终总结写得也是格外费力。其实在很早之前我就认可一个观点,「最好的学习方式是教授别人」,而博客就是一个很好的实现方式。在新的一年里,加油吧。

总体来说,之前在 2018 年终总结中的困惑少了许多,我也感激自己再次跟随了自己内心的声音,勇敢地做出选择付诸了行动。

生活

再说下这一年的生活方面。不得不说,有了孩子以后,心态上会有比较大的变化,生活也都基本上是围绕着孩子。

众所周知,互联网公司的工作节奏比较快(网传字节跳动尤甚),普遍下班时间不会太早。当然,整体氛围是这样,但具体几点下班还是可以自己把握的。因此我给自己制定了一套时间安排,每周一周二周四会在公司待得比较晚(22~23 点),尽量多做些事情,包括工作上的事情和个人技术学习;周三和周五晚上会下班回家跟家人一起吃饭,有工作上的事儿就带电脑回家在家处理;周末则基本上就不再做工作上的事情,会开车带着家人出去玩(遛娃)。通过这种方式,也算是取得了一定的工作和生活的平衡。

这一年,小坚果满两岁了,随着他的语言能力越来强,我们的生活也多了许多趣味。例如在我早上要出门上班的时候,他会不舍地拉着我说“不上班”,或者说要“跟爸爸一起去上班”;我安慰他说过两天周末了我们就出去玩,问他到时候想去哪里玩,结果他的要求总是那么低,不是“玩沙沙”就是“找个有滑滑梯的公园玩”。我也沾了小坚果的光,这一年没有以前那么宅了,深圳大点的公园、景点基本上都去了个遍,深圳湾公园都不知道去了多少次。坚果妈在家的时候,他就经常嚷着要“接爸爸下班”;到了来福士,他会在办公区安全闸口候着我,有时候我有点事儿耽误了会儿,他就会跟他妈妈念叨,“怎么还没出来哦”,待看到我后就会冲上来让我抱,这也是我最幸福的时光。小坚果的记忆力也是惊人,很久前去过的地方、吃过的东西,他居然也会记得;有次我在读三字经,发现他居然可以接下句,于是我试着让他来背,发现他居然可以从“人之初”背到“贵以专”,着实令我惊叹不已。当然,这是小坚果乖的时候,调皮捣蛋起来也是忍不住想捶他得不得了。在家里经常把东西翻得到处都是,有时候故意把垃圾桶推倒然后就跑,还“嘎嘎嘎”地笑得特别有成就感。说到这儿又是气,高铁上在我用手机写这份年终总结的时候,他趁我不注意扑过来抢我手机乱点了几下,害得我丢了好多内容(在 apple notes 上没有版本回退)。跟小坚果的点点滴滴太多了,坚果妈在他两岁生日的时候写了一篇,《来,我们一起》,满满的温馨回忆。

从大疆离职后,我就告别了大疆的公租房福利,开始在外面租房了,这也是我第一次自行在深圳租房。为了上班方便,以及享受字节跳动的租房补贴福利,我就租在了公司旁边,走路十分钟的样子。怎么说呢,住得近也是有好有坏吧。好的方面,不用任何交通工具,每天在路上的时间非常短,再加上公司上班时间晚,因此我基本上都是睡到自然醒,差不多 9:40 才出门去公司(因为公司的早饭 10 点停止供应)。但也是住得太近,感觉就没有了上下班的感觉(俗称仪式感),基本上工作日就是两点一线,不是在公司上班就是在家睡觉,仿佛回到了中学住校的时候。有时候我甚至挺怀念之前开车上下班的时光,在开车的同时还能听下极客时间,而现在这个场景也彻底没了。

在深圳租房不得不面对的另外一块儿就是房租,七十来平的小两房,每个月房租加上物业水电费花费接近八千了,着实是一笔不小的开销。很多朋友都说,这租金都快赶上月供了,还不如买一套。说到在深圳买房,我之前是有考虑过,在 2018 年终总结中也困惑过。但现在我和老婆都想清楚了,算是彻底放弃了这个念头。深圳的房价已经这么高了,南山福田均价早已过了七八万,要再上车也不是不可以,但能买到啥品质的住房我也是清楚的。例如我当前租的这套楼龄十多年的小两房,当前市场价差不多也要 550 万的样子,而且还没有啥好学位。之前跟同事闲聊为啥要留在深圳的话题,同事的普遍说法是为了给孩子更高的起点,让孩子以后大学毕业后不再像我们这一代这样,还要纠结是否能留在一线城市。但我觉得那都太遥远了,先不说等孩子长大后社会形态如何,眼前的是深圳学位严重紧张,好点的学位房价格早已高攀不起,即使留在深圳,也无法给孩子提供好的教育资源和居住环境,那又何必呢?想清楚这些之后,也就没啥好纠结的了,还是过段时间去成都吧。

随着年龄的增大,我也越发地感受到健康的重要性。今年因为皮肤有些问题,跑了几趟医院。医生的说法是慢性荨麻疹,本身不是啥大的问题,主要是由于生活作息不规律、运动少、压力大、抵抗力下降造成的。这个春节爆发新型冠状病毒肺炎疫情后,我也初步了解了些健康相关的知识,对于身体抵抗力的重要性有了更多的认识。在过去的这些年,我在锻炼身体这方面的确做得很不到位,今年一时兴起每天中午到公司健身房跑步 5 公里,也就坚持了两个月。好在这两年身体还算健康没出啥大问题,今年的慢性荨麻疹也算是给我敲了个警钟,后面的日常锻炼必须得安排起来了。

新年展望

最后再展望下 2020 年吧。

  1. 持续提升个人的技术深度,特别是在服务端方向,充分学习并掌握字节跳动的统一技术栈。
  2. 深入学习 Go 语言(恰逢鼠年,Go 语言的吉祥物是土拨鼠,也算是应景),并将 Go 语言作为自己的第一生产力编程语言(替代 Python)。
  3. HttpRunner 3.0 重构,支持更多的协议和应用场景,实现 Go 版本也不是不可能。
  4. 输入与输出相结合,系统性学习,勤思考,多输出,坚持技术博客创作。
  5. 学会生活,锻炼身体,陪伴家人,工作是长跑,讲究的是可持续发展。

往年记录