<audio id="audio" title="01 | 基础：跳出细节看全局，接口测试到底是在做什么？" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/ea/7e/ea965cf717561a641dbe7addf6d0867e.mp3"></audio>

你好，我是陈磊。

今天开始，我们就来聊一聊接口测试的那些事儿，这是我们专栏的第一节课，在讲解如何做好接口测试之前，我想先给你讲讲它的必要性，再讲讲什么是接口、什么是接口测试。

## 接口测试为什么重要？

我相信你一定听说过这样一句话：“测试要尽早介入，测试进行得越早，软件开发的成本就越低，就越能更好地保证软件质量。”

但是如何尽早地进入测试，作为软件测试工程师的你，是不是也没办法说得清楚呢？其实上面那句话中的“测试”，所指的并不是测试工程师这个人，而是指包含了单元测试、接口测试、界面测试等一系列质量保障活动的测试工作。

说到单元测试、接口测试和界面测试，你是不是马上就想到了“测试金字塔模型”呢？

<img src="https://static001.geekbang.org/resource/image/54/26/54babe3ca1b8baf147d6b83486f86b26.jpg" alt="">

在这个金字塔模型中，界面测试、接口测试和单元测试，每一个阶段所占面积的大小，代表了它们在测试过程中的投入和工作量占比。

你可以看到，单元测试在测试过程中，占据了绝大部分的比重，这表示单元测试需要你投入更多的时间和人力成本。但是，单元测试并非测试工程师的本职工作，它属于开发工程师的工作范筹。说到这你可能会问了：“如果开发工程师从来不写单元测试怎么办？”毕竟大部分开发人员都不爱写测试。

其实，我也会问自己这个问题。不可否认，开发工程师不只很少写单元测试，更很少写出好的单元测试代码，很多时候，工期的压力让他们放弃了单元测试。但是，一个产品的交付质量更多时候却是由测试工程师来保障的，面对这一实际现状，我们又该怎么办好呢？

