Mock
什么是Mock
unittest.mock是一个用于在Python中进行单元测试的库,Mock翻译就是模拟,顾名思义这个库的主要功能就是模拟一些东西。
它的主要功能是使用mock对象替代掉指定的Python对象,以达到模拟对象的行为。
unittest其实是单元测试框架,单元测试是自动化测试的至高境界,其中mock是单元测试的脊髓所在。
Mock能做什么
-
前后端联调,如果你是一个前端页面开发,现在需要开发一个功能:下一个订单,支付页面的接口,根据支付结果,支付成功,展示支付成功页;支付失败,展示支付失败页。
要完成此功能,你需要调用后端的接口,根据返回给你的结果,来展示不同的页面。此时后端没有开发好,作为一个前端开发不能等别人开发好了再开发,那只能加班了。
为了同步开发完成任务,此时可以根据接口文档的规定,把接口的地址和入参传过去,然后自己mock接口的不同返回界面,来完成前端的开发任务。 -
单元测试,单元测试的目的是测试某个小小单元的功能,但现实中开发的函数和方法都是有依赖关系的,比如b函数的参数,需要调用a函数的返回结果。但我前面已经测试过a函数了,这种情况下,就不需要再测一遍a函数了,此时可以用mock模块来模拟调用这部分内容,并给出返回结果。
-
第三方接口依赖,在做接口自动化的时候,有时候需要调用第三方的接口,但是别人公司的接口服务不受控,有可能别人提供的测试环境今天开着,突然关掉了,给自动化测试带来很多麻烦,此时可以自己写一个mock-server来模拟接口的返回数据
Mock环境准备
-
python 2.x 版本,mock是独立的模块,需要用pip安装
pip install -U mock
-
从python 3.3 以后的版本mock以及合并到unittest模块中了,是unittest单元测试的一部分,直接导入即可
from unittest import mock
依赖关系
1.如下场景:
支付是一个独立的接口,由其他开发提供,根据支付的接口返回状态去显示失败还是成功,这是你需要实现的功能。
也就是说你写了个b功能,同时写一个a功能,你的b功能需要根据a功能的结果去判断,然后实现对应的功能。
这就是存在依赖关系,你同时的开发进度你无法控制。若等他完成再开发,就需要加班啦。
2.以下时自己写的zhifu_status()函数功能,大概设计如下,保存为temple.py文件
# coding:utf-8
def zhifu():
'''假设这里是一个支付的功能,未开发完
支付成功返回:{"result":"success","reason":"null"}
支付失败返回:{"result":"fail","reason":"余额不足"}
reason返回失败原因
'''
pass
def zhifu_status():
'''根据支付的结果success or fail,判断跳转到对应界面'''
result = zhifu()
print(result)
try:
if result["result"] == "success":
return "支付成功"
elif result["result"] == "fail":
print("失败原因:%s" % result["reason"])
return "支付失败"
else:
return "未知错误异常"
except:
return "Error, 服务器返回异常!"
3.单元测试用例设计
# coding:utf-8
from unittest import mock
import unittest
import temple
class test_zhifu_status(unittest.TestCase):
'''单元测试用例'''
def test_01(self):
'''测试支付成功场景'''
# mock一个支付成功的数据
temple.zhifu = mock.Mock(return_value={"result":"success","reason":"null"})
# 根据支付结果测试页面跳转
status = temple.zhifu_status()
print(status)
self.assertEqual(status,"支付成功")
def test_02(self):
'''测试支付失败场景'''
# mock一个支付失败的数据
temple.zhifu = mock.Mock(return_value={"result":"fail","reason":"余额不足"})
# 根据支付结果测试页面跳转
status = temple.zhifu_status()
print(status)
self.assertEqual(status,"支付失败")
if __name__ == "__main__":
unittest.main()