遇到問題:
因?yàn)楸救酥笆怯玫膗nittest框架寫的自動化腳本挪挤,已經(jīng)預(yù)先寫好了log日志模塊的裝飾器。后需將unittest替換成pytest蛾派,用到了pytest中功能強(qiáng)大的fixture瓤荔,但是讀取coftest.py中的fixture后,pytest的測試用例中填寫fixture的方法名骨坑,執(zhí)行,卻發(fā)現(xiàn)自己寫log裝飾器報missing 1 required positional argument
-
同時使用fixture和裝飾器代碼:
image.png -
報錯:
image.png
解決問題途徑:
發(fā)現(xiàn)同樣的情況下柬采,加上@allure.step("")裝飾器卻不會報該錯欢唾,查看allure的源碼
解決問題:
allure源碼中,發(fā)現(xiàn)裝飾器中加了一個@wraps(func)粉捻,解決上述問題
以下介紹wraps相關(guān):
Python中被裝飾后的函數(shù)礁遣,函數(shù)名等函數(shù)屬性會發(fā)生改變(相當(dāng)于另一個函數(shù)了),所以杀迹,Python的functools包中提供了一個叫wraps的裝飾器來解決該問題亡脸。它能使其保留原有函數(shù)的結(jié)構(gòu)押搪。
- 不加@wraps()的裝飾器:
import time
class MyLog(object):
def __call__(self, func):
def my_log(*args, **kwargs):
"""這里是my_log的docstring"""
start = time.time()
res = func(*args, **kwargs)
end = time.time()
print('|運(yùn)行時長:{:.4f}'.format(end - start))
return res
return my_log
@MyLog()
def is_test():
"""這里是is_test的docstring"""
print("一個測試方法")
print("__name__: ", is_test.__name__)
print("__doc__: ", is_test.__doc__)
運(yùn)行結(jié)果:
image.png
看運(yùn)行結(jié)果树酪,會發(fā)現(xiàn),被裝飾器裝飾后的函數(shù)大州,name和docstring都發(fā)生了變化
- 加了@wraps()的裝飾器:
import time
from functools import wraps
class MyLog(object):
def __call__(self, func):
@wraps(func)
def my_log(*args, **kwargs):
"""這里是my_log的docstring"""
start = time.time()
res = func(*args, **kwargs)
end = time.time()
print('|運(yùn)行時長:{:.4f}'.format(end - start))
return res
return my_log
@MyLog()
def is_test():
"""這里是is_test的docstring"""
print("一個測試方法")
print("__name__: ", is_test.__name__)
print("__doc__: ", is_test.__doc__)
運(yùn)行結(jié)果:
image.png
看運(yùn)行結(jié)果续语,會發(fā)現(xiàn),裝飾器加了@wraps后厦画,被裝飾器裝飾后的函數(shù)疮茄,還是保持原有的狀態(tài)
- 裝飾器的作用: 在不改變原有功能代碼的基礎(chǔ)上,添加額外的功能。
- @wraps(func)的作用: 不改變使用裝飾器原有函數(shù)的結(jié)構(gòu)(如name, doc)