每当我们谈起自动化测试时,第一反应是UI自动化测试;而具有一些经验的测试人员,则会非常慎重的对待UI自动化,他们会更加倾向于接口自动化测试。究其缘由,主要是因为UI自动化通常成本较高,后期维护更加苦不堪言;而接口测试则相对轻量级一些,它是介于UI自动化和单元测试之间的一种自动化测试手段,可以兼具二者的各自优点,是业内广泛应用的一种测试技术。
在聊接口测试之前,我们需要明确什么是“接口”。这个问题对于不同的项目组可能各有不同。比如:于WEB项目组而言,接口可能就是HTTP的请求接口;而对于C++项目而言,接口可能是一个动态库文件,亦或是TCP等基础服务。于是对于不同的接口对象,我们使用的方法自然也是不一样的。
这里的动态库通常指的是linux下的.so和windows下的.dll文件,它们都是提前编译好的库文件,可以被其它C/C++程序直接调用。因为它集成了一个或多个函数,并可以提供特定的完整功能;所以它可以被作为一个独立的测试对象来进行测试。类似的Java的JAR包也可以作为接口测试的对象。
对于这种基础库的接口测试,其测试方法和单元测试很相似;选用一个测试执行框架,通常也就是单元测试的框架;然后针对特定的接口方法设计不同组合的调用参数,最后检查调用结果与期望结果的差别。当然对于一些复杂功能的模块,你可能还需要进行一些setup的工作,比如:数据初始化等。
假如你有一个叫math.dll的动态库,其实现了一个叫add的接口,那么你的接口测试代码可能是这样的。
import unittest
from ctypes import *
class TestMathDLL(unittest.TestCase):
def __init__(self):
super().__init__()
self.dll = CDLL("math.dll")
def test_add(self):
actual = self.dll.add(2, 9)
expect = 11
self.assertEqual(actual, expect)
if __name__ == '__main__':
unittest.main()
这只是一个简单的例子,在结构上和单元测试没有什么区别,只是测试的对象由原来的函数,变成了集成好的动态DLL库文件了。(很多的UI自动化测试也是这样的结构,只是对象变成了UI应用程序)
除了动态库这一类的接口之外,常见的接口测试对象就是服务类接口了;这里又以WEB服务接口为主,通常还会以RESTful形式来提供服务。它与动态库类的接口主要区别在于提供服务的调用方式不同,我们只需简单的修改下调用方式,就可以使用相同的方式来测试服务类接口。
假设你有一个/math/add的WEB服务接口,它支持POST请求方式;那么你的接口测试代码可能是这样的。
import unittest
import requests
class TestMathDLL(unittest.TestCase):
def __init__(self):
super().__init__()
self.base_url = 'http://localhost/math'
def test_add(self):
add_url = '/add'
data = {'num1': 2, 'num2': 8}
actual = requests.post(self.base_url + add_url, data=data).json()
expect = {'success': True, 'result': 10}
self.assertEqual(actual, expect)
if __name__ == '__main__':
unittest.main()
上面的两种接口测试方式,已经可以满足我们日常对接口的测试需求。它比UI自动化更轻量,更稳定,比单元测试更简单,更具有业务覆盖能力。但是跟UI自动化具有一个相同的问题,需要用例维护成本;虽然接口的变化相对于UI的变化会稳定很多,但由于一个接口调用对应于一个测试用例,会导致测试用例的激增,一旦接口发生变化,需要同步修改的接口测试用例就会很多。
针对这类问题的解决思路,一种是提到测试代码的提炼程度,尽量避免重复代码;另一种是根据接口的参数形式和可接收类型,自动生成测试代码。
除了上述的2种解决方法之外,还有另外一种就是统一化的接口测试平台。即所有的测试用例使用同一套测试流程代码,唯一不同的是测试输入数据,测试结果检查。针对这些可变的内容,在平台上提供易用的录入方式即可。通过此类方式可以很容易达到数据驱动、测试用例统一管理、测试报告统一管理的目标。
前面讲的三种都是基于用例的接口测试,而如果你不想写用例、或者对业务不是很熟,那么也许你可以考虑接口对比测试。注意这类测试比较适合开发同学,另外接口对比测试仅仅用于回归测试,而不能用例新接口/功能的测试。
接口对比测试与常规测试相比,有如下特点: