Python: 如何在单元(鼻子)测试期间忽略装饰器?
Python: How to ignore decorators during unit (nose) tests?
我想忽略代码中的某些装饰器以跳过相关功能,但仅当 运行ning 作为单元测试的一部分时。这能做到吗?
例如,我有一个函数 f,它用 numba 装饰器定义,如下所示:
@numba.jit
def f(a, b):
return a + b
当我 运行 调用上述函数的单元测试时,我不希望 numba 魔术发生,因为它会减慢速度并在某些平台上导致错误。是否可以在某个地方进行设置,告诉 nose 运行 测试,而无需应用任何 numba 即时(and/or 所有 numba)装饰器?
您也许可以欺骗 nose 使用您自己的装饰器来保持功能不变。
写一个包含这个函数的文件numba.py
:
def jit(func):
return func
并放置在您的 PYTHONPATH 中。
运行 您从这个文件所在的目录进行测试,或者在
你的测试文件作为第一行:
import sys
sys.path.insert(0, 'path/to/dir/with/myfile')
或者,您可以将环境变量 PYTHONPATH
设置为文件所在的目录。
Windows:
set PYTHONPATH=%PYTHONPATH%;path/to/dir/with/myfile
Unix/Mac:
export PYTHONPATH=$PYTHONPATH$:path/to/dir/with/myfile
您可以使用您可以控制的新装饰器修补装饰器:
import functools
def patch(parent, obj_name, switch_reg, switch_name):
def gen_switcher():
def wrapper(func):
ori_wrapped = ori_decorator(func)
@functools.wraps(func)
def _(*args, **kwargs):
if switch_reg.get(switch_name, False):
func_to_call = func
else:
func_to_call = ori_wrapped
print(func_to_call)
return func_to_call(*args, **kwargs)
return _
return wrapper
ori_decorator = getattr(parent, obj_name)
setattr(parent, obj_name, gen_switcher())
与:
# have to patch the decorator before applying it
import numba
switchs = {}
patch(numba, 'jit', switchs, 'DISABLE_NUMBA_JIT')
@numba.jit
def f(a, b):
return a + b
f(1, 2)
产量:
CPUDispatcher(<function f at 0x10a5f90d0>)
然后:
# this part could be rewrited as a context manager
switchs['DISABLE_NUMBA_JIT'] = True
f(1, 2)
得到:
<function f at 0x10a5f90d0>
仅对于 numba,您可以设置一个环境变量(例如 export NUMBA_DISABLE_JIT=1
)以使 jit 装饰器无操作。
http://numba.pydata.org/numba-doc/dev/user/troubleshoot.html#disabling-jit-compilation
我会将函数分离到您单元测试的非装饰部分 -- 然后让您的真实函数具有装饰器并简单地调用辅助函数:
@numba.jit
def f(a, b):
return f_undecorated(a, b)
def f_undecorated(a, b):
return a + b
仅为f_undecorated
编写单元测试。
如果您正在使用 coverage
,您可以通过在 coverage
命令之前添加 NUMBA_DISABLE_JIT=1
来修改 CI .yml
文件:
NUMBA_DISABLE_JIT=1 coverage run -p "test_*.py"
我想忽略代码中的某些装饰器以跳过相关功能,但仅当 运行ning 作为单元测试的一部分时。这能做到吗?
例如,我有一个函数 f,它用 numba 装饰器定义,如下所示:
@numba.jit
def f(a, b):
return a + b
当我 运行 调用上述函数的单元测试时,我不希望 numba 魔术发生,因为它会减慢速度并在某些平台上导致错误。是否可以在某个地方进行设置,告诉 nose 运行 测试,而无需应用任何 numba 即时(and/or 所有 numba)装饰器?
您也许可以欺骗 nose 使用您自己的装饰器来保持功能不变。
写一个包含这个函数的文件numba.py
:
def jit(func):
return func
并放置在您的 PYTHONPATH 中。 运行 您从这个文件所在的目录进行测试,或者在 你的测试文件作为第一行:
import sys
sys.path.insert(0, 'path/to/dir/with/myfile')
或者,您可以将环境变量 PYTHONPATH
设置为文件所在的目录。
Windows:
set PYTHONPATH=%PYTHONPATH%;path/to/dir/with/myfile
Unix/Mac:
export PYTHONPATH=$PYTHONPATH$:path/to/dir/with/myfile
您可以使用您可以控制的新装饰器修补装饰器:
import functools
def patch(parent, obj_name, switch_reg, switch_name):
def gen_switcher():
def wrapper(func):
ori_wrapped = ori_decorator(func)
@functools.wraps(func)
def _(*args, **kwargs):
if switch_reg.get(switch_name, False):
func_to_call = func
else:
func_to_call = ori_wrapped
print(func_to_call)
return func_to_call(*args, **kwargs)
return _
return wrapper
ori_decorator = getattr(parent, obj_name)
setattr(parent, obj_name, gen_switcher())
与:
# have to patch the decorator before applying it
import numba
switchs = {}
patch(numba, 'jit', switchs, 'DISABLE_NUMBA_JIT')
@numba.jit
def f(a, b):
return a + b
f(1, 2)
产量:
CPUDispatcher(<function f at 0x10a5f90d0>)
然后:
# this part could be rewrited as a context manager
switchs['DISABLE_NUMBA_JIT'] = True
f(1, 2)
得到:
<function f at 0x10a5f90d0>
仅对于 numba,您可以设置一个环境变量(例如 export NUMBA_DISABLE_JIT=1
)以使 jit 装饰器无操作。
http://numba.pydata.org/numba-doc/dev/user/troubleshoot.html#disabling-jit-compilation
我会将函数分离到您单元测试的非装饰部分 -- 然后让您的真实函数具有装饰器并简单地调用辅助函数:
@numba.jit
def f(a, b):
return f_undecorated(a, b)
def f_undecorated(a, b):
return a + b
仅为f_undecorated
编写单元测试。
如果您正在使用 coverage
,您可以通过在 coverage
命令之前添加 NUMBA_DISABLE_JIT=1
来修改 CI .yml
文件:
NUMBA_DISABLE_JIT=1 coverage run -p "test_*.py"