我们聪明的测试工程师提供了两种解决手段：一种是用一些智能化框架补充单元测试工作（如果你对智能化单元测试感兴趣，可以参考我在2019年TiD上的演讲内容“[自动的自动化测试智能化一站式API测试服务](https://mp.weixin.qq.com/s?__biz=MzUxOTg3NzA4Mg==&amp;mid=2247485068&amp;idx=4&amp;sn=dcabc199c0f9ba03319ecfdbe07a0b62&amp;chksm=f9f3be39ce84372f78d00a691559cdedef1e54355d12243efc5821c74f39def0d78164bd9296&amp;token=2056996305&amp;lang=zh_CN#rd)”）；另外一种，就是加大我们自己主导的接口测试的工作投入比重，来弥补单元测试的不足，这样，上面那个金字塔模型就会逐渐演变成菱形模型。

<img src="https://static001.geekbang.org/resource/image/af/60/afec8e77c9fc22d448f9b2885d278b60.jpg" alt="">

那之所以出现从“金字塔模型”到“棱形模型”这种变化，并不是有人刻意提高测试工程师在整个交付流程中的地位，这其实是随着工作的不断进行，逐渐形成的结果。

在质量保障过程中，我们的测试工程师会不断增大接口测试的测试深度和测试广度，往下逐渐覆盖一些公共接口的单元测试内容，往上则逐渐覆盖应该由UI层保障的业务逻辑测试，这么做的主要目的，就是为了更好地完成质量保障工作，交付一个可靠的、高质量的项目。

所以，从接口测试这一环节开始，测试工程师就变成了质量保障工作的主要推动者，接口测试也变得愈发重要。那它有什么好处和优越性呢？我觉得可以从下面这3个角度来看：

1. 接口测试更容易和其他自动化系统相结合；
1. 相对于界面测试，接口测试可以更早开始，也可以测试一些界面测试无法测试的范围，因此它使“测试更早的投入”这句话变成现实；
1. 接口测试还可以保障系统的鲁棒性，使得被测系统更健壮。

现在，我相信你已经意识到接口测试在质量保障中的重要地位了，那么，你知道究竟什么是接口吗？接口测试又在测些什么呢？我们又为什么要做接口测试呢？

下面我就逐一把这些讲解给你。

## 接口是什么？

如果你想要知道接口测试在测什么，首先就要知道接口是什么。

在这里我不想告诉你书本上是怎么定义接口的，从那些晦涩的语言中，你可能读几次都不能真正理解它的含义，我准备用一个实际生活中的例子，来告诉你接口究竟是什么。

我相信你肯定去过麦当劳，那每次在你去麦当劳吃东西时，你是否细心观察过它为你准备订单商品的过程呢？

如果你的订单上有一个汉堡，工作人员会先找到汉堡的原材料如面包片、肉饼和生菜等，按照规定步骤，将这些原材料组合成一个汉堡，然后送给你；如果你的订单上有一份薯条，那么工作人员会进入另外一个工作流程，先找到薯条原材料和炸薯条的锅，把薯条炸好后，送到你面前。

那么在上面的例子中，汉堡以及薯条的原材料就是接口中必要的条件入参，也就是接口的特定输入；制作汉堡或烹饪薯条的过程，就是接口内部的处理逻辑；送到你面前的汉堡和薯条，就是接口的处理结果和特定输出，也就是返回参数。

**所以我们可以看到，接口就是有特定输入和特定输出的一套逻辑处理单元，而它不用知道自身的内部实现逻辑，这也可以叫做接口的黑盒处理逻辑。**

而从上面的例子你也可以看到，由于服务对象不同，接口又可以分为两种，一种是系统或服务的内部接口，一种是外部依赖接口。

<li>
<h3>内部接口</h3>
</li>

简单来说，内部接口就是系统内部调用的接口。

在上面麦当劳的例子中，内部接口有两个：

- 汉堡订单。服务员在接到订单后，输入汉堡的原材料，将汉堡做好后，放到后厨和前台之间的一个中间储存柜里，作为输出，为下一个中间储物柜接口提供输入参数。
- 中间储物柜。服务员从中间储物柜拿出汉堡，这就是这个内部接口的特定输入，最后送到你面前的汉堡，就是这个内部接口的特定输出。

那么在软件系统中，内部接口是怎么一回事呢？

其实，你在网上购物时，要先登录系统，然后将商品加入购物车，再接下来支付订单。那么，从添加商品到购物车，再到支付订单，这一长串的流程之间，就是通过系统内部接口来完成的。

<li>
<h3>外部接口</h3>
</li>

刚刚说了内部接口，那什么是外部接口呢？其实它是相对于内部接口而存在的一个概念，上面你在麦当劳点餐的场景就是一个外部接口，它又可以分为两部分：

- 出订单前，你的点餐过程。这个外部接口特定的输入是你在点餐时，告诉服务员你想点什么，这也是你输出给麦当劳的参数。
- 出订单后，服务员送餐的过程。它的特定的输出是服务员把汉堡送给你，这也是麦当劳返回给你的处理结果参数。

在系统上，外部接口又是怎么回事呢？

你在购物后点击付款时，页面会跳转到支付系统，等你完成支付流程后，再跳转回订单页，在这样的流程中，都会涉及系统对外的接口，还有，比如说付款工程的支付接口、配送过程的物流接口等等。

**现在我来总结一下接口的本质，它其实就是一种契约，遵循这样一种形式：在开发前期，我们约定接口会接收什么数据；在处理完成后，它又会返回什么数据。**

如果调用方和被调用方都遵从了这种契约，那么就可以达到共同开发的目的，开发完成后，联调完成系统逻辑的前期预期，提高研发效能。

## 什么是接口测试？

**还是以麦当劳的汉堡为例，接口测试，其实就是要验证制作汉堡的过程是否正确。**这里所说的“正确”其实有两方面的意思：

- 一方面，是要验证输入了汉堡的原材料，经过制作汉堡的处理流程，最后交付给你的是一个汉堡；
- 另外一方面，是要验证在输入的汉堡原材料不对或者不全的情况下，经过制作汉堡的处理流程后，不能给你交付一个汉堡。

你一定要注意，**这两方面的验证是都要进行的，对于一个测试工程师来说，这两种流程都是正向流程。只有理解了这个思维，你才能把自己从客户思维里拉出来，形成测试工程师思维。**

我相信你在工作中，已经接触过各式各样的接口了，比如说HTTP协议的接口、RESTful格式的接口、WebService的接口、RPC协议的接口等。其实无论是哪一种形式的接口，它们都是通过某一种传输协议，在Client端和Server端之间来完成数据传递的。

- 假如你现在测试的，是Web端的极客时间，那么Client端就是浏览器，Server端就是Web服务，那么浏览器和Web服务之间，就是通过HTTP协议传输的；
- 如果你测试的，是移动端的极客时间，那么Client端就是你的设备上安装的极客时间应用，Server端就是RESTful格式的接口服务，那么极客时间的应用和RESTful格式的接口服务，就是通过JSON格式的数据来传递的。

**看到这，我想你也能理解了，接口测试其实就是模拟调用方，比如Client端，通过接口通信来检测被测接口的正确性和容错性。**

但是请你放心，我现在所说的模拟调用方，并不是让你开发一个浏览器或者极客时间的手机应用，而是让你模拟这些客户端上的前端逻辑，调用Server端提供的接口，你完全可以借助一些工具或代码来完成这项工作。

这些相关的工具或代码技巧，也就是我设计这个专栏的主要思路。但我不想把这些工具一次都罗列给你，让你马上就失去兴趣，这是由于两个原因：

- 当你看到一个好几页的工具列表或者技术列表式时，你可能会觉得，自己需要翻越无数个高峰才能学会接口测试；
- 另一方面我也觉得，在接口测试中，工具或代码并不是它的核心内容，接口测试思维才是你应该重点关注的问题。

所以，我会在做一些工作或者任务的过程中，把这些工具介绍给你，让你知道哪些工具能够解决哪些问题，用什么样的代码可以解决什么样的问题。我也更希望你知道，工具和代码并不是相互排斥的，而是相互依存和相互辅助的。

其实，接口测试和你以前最熟悉的业务测试一样，都是关注输入和预期是否一致，尤其是输入数据中有一些非法输入的时候，接口的处理和逻辑控制是否合理，这些都是通过返回值来判定的。

还有一些小概率逻辑的处理也是我们设计输入的关注重点，比如一些代码中的异常情况，我们也要想办法，通过输入参数来触发这种逻辑分支，通过返回值来判定对应接口内部实现的处理逻辑是否合理、是否健壮。

这样看来，接口测试对于你来说，也不是一个全新的工作内容，但它还有自身的特别之处的，比如说：

- 在测试手段上，接口测试算是技术驱动和业务驱动双管齐下的工作（界面测试却是业务驱动为主的工作），因此，你需要借助一定的工具来完成它。这个工具既有可能是成熟的工具，也有可能是你自己写的代码，因此，测试技术会在接口测试阶段，变得和业务知识一样重要。
- 在工作范围上，接口测试影响的范围会更广一点，它会覆盖一部分单元测试的内容，也会覆盖一部分业务测试的内容，但是，无论是哪一部分的内容被它侵占，相对应部分的工作投入其实都减少了。

## 总结

今天我们一起聊了聊接口测试，有人说，从吃的开始聊起就很容易打开谈话的僵局，所以我们从麦当劳的汉堡开始，讲述了接口为什么重要、接口是什么以及接口测试在测些什么。我还讲了接口测试和业务测试的区别和联系，那就是“相互依存，不可分割”。

虽然我今天洋洋洒洒给你讲了很多内容，你也有可能记住的并不多，但我希望下面这三点你一定要烂熟于心：

1. 接口测试是通过设计输入和预期输出来完成测试验证的，你之前掌握的测试用例设计方法等测试基本功，在这里还是有用武之地的；
1. 接口测试是一个技术知识和业务知识相结合的工作，可以更好地提升你自己的技术实力，让那些说我们是“点工”的人早早闭嘴；
1. 接口测试也是功能测试，要说有和界面测试不同的地方，仅仅是和我们交互的，不再是开发工程师设计的界面，而是测试工具或者代码。

在很多人眼里，接口测试是技术，业务测试是业务，但它们其实是不可分割的。所以在这个专栏中，我会通过先介绍方法再引入工具，到最后用代码引入封装框架，一步一步教你完成接口测试。

## 思考题

我们今天的课程到这里就结束了，现在我想请你思考一下，你还能举出其它实际的例子，证明接口测试是质量保障环境中，必不可少的一个测试阶段吗？

我是陈磊，欢迎你在留言区留言分享你的观点，如果这篇文章让你有新的启发，也欢迎你把文章分享给你的朋友，我们一起来探讨和学习。
