<audio id="audio" title="32 | 软件测试：什么样的公司需要专职测试？" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/0c/e7/0ca23031171817b35f2c832f4b32e3e7.mp3"></audio>

你好，我是宝玉，我今天想与你讨论一下，什么样的公司需要专职测试这个问题。

若干年前，网络上对于软件开发是否需要专职测试有过一次讨论，代表文章有：左耳朵耗子老师写的《[我们需要专职的QA吗？](http://coolshell.cn/articles/6994.html)》，然后邹欣老师对此回复《[测试QA的角色和分工](http://www.cnblogs.com/xinz/archive/2012/04/09/2439695.html)》。

从这些年业界发展趋势来看，看起来很多公司都不需要专职测试了，只需要开发兼任测试工作就可以了。比如，Facebook号称自己没有专职测试工程师，Google和Amazon虽然有专职的测试工程师，但都是开发人员对质量负责，开发人员写大量的自动化测试代码。但这样真的可行吗？

在回答这个问题之前，我们还是先来看看，软件测试的主要工作是什么？只有搞清楚软件测试的工作，才能搞清楚这部分工作是否可以由开发来替代，是否需要专职测试。

## 软件测试的主要工作是什么？

在前面开发篇内容的学习中，我们对开发的工作已经比较了解了：在需求确定后，开发人员开始针对需求进行架构设计，然后编码，最后对发现的Bug进行修复，保障线上稳定运行。

而软件测试也类似，也是从需求开始，在需求确定后要去对需求进行分析，然后做测试设计。

如果说架构设计是对业务需求在技术方面的抽象，那么测试设计更像是对业务需求的具象，把业务需求分解成一个个具体的用户操作步骤，也就是测试用例。然后在开发完成后，按照设计好的测试用例进行逐一的测试验证，将发现的Bug报告给开发人员，并跟踪Bug的修复。

如果对软件测试的工作简单总结一下，就是发现Bug，报告Bug，跟踪Bug。

#### 软件测试怎么发现Bug？

这里面最难的就是发现Bug，尤其是如何尽早、尽可能全面地发现Bug。

举个例子来说，如果现在你需要开发一个用户登录的功能，你在开发完成后会怎么测试？

一个普通的程序员通常只会简单测试一下以下用例：

- 输入正确的用户名、密码，能登录；
- 输入错误的用户名密码，提示错误，不能登录。

而一个有经验的程序员还会测试一下其他情况，例如：

- 用户名或者密码为空，是否提示错误；
- 没有注册的用户名和密码，是否会提示错误。

但如果是一个专业的测试人员来测试，是不是只做上面的测试就够了呢？专业测试还会测试哪些内容呢？

对于专业测试人员来说，上面这些肯定是不够的，还需要有以下这些情况的功能性测试：

- 用户名密码是否大小写敏感；
- 用户名或密码如果是用特殊字符，会不会导致程序异常；
- 用户名或密码如果特别长，是不是会有异常；
- 是不是所有主流浏览器和终端设备都能使用。

这就完了吗？并没有。除了功能性的测试，还需要进行非功能性的测试，也就是像性能、安全性和用户体验等方面的测试。比如以下测试用例：

- 是否可以通过发送数据包反复登录，暴力破解密码；
- 会不会有Sql注入的风险；
- 大量用户同时登录，页面会不会崩溃；
- 用键盘tab、回车键是否可以操作。

当然还会有其他测试用例，这里就不一一列举。为什么专业测试人员和开发人员的测试用例会差这么多？

因为开发人员的重点，是放在如何实现功能上，就拿上面用户登录的例子，开发人员会想着如何能校验用户输入的用户名密码，并给出相应的提示，对于异常流程和场景会相对考虑较少。

而对于测试人员来说，重点是在检测，也就是会考虑所有可能的用户使用场景，正常的、异常的，甚至各种极端情况，例如大量并发访问、黑客恶意破解，所以他们能想到更多、更全面的测试用例。

测试人员设计测试用例，就是要尽可能做到覆盖所有用户操作的可能，但理论上来说这是不可能的，因为组合是有无限多个的。不过从测试的角度看，没有必要每一个可能都去测试，可以通过一些科学的方法来通过有限的测试用例，保证尽可能多的测试覆盖。

有哪些方法呢？我给你举几个例子：

- 等价类划分

就是把所有用户可能输入的数据分类，如果一类数据对于发现Bug的效果是一样的，那么这类数据就是一个等价类，测试的时候只要从里面任意选取一个值就好了。比如一个输入框要求只能输入1-100之间的整数，那么1到100之间都是等价的，0和任意负数也是等价的，101和之上的整数也是等价的。

因为分类是有限的，这样就可以用有限的测试用例实现尽可能多的测试覆盖。

- 边界值分析

边界值是对等价类的补充，因为输入输出的边界是非常容易出错的一个地方。比如说上面输入框的例子，0，1，100，101都是边界值，可以设计用例来测试是否会有可能出错。

- 探索性测试

探索性测试就是根据前面的测试结果，通过有效的策略进行测试。

举例来说，如果你玩过RPG游戏的话，里面通常会有走迷宫的地图，各种分叉，不同的分叉可能有不用的宝箱，如果你想打开所有的宝箱，那么就可以在遇到分叉的时候，每次优先走右边的分叉，除非右边已经去过了。

那么这里“右边的分叉是不是走过了”，就属于已经测试过的结果，策略就是优先走右边的分叉。关于探索性测试的介绍可以参考这篇文章《[探索性测试揭秘](http://blogs.msdn.microsoft.com/billliu/2012/05/25/103/)》。

当然除了以上这几个主要的策略，还有很多其他的策略，比如说：

- 场景设计；
- 因果图；
- 错误推测法。

这里我就不一一介绍，推荐阅读《微软的软件测试之道》，这本书上有很多具体的测试方法的详细介绍。

借助这些方法，测试人员就可以对需求功能设计出完整的、有较高覆盖率的测试用例。

所以，有时候测试人员的工作看起来不过是用鼠标点点测试，但他们在拿到需求后，其实花了很多时间和精力分析需求，然后根据需求设计测试用例，准备测试数据。等到开发人员完成软件开发后，就按照设计好的测试用例逐一测试，这样就可以做到及时发现Bug。

#### 软件测试怎么报告Bug？

在测试的过程中，如果测试人员发现了Bug，就会通过Bug跟踪系统提交Bug给开发人员。Bug跟踪系统其实跟我们在《[14 | 项目管理工具：一切管理问题，都应思考能否通过工具解决](http://time.geekbang.org/column/article/87787)》中介绍的任务跟踪系统是一样的，它可以方便地提交和跟踪Bug。

测试人员要做的就是创建一个新的Ticket，在Ticket的描述中，详细说明Bug是什么，具体的重现步骤，必要的话还要附上截图、日志等辅助信息。这样开发人员在收到Bug后就能快速定位问题，按照优先级对Bug进行修复。

#### 软件测试怎么跟踪Bug？

Bug的跟踪，并不仅仅是要跟踪开发人员什么时候修复了这个Bug，通常还包括对Bug修复的验证。

开发人员修复完一个Bug后，测试人员首先会验证这个Bug是不是真的被修复了，然后还要对整体功能做一个回归测试，确保不会因为修复Bug而引起其他功能出现问题。

回归测试是指修改了旧代码后重新进行测试，以确认修改没有引入新的错误或导致其他代码产生错误。

回归测试这一步很重要，因为通常开发人员在修复完Bug后，只会验证其修复的Bug，而不会验证其他功能是不是会有影响。但实际上，软件项目中经常会出现修复一个Bug，而导致系统其他功能出现问题的情况。回归测试，则能有效、及时地发现修复Bug导致系统不稳定的情况。

## 什么样的公司需要专职测试？

了解了测试的主要工作内容之后，我们再回过头来看看今天要讨论的问题：什么样的公司需要专职测试。

如果一个公司不需要专职测试，那么意味着专职测试的工作可以被其他工种替代，比如说由开发人员一起完成软件测试的工作。

想象一下，如果你是一名开发工程师，然后你要兼职做测试，那么你需要额外做好哪些工作？

首先，你在拿到需求后，除了做技术上的设计外，还需要做测试上的设计，借助测试方法设计测试用例。

这样做好处很明显，可以在写程序时，让程序更易于测试，设计时会对需求考虑更全面。缺点也显而易见，你不止要学习编程知识、了解业务，还要学习测试方法。也许对你来说可以做到，但是对于绝大多数开发人员来说，这是一个很高的要求。

然后在开发完成后，要对自己写的程序进行测试。这里可能存在一个问题，也就是如果你在程序实现的时候，漏掉了一个逻辑处理，比如说漏了检测Sql注入，那么你在测试的时候也不会想到要去测试这部分。

测试自己的程序还要克服一个心理障碍，就是要对自己的程序进行破坏性测试，才可能找到潜在的问题，但去“破坏”自己完美的程序，对大多数开发人员来说也是很难接受的一件事。

如果上面两个问题都能克服，你还得再考虑一个问题：如果项目进度比较吃紧，作为开发人员你会压缩哪部分时间？

正常来讲，测试时间必然要被压缩的，因为你首先得保证代码实现。这可能就导致只要项目进度一紧张，测试就被严重压缩了，进而会严重影响质量。

这样看来，完全由开发人员兼职测试，还是很有难度的，不仅对开发人员要求非常高，而且需要开发人员承担所有的开发和测试的压力。

#### 为什么Facebook可以做到没有专职测试呢？

首先Facebook的工程师水平确实是高于业界平均水平的，有能力同时做好开发和部分测试工作；

其次，Facebook的产品周期相对宽松，可以有时间完成自动化测试代码；

Facebook在功能发布之前，先发布新功能到内部环境，几千内部员工先测试，部分充当了测试人员角色；

Facebook的发布和监控也比较完善，有问题能通过监控及时发现，并且可以随时快速回滚或者发布补丁；

最后就是用户对这类社交产品的Bug相对容忍度比较高，想想看如果是波音飞机上的软件能这么做吗？

至于Google和Amazon这些公司，他们也是类似的情况：

- 大量优秀的工程师，可以同时兼任开发和测试；
- 有大量的自动化测试代码覆盖；
- 强大的发布和监控系统；
- 时间进度比较宽松；
- 用户对Bug容忍度较高。
- 对于不能满足上面条件的公司，有专职的测试是更有利于软件项目开发和质量保障的。

#### 大厂不设专职测试的启示

虽然对于大部分公司来说，要做到完全没有专职测试还不现实，但这些大厂不设专职测试的实践还是有值得借鉴和思考的地方。

首先，用自动化测试代替重复性的手工测试是必然趋势。随着自动化测试技术的成熟，写自动化测试代码的成本逐步降低，而自动化测试，可以极大提高测试效率，尤其是像回归测试这种需要频繁进行的。

其次，测试设计是软件测试人员的核心竞争力。无论是自动化测试还是手工测试，测试用例是核心。无效的测试用例，用任何方法去测试，都不会达到良好的测试目的，只有测试用例设计好了，真正做到有效高覆盖，测试才是高质量的。

最后，开发人员和测试人员的更多融合是一种双赢。比如说测试人员可以给开发人员提供测试用例作为测试参考，开发人员可以写更多自动化测试代码，这些方式都能有效保障产品质量。

## 总结

今天我带你一起分析了什么样的公司需要专职测试。同时也学习了软件测试的一些基本知识，简单来说软件测试的工作，就是发现Bug，报告Bug，跟踪Bug。

要能及时发现Bug，需要针对需求进行分析和测试设计，把需求具象成一个个用户操作步骤的测试用例。通过一些科学的测试方法，像等价类划分、边界值分析、探索性测试，能有效提升测试的覆盖率。

公司是否需要专职测试，还是取决于公司的具体情况，例如是否有大量优秀的工程师可以同时兼任开发和测试，有大量的自动化测试代码覆盖，有强大的发布和监控系统，时间进度宽松，用户对Bug容忍度较高。

## 课后思考

你们公司有专职测试吗？你觉得是否应该保留专职测试？为什么？欢迎在留言区与我分享讨论。

感谢阅读，如果你觉得这篇文章对你有一些启发，也欢迎把它分享给你的朋友。


