使用 py.test 对 python 代码进行测试

时间:2023-03-09 13:33:28
使用 py.test 对 python 代码进行测试

其实以前我记得有人对我说过,写代码甚至可以先写完测试之后部署好了再开始写逻辑代码。我觉得有点吃惊和奇怪,这不是扯淡吗?

但是这次在完成了积分支付第一阶段开发之后我意识到,这可能并不是开玩笑,特别是项目可能还涉及到以前的代码进行迁移,如何保证代码迁移之后还能继续正常运行?

越是大的项目,在这个上面的维护成本就越高,如果是一人开发,既要负责测试又要负责开发,没有单元测试对这种任务来说简直就是灾难。

之前在编写openapi模块的时候也为那边的代码写过测试,但是对py.test也没有使用什么其它的特性,这次用到感觉比较通用的几个函数和用法所以纪录一下。

上个例子:

import pytest
@pytest.mark.parametrize("package_price, package_ident, begin_time, end_time", [
(-800, 1, datetime.datetime.now(), datetime.datetime.now()+datetime.timedelta(days=30)),
(800, 1, datetime.datetime.now(), datetime.datetime.now()+datetime.timedelta(days=30)),
], ids=["-钱购买爱尝鲜", "+钱购买爱尝鲜"])

来分析一下这个pytest.mark.parametrize("", [])

第一个字符串参数里面可以传你想要初始化的字段name以逗号分隔,注意它们都在一个字符串里。

后面的数组以tuple为一个元素,每个tuple里面可以初始化在前面string里面写的各参数,同样以逗号分隔。

ids是可以指定单组参数也就是一个tuple为一个单位的这组测试用例的id,这个会在测试的时候显示出来就像这样。

使用 py.test 对 python 代码进行测试

这样我们就能通过自己手动构造参数愉快的开始测试了。

但是其实除了这种简单的参数,真正在测试的时候是比较难构造的是指定的obejct对象。

这里可以引入一个叫mock的库

下面看个例子

from mock import MagicMock
order = MagicMock(id=order_id, shop_id=shop_id, user_id=user1.id, finish_time=order_finish_time)
gio = MagicMock(id=gio_id, order_id=order_id, goods_id=goods_id, goods_type=goods_type,
user_id=user1.id, shop_id=shop_id,
is_allowed_to_review=lambda: True, is_reviewed=lambda: False, order=order,
goods_paid_cash_amount=goods_paid_cash_amount)
gio.__class__ = GoodsInOrder

你用一个叫mock的库来轻易构造那些看似复杂的需要传递大量参数的对象。上面那些参事可以在parametrize里面构造好然后传入MagicMock里要初始化的对象里面去,就能按照你的想法初始化出这个对象。给测试带来极大便利。

mock库在python3.4中已加入标准库。不过在python2.7里面还需要通过pip install mock安装。

下面贴上一个完整的例子.

@pytest.mark.parametrize("package_price, package_ident, begin_time, end_time", [
(-800, 1, datetime.datetime.now(), datetime.datetime.now()+datetime.timedelta(days=30)),
(800, 1, datetime.datetime.now(), datetime.datetime.now()+datetime.timedelta(days=30)),
], ids=["-钱买不起爱尝鲜", "+钱也买不起爱尝鲜"])
def test_can_not_buy_fresh_member(package_price, package_ident, begin_time, end_time, user4):
with pytest.raises(NoEnoughAvailablePoints):
decrease_points_by_fresh_member(user4.id, package_price, package_ident, begin_time, end_time)

Reference:

https://wangshunping.gitbooks.io/testing_python/content/chapter3/Mock_and_Patch.html  Mock和Patch小技巧