问题背景
在 Python 中测试函数调用顺序是一个常见的需求。例如,您可能有一个对象 Obj
,其中包含三个方法:method1
、method2
和 method3
。您还编写了一个函数 do_something
,该函数调用这些方法。您想编写一个测试来测试 do_something
函数和 Obj
对象。但是,您不想直接模拟或改变 Obj
对象的行为。您需要一种方法来获取在 obj
对象上调用的方法列表,而无需更改其行为。
解决方案
方法一:使用 trace
包
您可以使用 trace
包来获取在 obj
对象上调用的方法列表。trace
包是一个 Python 内置的调试工具,它允许您跟踪函数的调用和返回。
要使用 trace
包,您需要先安装它。您可以使用以下命令安装 trace
包:
pip install trace
安装完成后,您就可以使用 trace
包了。以下是如何使用 trace
包来获取在 obj
对象上调用的方法列表:
import sys
import trace
# 创建一个 Trace 对象,告诉它要忽略哪些目录,以及是要进行跟踪还是行计数。
tracer = trace.Trace(
ignoredirs=[sys.prefix, sys.exec_prefix],
trace=0,
count=1)
# 使用给定的跟踪器运行新命令。
tracer.run('main()')
# 生成报告,并将输出放在当前目录中。
r = tracer.results()
r.write_results(show_missing=True, coverdir=".")
trace
包会生成一个报告,其中包含了在 obj
对象上调用的方法列表。您可以使用这个报告来测试 do_something
函数和 Obj
对象。
方法二:使用 Wrapper
类
您还可以创建一个通用的 Wrapper
类来封装您的对象并跟踪对它的更改。Wrapper
类会拦截对对象的所有属性访问并将其记录下来。
以下是如何编写一个 Wrapper
类:
class Obj:
def method1(self):
print 'method1'
def method2(self):
print 'method2'
def method3(self):
print 'method3'
class Wrapper:
def __init__(self, wrapped):
self.calls = []
self._wrapped = wrapped
def __getattr__(self, n):
self.calls.append(n)
return getattr(self._wrapped, n)
要使用 Wrapper
类,您可以像这样:
obj = Obj()
x = Wrapper(obj)
x.method2()
x.method1()
x.method3()
print(x.calls)
输出:
['method2', 'method1', 'method3']
您可以使用 Wrapper
类来测试 do_something
函数和 Obj
对象。
代码例子
以下是如何使用 trace
包和 Wrapper
类来测试 do_something
函数和 Obj
对象:
使用 trace
包
import sys
import trace
class Obj:
def method1(self):
print 'method1'
def method2(self):
print 'method2'
def method3(self):
print 'method3'
def do_something():
obj = Obj()
obj.method2()
obj.method1()
obj.method3()
# 创建一个 Trace 对象,告诉它要忽略哪些目录,以及是要进行跟踪还是行计数。
tracer = trace.Trace(
ignoredirs=[sys.prefix, sys.exec_prefix],
trace=0,
count=1)
# 使用给定的跟踪器运行新命令。
tracer.run('do_something()')
# 生成报告,并将输出放在当前目录中。
r = tracer.results()
r.write_results(show_missing=True, coverdir=".")
使用 Wrapper
类
class Obj:
def method1(self):
print 'method1'
def method2(self):
print 'method2'
def method3(self):
print 'method3'
class Wrapper:
def __init__(self, wrapped):
self.calls = []
self._wrapped = wrapped
def __getattr__(self, n):
self.calls.append(n)
return getattr(self._wrapped, n)
def do_something():
obj = Obj()
obj.method2()
obj.method1()
obj.method3()
# 创建一个 Wrapper 对象,并用它来封装 Obj 对象。
x = Wrapper(obj)
# 调用 do_something() 函数。
do_something()
# 打印出在 Obj 对象上调用的方法列表。
print(x.calls)
输出:
['method2', 'method1', 'method3']
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。