面试官把一张打印着代码的测试A4纸推到我面前,说:“别紧张,工程看看这段代码有什么问题。师面试”我低头一看,测试是工程一段很常见的Java单例实现——双重检查锁。但里面少了一个volatile关键字。师面试这个陷阱太经典了,测试经典到几乎每个测试工程师面试都会遇到,工程但真正能答好的师面试人并不多。
我抬头看了他一眼,测试说:“这个单例在多线程环境下可能拿到未初始化完成的工程对象。”他眼睛亮了一下,师面试追问:“为什么?测试”我说因为指令重排序,构造函数里的工程赋值操作可能被提前执行,另一个线程看到的师面试instance不是null,但内部的字段还没初始化好。他没说话,又推过来第二张纸,这次是一段SQL。
这就到了测试工程师面试最核心的地方——你不是在考代码,你是在考一个人怎么思考问题。测试这行当,表面上考的是技术,实际上考的是怀疑精神。代码写得漂亮的人很多,但能在一堆看似正常的逻辑里嗅出隐患的人,才是测试团队真正需要的。就像刚才那段单例,大多数人能看出缺了volatile,但只有少数人会接着问:那如果把这个类加载到不同的类加载器里,还会不会出问题?这种追问的能力,比背一百道面试题都管用。
我遇到过一位候选者,简历上写着“精通自动化测试框架”,结果我让他现场设计一个针对登录功能的测试用例,他张口就是“输入正确的用户名密码,点击登录,验证跳转成功”。我说你等一下,如果用户名的长度超过数据库字段限制呢?如果密码里带了特殊字符,比如单引号,会不会触发SQL注入?他愣住了。这哥们儿不是不聪明,他是习惯了执行别人设计好的用例,从来没想过为什么要这么设计。测试工程师的核心竞争力不是会写脚本,而是会设计场景——你脑子里能装下多少种“用户会怎么折腾这个系统”的可能性,决定了你能走多远。
还有个细节让我印象很深。有个小伙子面试时带了自己写的接口测试工具,不是那种包装精美的框架,就是一堆Python脚本,但里面每个断言都写得特别讲究。他解释为什么对某个字段的校验要区分“为空”和“为null”两种情况,因为后端可能返回空字符串也可能返回null,前端处理方式完全不同。这种对细节的偏执,就是测试工程师的底色。我当场就给他发了offer。
说白了,面试测试工程师,我最怕遇到那种把测试当过渡职业的人。有人觉得开发太难,先干两年测试再说。这种心态藏不住,你问他“如果开发说这个bug不是问题,你怎么办”,他要么说“那就听开发的呗”,要么说“我就反复提交,直到他改为止”。这两种答案都让人头疼。前者没有立场,后者没有沟通能力。好的测试工程师得有点“温柔的固执”——你能用数据和逻辑说服开发,而不是用级别压人,也不是一味退让。我见过最漂亮的处理方式,是一位测试妹子,她发现一个性能问题后,自己写了个压力测试脚本,把复现概率从千分之一提升到了百分之百,然后拿着截图和数据去找开发,对方二话没说就改了。
面试快结束时,我通常会让对方反问一个问题。有人问加班多不多,有人问技术栈新不新,但有个答案让我记到现在——他问的是:“你们团队怎么处理测试和开发之间的分歧?”这个问题问到点子上了。因为测试这份工作,表面上是跟代码较劲,实际上是跟人协作。一个团队处理分歧的方式,决定了测试工程师是在做质量守护者,还是只做个背锅的质检员。
说到底,测试工程师面试没有标准答案。代码题考的是基本功,场景题考的是思维广度,但最后决定录不录用的,往往是这个人对“质量”这件事有没有发自内心的执念。这种执念装不出来,也背不下来,它就藏在你面对一个不起眼的边界条件时,会不会多问自己一句:这里真的没问题吗?