其實以前我記得有人對我說過,寫代碼甚至可以先寫完測試之后部署好了再開始寫邏輯代碼。我覺得有點吃驚和奇怪,這不是扯淡嗎?
但是這次在完成了積分支付第一階段開發之后我意識到,這可能並不是開玩笑,特別是項目可能還涉及到以前的代碼進行遷移,如何保證代碼遷移之后還能繼續正常運行?
越是大的項目,在這個上面的維護成本就越高,如果是一人開發,既要負責測試又要負責開發,沒有單元測試對這種任務來說簡直就是災難。
之前在編寫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,這個會在測試的時候顯示出來就像這樣。
這樣我們就能通過自己手動構造參數愉快的開始測試了。
但是其實除了這種簡單的參數,真正在測試的時候是比較難構造的是指定的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小技巧