前言
有时候,在测试过程中,可能会用到测试桩。举个例子,模块A是我们的被测试系统,但是模块A需要从模块B获取到需要的数据才能正常运行,但是模块B还没有ready,那这种情况下如何测试模块A呢?这个时候就需要一个测试桩,用测试桩来模拟模块B响应模块A的请求。
基本原理
尤其是一些新手,一听到测试桩,可能就懵逼了,觉得是一个超级高大上的东西。其实它的原理非常简单,几行代码就能搞定的事情。通常情况下,测试桩就是一个运行着的普通http/https服务,本身没有业务逻辑,仅仅被动响应被测试系统的请求,返回预定义的结构化的测试数据。这里听上去比较拗口,但是感觉也不太好用人话表述,直接上图吧。
这里一定要弄清楚谁是被测试系统,谁是测试桩,之前在评审一个测试的时候,发现一个员工稀里糊涂废了半天劲,把被测试系统给模拟掉了,自动化用例直接调用测试桩,我当时想死的心都有了。
结构分析
既然原理这么简单,那实现起来肯定也不会复杂。起一个http服务,跟前请求的路径和方法,响应对应的结构化数据就可以了。
我们举个例子。
当收到http get请求,并且路径名称是“/getinfo”的时候,返回状态码200,外加响应数据;
当收到http get请求,并且路径名称不是“/getinfo”的时候,返回404;
当收到http post请求,并且路径名称是“/profile”的时候,返回状态码200,外加响应数据;
当收到http post请求,并且路径名称不是“/profile”的时候,返回404。
这个例子的逻辑够清晰吧? 废话不多说,直接上源代码(这里的代码是当年用python2写的,如果现在用flask实现,会更加精炼)。
#!/usr/bin/python2
# coding: utf-8
import BaseHTTPServer, SimpleHTTPServer
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
import ssl
class MyHttpHandler(BaseHTTPRequestHandler):
# 定义函数,用于处理http get请求
def do_GET(self):
# 当请求path为/getinfo的时候,响应200
if self.path.find("/getinfo") >= 0:
result_code = 200
content = '{"app0":{"8103":"IOS_FakeAkina.B","8102":"100","0100":"2"}}'
# 否则,响应404
else:
result_code = 404
content = '{"message": "not found"}}'
self.send_response(result_code)
self.send_header("Content-type", "text/plain; charset=UTF-8")
self.send_header("Content-Length", str(len(content)))
self.end_headers()
self.wfile.write(content)
# 定义函数,用于处理http post请求
def do_POST(self):
# 当请求path为/profile的时候,响应200
if self.path.find("/profile") >= 0:
result_code = 200
content = '{"app0": {8102: "400"}}'
# 否则,响应404
else:
result_code = 404
content = '{"message": "not found"}}',
self.send_response(result_code)
self.send_header("Content-type", "text/plain; charset=UTF-8")
self.send_header("Content-Length", str(len(content)))
self.end_headers()
self.wfile.write(content)
# 定义http server的端口和IP地址,指定ssl证书,启动http server
httpd = BaseHTTPServer.HTTPServer(('10.64.21.31', 443), MyHttpHandler)
httpd.socket = ssl.wrap_socket(httpd.socket, certfile='./server.pem', server_side=True)
httpd.serve_forever()
运行效果
为了展示运行效果,这里简单写了几个自动化测试用例来直接请求测试桩(重要的话说三遍,真实情况下,测试用例不可能直接调用测试桩,测试用例请求的一定是被测试系统)。
测试用例
如下代码,在txt文件中简单定义了4个测试用例,对应上述的4种情况。
*** Settings ***
Library Collections
Library RequestsLibrary
*** Test Cases ***
Get_200
Create Session api https://10.64.21.31
${response} Get Request api /getinfo
log code: ${response.status_code}, content: ${response.content}
Delete All Sessions
Get_404
Create Session api https://10.64.21.31
${response} Get Request api /information
log code: ${response.status_code}, content: ${response.content}
Delete All Sessions
Post_200
${request_string} Set Variable {"key001":"value001","key002":"value002"}
${request_param} To Json ${request_string}
${headers} Set Variable {"Content-type":"text/plain"}
${headers} To Json ${headers}
Create Session api https://10.64.21.31
${response} Post Request api /profile json=${request_param} headers=${headers}
Create Session api https://10.64.21.31
log code: ${response.status_code}, content: ${response.content}
Delete All Sessions
Post_404
${request_string} Set Variable {"key001":"value001","key002":"value002"}
${request_param} To Json ${request_string}
${headers} Set Variable {"Content-type":"text/plain"}
${headers} To Json ${headers}
Create Session api https://10.64.21.31
${response} Post Request api /myprofile json=${request_param} headers=${headers}
Create Session api https://10.64.21.31
log code: ${response.status_code}, content: ${response.content}
Delete All Sessions
启动测试桩
$ python2 debug_stub.py
执行测试用例
测试用例执行结果如下。
这个时候,测试桩终端会打印出对应的请求。
很简单吧。