文/ThoughtWorks 杨瑞
我尝试从几个角度来分析,在正式分析开始前,我们先把范围划定在软件开发这个圈子里头,并且对这些问题进行解释。关于这方面的讨论,一般会存在以下几个误区:
- 将开发阶段、测试阶段完全剥离。
- 对测试的理解有些偏差,误认为测试只是在产品做出来之后,使用它,然后挑毛病,找bug。
- 误认为测试只有功能性的校验。
下头对这3点逐一解释:
将开发阶段、测试阶段完全剥离。
** 经常有人会问,“为什么互联网公司不开除测试,转而让大众来测,找到一个bug给100元?”**
这个问题有个假设,就是开发阶段、测试阶段完全剥离开了。开发阶段单纯地就是开发人员敲代码,然后出来的东西交给测试人员去做测试。
我不否认,现在依然存在这样的实践方式。但是,这不是一个好的方式。因为这种流程,把发现bug的时间点推迟了。而发现bug的时间点越靠后,修复它所要付出的代价就越大。
这点应该很容易理解,比如你敲钉子,如果一口气敲完了才发现,敲歪了,那就得拔出来重新来,可是东西上已经有一个很深的洞了。所以,好的方式是敲一敲,检查一下,随时纠正方向,确保前进的大方向是正确的。
软件更是如此,某个bug可能是在最底层的地方发生的,如果早期发现,定位也容易,修复起来被牵扯到的地方也少,付出的代价可以接受。因为bug的产生可能是多个原因,有可能是功能性的,也有可能是对业务理解的偏差导致开始就做错了。
如果在产品做出来,发布给最终用户之后才发现。那个时候再排查到底哪里出了问题,就不是一时半会能做到的了,代价很大。
所以比较好的实践方式,是由专业的业务人员把要做的东西切割成足够小的、彼此独立的、可单独交付的模块,开发、测试以及业务人员及时沟通、及时反馈,一个一个小模块完成,随时做随时测。把发现bug的时间点尽量往前推,这样就可以把修复它的代价降得尽可能小。
当然,小模块都通过测试,并不意味着所有小模块拼装起来组成的系统一定正确,还需要进行层次高一点的集成测试。这就引出了第2点。
测试就是找bug的?
对测试的理解有些偏差,误认为测试只是在产品做出来之后,使用它,然后挑毛病,找bug。
有这样的偏差并不奇怪,因为执这样想法的人太多了,甚至包括一些软件行业的从业人员。比如有这样的说法:
开发就是敲代码的,测试就是找bug的
如果是业外人士,我觉得有这样的误解没什么。毕竟,隔行如隔山,但业内人士这样理解的话,真的不知道该说什么好了。开发是不是只管敲代码,这里不谈。这里我们要谈的,是,测试不是单纯的找bug。
现在我们承接第1点,来说说为什么测试不是在产品做出来之后,单纯的找bug。
先科普的一个东西,就是测试金字塔。
这是Martin Fowler的一篇博客中提到的《TestPyramid》。
看不懂这个图没关系,我来慢慢解释。
测试是分层的,它真的不是只有在产品做出来后才开始的,并且也不能那个时候才开始。原因在第1点里已经解释过了。一个工程级别的软件产品,它的测试大致覆盖了代码级别的单元测试,模块级别的API测试,还有端到端的集成测试。这并不全面,还有很多其他类型,这里我们只是大概分成这3种,便于解释、理解。
底部那层,就是代码级别的单元测试。它是发现bug的最前沿阵地,能在这个层级抓住的bug,修复起来的代价,会小很多。而且这部分测试数量很大,验证的东西也不是最终用户所能理解的,通常都是自动化运行,有很多种框架可供选择。只有这层的测试全部通过,才会运行后面更上层的测试。
中间那层,是service级别的测试,大概可以理解成模块间的API测试。到这一层,基本每个模块的功能都得到了保障,但是他们彼此的协作不一定正常,所以这层集中要测的就是不同模块间的协作、通信了。这部分测试数量第二多,也是自动化运行。通过之后,就可以开始最上面那层的测试了。
顶部那层,这部分测试的数量最少,是UI级别的测试。测试的过程大致可以认为是,模拟使用产品的过程,最终用户也能理解了。比如从注册用户开始,到注册成功,登录成功,页面正确加载。这种校验最基本功能的测试,叫冒烟测试,确保产品可以正确运行,没有无法启动之类的重大缺陷。除此之外,还有部分不便自动化的测试,需要手动测试,同时还会校验一些边角的情形。
即便上面说的测试全部通过,也不能确保产品万无一失没有bug,这是不可能的。只能说,通过了那么多层的测试,产品处在一个稳定状态了,最终用户的使用体验良好,绝大部分需求都可以满足。
误认为测试只有功能性的校验。
之所以有人会这样认为,可能是觉得测试只是在使用产品的过程中,发现了功能上、界面上不合理的地方,报告给开发,他们修复,就结束了。
其实不然,测试除了功能性的校验,还有安全方面的测试、性能方面的测试、兼容性的测试,等等等等。一个负责任的企业,不可能把包含安全漏洞、性能奇差、对运行系统有各种吹毛求疵严酷要求的产品发布给普通用户,就算他们敢发布,用户也会选择唾弃他们。所以在发布产品之前,肯定有这方面的测试,而这方面的测试,不是普通用户所能胜任的。
喏,现在看到了吧。其实测试也是一个复杂的工程,并非单纯的使用最终产品,找到其中的缺陷和问题,再提交这么简单的事情。
说到这里,我猜想,所谓的“让大众去测试,去找bug”,很大程度应该是指测试金字塔中,位于顶层的那部分。让用户通过自己的使用,遇到bug直接报。
也有人说,单元测试那些是开发做的。对于那些测试金字塔中层级较低的测试,可以由开发人员或者其他相应的技术人员在产品发布前解决。对于那些层级高的,比如UI级别的测试,可以分发出去,让最终用户来测试,并且奖钱!
OK,没问题。那就依照这个说法,我再来解释为什么UI级别的测试也不能不管不顾的直接扔给最终用户。前面有人也提到了相关的东西,我在这里依旧分几点来说,先来个summary,主要是这几个点:
测试是一项工程,需要计划、策略。不能无脑乱来。
对于bug的描述和修复,是有相应要求的。普通用户做不来。
详细解释如下:
1、测试是一项工程,需要计划、策略。不能无脑乱来
即便对于大家认为没有技术含量的手动测试,也要制定相应的测试策略、测试计划。确定使用什么方法去测试产品,如何测试,开展测试时如何组织测试用例,人员如何分配,团队如何分工合作。如果没有这些纲领性、指导性的东西,面对产品那么多的功能,全凭脑子想,用到哪里测到哪里?这个真有点天方夜谭了。苏杰的回答中已经提到不少。
要构建这么多测试,是需要团队内的人员一起努力、合作的。要考虑哪些东西需要提前注意,哪些情况需要单独拿出来测试,哪些东西不重要可以不测。在开发的过程中就尽量避免出现问题,而不是等它出现再修。
2、对于bug的描述和修复,是有相应要求的
还是那句话,测试是一项工程。发现了bug,需要把它用合理的形式记录下来,反馈给开发方,再经过多方人员的沟通,修复,回归测试,才能确认修复好了,再次发布产品。
对于记录bug也有一些要求,比如要阐明在运行什么系统下、系统的版本、产品的版本、如果是浏览器中打开还要标明浏览器版本、重现步骤、提供截图、提供测试账号。
开发人员拿到bug后,可以根据那些信息尝试快速地复现bug,再定位,再修复。如果中间出现问题,需要跟报bug的人员沟通、确认,是产品本身就如此设计的?是偶然发生无法复现的?是优先级很低暂且不用管的?
这些事情,如果是在团队内,很好实施。如果需要跟用户做这样的沟通,那真是……费死牛劲了。所以,即便大家都认为没有技术含量的UI测试,也不能直接扔给用户去做。
最后,最重要的一点在这里:
- 用户使用产品,享受的是体验。
- 目的是高效舒服地解决自己的问题。
如果没有任何测试,直接把产品扔出去,让用户负责测试。前面提到的安全、性能、兼容性还有功能上的各种问题,任何一个都会导致用户崩溃。
所以,无论如何都不能把质量没有保障的产品,直接扔给最终用户去做测试。
最后感慨一下,大家普遍对测试有一定程度的误解,觉得测试就是在界面点点点,找几个茬,就算完事了。
其实,测试需要专业的人士,需要对产品的透彻理解,需要对用户的同理心,需要对市场的把握,需要足够好的大局观,需要足够的耐心,需要一定的技术功底,需要宽泛的知识面,需要良好的沟通能力,需要能够协调团队中不同角色。
说的好像很高级,好多事情是产品经理或者项目经理干的活,但是,说实话,想做一个好的测试人员,这些东西真的都需要。当然,如果愿意踏踏实实做一个点界面的人,那就不需要这些。
再响应一下现在很热的口号,“工匠精神”,作为一个有工匠精神和责任心的企业,怎么能容许自己的产品质量没有保障就直接交付给用户呢?
Google出过一本书,叫《Google软件测试之道》,里面提到过一些观点,原话记不清了。我说说我的理解:
- 尽量把测试往前推,尽早发现,降低修复成本;
- 测试的目的不是发现bug,而是预防bug的发生;
当各种测试做的足够好的时候,即发布的产品质量有足够保障时,一些不重要、影响小的问题可以不考虑,直接发布产品,用户发现提出反馈后,酌情修复;
通过各种技术手段和流程改进,逐步的解放公司内部测试人员,让他们把精力放在对产品的把握上。