我正在用Python编程,我想知道我是否可以测试我的代码中是否调用了函数
def example():
pass
example()
#Pseudocode:
if example.has_been_called:
print("foo bar")
我该怎么做?
答案 0 :(得分:25)
如果函数知道自己的名称是可以的,可以使用函数属性:
def example():
example.has_been_called = True
pass
example.has_been_called = False
example()
#Actual Code!:
if example.has_been_called:
print("foo bar")
您还可以使用装饰器来设置属性:
import functools
def trackcalls(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
wrapper.has_been_called = True
return func(*args, **kwargs)
wrapper.has_been_called = False
return wrapper
@trackcalls
def example():
pass
example()
#Actual Code!:
if example.has_been_called:
print("foo bar")
答案 1 :(得分:1)
标准记忆功能如下所示:
def memoize(func):
memo = {}
def wrapper(*args):
if not args in memo:
memo[args] = func(*args)
return memo[args]
return wrapper
你装饰你的功能:
@memoize
def example():
pass
在python3.2中,您可以使用functools.lru_cache代替memoziation函数。
import functools
@functools.lru_cache(maxsize=None)
def example():
pass
答案 2 :(得分:0)
这是一个装饰师,会使用colorama观察你的所有功能,并返回一个不错的输出。
try:
import colorama
except ImportError:
class StdClass: pass
def passer(*args, **kwargs): pass
colorama = StdClass()
colorama.init = passer
colorama.Fore = StdClass()
colorama.Fore.RED = colorama.Fore.GREEN = ''
def check_for_use(show=False):
if show:
try:
check_for_use.functions
except AttributeError:
return
no_error = True
for function in check_for_use.functions.keys():
if check_for_use.functions[function][0] is False:
print(colorama.Fore.RED + 'The function {!r} hasn\'t been called. Defined in "{}" '.format(function, check_for_use.functions[function][1].__code__.co_filename))
no_error = False
if no_error:
print(colorama.Fore.GREEN + 'Great! All your checked function are being called!')
return check_for_use.functions
try:
check_for_use.functions
except AttributeError:
check_for_use.functions = {}
if colorama:
colorama.init(autoreset=True)
def add(function):
check_for_use.functions[function.__name__] = [False, function]
def func(*args, **kwargs):
check_for_use.functions[function.__name__] = [True, function]
function(*args, **kwargs)
return func
return add
@check_for_use()
def hello():
print('Hello world!')
@check_for_use()
def bonjour(nb):
print('Bonjour tout le monde!')
# hello(); bonjour(0)
hello()
check_for_use(True) # outputs the following
输出:
Hello world!
The function 'bonjour' hasn't been called. Defined in "path_to_file.py"
答案 3 :(得分:0)
我们可以使用模拟。模拟
from unittest import mock
def check_called(func):
return mock.Mock(side_effect=func)
@check_called
def summator(a, b):
print(a + b)
summator(1, 3)
summator.assert_called()
assert summator.called == True
assert summator.call_count > 0
summator.assert_called_with(1, 3)
summator.assert_called_with(1, 5) # error
# AssertionError: Expected call: mock(1, 5)
# Actual call: mock(1, 3)
答案 4 :(得分:0)
使用标准库中的unittest.mock.Mock
的一个最小示例:
from unittest.mock import Mock
def example():
pass
example_mock = Mock(side_effect=example)
example_mock()
#Pseudocode:
if example_mock.called:
print("foo bar")
运行脚本后控制台输出:
foo bar
这种方法很好,因为它不需要您修改example
函数本身,如果您想在某些单元测试代码中执行此检查而无需修改源代码本身(例如,EG存储has_been_called
属性,或将函数包装在装饰器中。
如the documentation for the unittest.mock.Mock
class中所述,side_effect
构造函数的Mock()
参数指定“每当调用Mock时都要调用的函数”。
Mock.called
属性指定“一个表示是否已调用模拟对象的布尔值”。
Mock
类还具有其他可能有用的属性,例如EG:
call_count
:一个整数,告诉您模拟对象被调用了多少次
call_args
:这是“无”(如果尚未调用该模拟),或者是上次使用该模拟调用的参数
call_args_list
:这是按顺序对模拟对象进行的所有调用的列表(因此列表的长度是其被调用的次数)。在进行任何呼叫之前,它是一个空列表
Mock
类还具有方便的方法,可根据调用Mock
对象的次数以及使用EG调用的参数来制作断言语句:
assert_called_once_with(*args, **kwargs)
:断言该模拟只被调用了一次,并且该调用带有指定的参数