1何为幂等性?
幂等(idempotent)或幂等性(idempotence)源自数学。在抽象代数中,有一整套理论上是关于幂等的。幂等的数学定义,远远超出网络上所谓的:"如果满足f(x)=f(f(x)),那么f就是幂等的"。文章源自玩技e族-https://www.playezu.com/194515.html
对于从事计算机领域的我们来说,没有必要去深究幂等的数学理论。在计算机领域,幂等有一个十分通俗的定义:如果一个操作执行多次与执行一次的效果相同,那么这个操作就是幂等的。幂等的对立面是非幂等。在非幂等操作中,执行多次的效果与执行一次的效果不同。文章源自玩技e族-https://www.playezu.com/194515.html
例如,查询数据库中某个用户的账号名,这个操作就是幂等的。因为无论我们查询多少次,效果都一样。而每调用一次,就会生成一个新订单的操作,就不是幂等的。因为执行N次会生成N个订单,与执行一次只生成一个订单的效果是不一样的。文章源自玩技e族-https://www.playezu.com/194515.html
2HTTP的幂等性文章源自玩技e族-https://www.playezu.com/194515.html
事实上,幂等性的通俗定义(执行多次与执行一次的效果相同)看似很简单,其实很容易产生误解。文章源自玩技e族-https://www.playezu.com/194515.html
我们有必要结合具体的场景,来更准确地把握幂等性的内涵。幂等性经常用于描述HTTP方法(对资源的操作)。下面,我们就结合HTTP,来澄清几个常见的幂等性认知误区。文章源自玩技e族-https://www.playezu.com/194515.html
(1) 我拿到一份接口说明文档,里面的GET、PUT、DELETE方法一定是幂等的,POST方法一定不是幂等的吗?文章源自玩技e族-https://www.playezu.com/194515.html
答案是不一定。原因很简单,虽然在IETF制定的HTTP标准(RFC7231)中,提到GET、PUT、DELETE等方法应当是幂等的,而POST方法不是幂等的。但是,HTTP的这部分标准只是建议(SHOULD),而不是强制(MUST)。文章源自玩技e族-https://www.playezu.com/194515.html
在实际中,没有遵从HTTP标准的接口定义相当常见。文章源自玩技e族-https://www.playezu.com/194515.html
比如,HTTP标准建议,POST方法用来创建由服务端分配ID的资源(区别于PUT方法,后者用来创建由客户端指定ID的资源)。由于每次调用POST,都会在服务端创建一个全新的资源,因而在标准中,它不是幂等的。文章源自玩技e族-https://www.playezu.com/194515.html
在实际中,如果POST方法被用来更新资源,那么它就变成幂等的。毕竟,将一个指定的资源更新10次,与更新一次的效果是一样的。
又比如,HTTP标准建议,DELETE方法用来删除指定的资源。由于删除10次与删除一次一样,都只删除了一个资源,因此在标准中,它是幂等的。
在实际中,如果DELETE接口被定义为删除系统里存在时间最长的资源,那么它就不是幂等的。毕竟,这时候删除10次会删除10个不同的资源,与删除1次的效果不一样。
(2) 对于幂等的HTTP方法,重复执行时,返回结果一定是一样的吗?
答案是不一定。事实上,幂等性与HTTP的响应内容没有关系。在幂等性的定义中,重复执行的效果相同,指的不是重复执行时收到的服务端响应状态码或响应体相同,而是指服务端资源的状态没有发生变化或者变化情况相同。
对于DELETE方法来说,在第一次调用,资源成功删除时,服务端响应200;在第二次调用,资源已经删除时,服务端返回404。两次调用返回结果不同,但是资源在服务端的状态变化是相同的,都是变成已删除状态。
同样的道理,对于GET方法来说,它之所以是幂等的,并不是因为GET某个资源返回的结果一样,而是因为无论GET一个资源多少次,这个资源的状态没有发生变化。
(3) 对于幂等的HTTP方法,重复执行时,服务端资源的变化一定相同吗?
答案是不一定。原因在于,幂等性是关于客户端所请求的资源的。对于非客户端所请求的资源,其是否发生变化,如何发生变化,与幂等性没有关系。
例如,服务端在收到请求时,可能会写日志。这时候,对于日志资源来说,当进行幂等操作(例如删除账号信息)时,多次执行与一次执行,日志资源的变化是不一样的。但是没有关系,删除账号操作仍然是幂等的。
(4) 幂等方法一定是安全的吗?
答案是不一定。安全和幂等,是HTTP方法的两个不同属性。HTTP方法是安全的,指的是这个方法不会改变服务端资源状态,例如只读的HTTP方法GET、HEAD。对于幂等方法,资源状态可以不变,也可以变化,只要多次变化的情况与一次变化相同即可。
因此,安全的HTTP方法一定是幂等的,而幂等的HTTP方法不一定是安全的。
3幂等性与接口测试
谈了这么多理论,重点还是要看看幂等性的应用。下面,就谈谈幂等理论在接口测试中的应用。在接口测试中,幂等理论有三种应用场景。
(1) 接口级的幂等性测试
根据上面的讨论,在阅读接口文档时,不能天真地根据接口方法名称来判断接口是否具有幂等性。一定要抓住幂等性的核心,即客户端所请求的资源在服务端的状态变化情况来做判断。
例如,查询指定资源,删除指定资源,以相同的方式修改指定资源,创建指定ID的资源,这些接口无论取哪个HTTP方法名,都应当是幂等的。
但是,我们很难只通过调用单个接口,来校验这个接口是否以幂等地方式实现。毕竟,单个接口的能力有限,可能无法让我们获取服务端的资源状态变化情况。
这时,我们往往需要调用多个接口来校验。例如,要测试删除接口的幂等性,可以通过连续调用删除 -> 查询 -> 删除 -> 再查询四个接口来实现。
(2) 业务级的幂等性测试
在实际中,比接口级幂等性更重要的是业务级的幂等性。以常见的订单扣款场景为例,业务上的需求是,对于同一个订单不能造成两次扣款。站在幂等理论的角度来看,这就是一个幂等性需求,即多次扣款的结果与一次扣款一样。
订单扣款的需求,可能由一个HTTP接口实现,也可能由多个HTTP接口实现。此时,接口的实现方式不重要,单个接口是否幂等也不是重点。测试应该聚焦业务的幂等性,并设计各种异常场景的测试用例,来验证是否发生重复扣款。
(3) 接口测试自身的幂等性
不仅接口有幂等性,业务有幂等性,事实上幂等性有普遍意义。有一种观点就认为,测试用例自身就需要具备幂等性。
什么意思呢?就是说测试用例多次执行,与单次执行的效果一样。当然,这里的效果一样,并不是说发现的问题一样,毕竟多次执行相比单次执行更有能力发现偶现问题。而是指用例多次执行后的被测系统状态与一次执行后、甚至没有执行时相同。
这种观点其实与我们所强调的用例独立性不谋而合。用例不只有测试步骤,还有SETUP和TEARDOWN。在TEARDOWN中,尤其要做好资源的释放和环境的清理,从而避免对当前用例的再次执行或者其他用例的执行产生影响。