在这种情况下,我想检查内部类方法被调用了多少次。我有一个敏感的云任务,必须根据某些情况进行计数。我想用一个单元测试来增强我的应用程序,以断言特定函数被调用的次数。
为了在一个简单得多的场景中做到这一点,我想在以下脚本中进行测试:
class HMT:
def __init__(self):
self.buildedList = []
def handle(self, string_to_explode: str):
for exploded_part in string_to_explode.split(","):
self.doCoolThings(exploded_part)
def doCoolThings(self, fetched_raw_string: str):
self.buildedList.append("Cool thing done: " + fetched_raw_string)
根据我传递给handle
函数的字符串,doCoolThings
将被调用N次(在这种简单的情况下,仅取决于字符串中的命令数(。
我可以通过计算builderList
:中产生的元素的数量来进行测试
import unittest
from HMT import HMT
class test_HMT(unittest.TestCase):
def setUp(self):
self.hmt = HMT()
def test_hmt_3(self):
string_to_test = "alpha,beta,gamma"
self.hmt.handle(string_to_test)
self.assertEqual(3, len(self.hmt.buildedList))
def test_hmt_2(self):
string_to_test = "delta,epsilon"
self.hmt.handle(string_to_test)
self.assertEqual(2, len(self.hmt.buildedList))
但在实际场景中,不会有一个可用的公共类列表,该列表的元素数量总是与调用函数doCoolThings
的次数相匹配。
那么,如何在不需要检查列表元素计数的情况下检查doCoolThings
被调用了多少次呢?
我知道我可以在每次调用doCoolThings
时增加的类中放入一个计数器,然后将其公开到外部进行检查。但我不想把与我的业务规则没有直接关系的代码行搞砸。
在@jarmod评论之后,我进入了这个代码的版本:
def mydecorator(func):
def wrapped(*args, **kwargs):
wrapped.calls += 1
return func(*args, **kwargs)
wrapped.calls = 0
return wrapped
class HMT:
def __init__(self):
self.buildedList = []
def handle(self, string_to_explode: str):
for exploded_part in string_to_explode.split(","):
self.doCoolThings(exploded_part)
@mydecorator
def doCoolThings(self, fetched_raw_string: str, *args, **kwargs):
self.buildedList.append("Cool thing done: " + fetched_raw_string)
测试:
import unittest
from HMT import HMT
class test_HMT(unittest.TestCase):
def test_hmt_3_dec(self):
hmt = HMT()
string_to_test = "epsilon,ota,eta"
hmt.handle(string_to_test)
self.assertEqual(3, hmt.doCoolThings.calls)
def test_hmt_3(self):
hmt = HMT()
string_to_test = "alpha,beta,gamma"
hmt.handle(string_to_test)
self.assertEqual(3, len(hmt.buildedList))
但仍然无法正常工作。当我运行测试时,我收到:
.F
======================================================================
FAIL: test_hmt_3_dec (myTest.test_HMT)
----------------------------------------------------------------------
Traceback (most recent call last):
File "D:UsersdaniltmpmyDecmyTest.py", line 10, in test_hmt_3_dec
self.assertEqual(3, hmt.doCoolThings.calls)
AssertionError: 3 != 6
----------------------------------------------------------------------
Ran 2 tests in 0.001s
FAILED (failures=1)
更多的测试表明,测试运行了两次,但计数器在新的实例化中都没有重置。
无论如何,最初的想法是在内部类方法中动态地放置一个观察器,并在每次触发这些方法时从外部获取(尽管如此,这似乎不是使用decorator解决的问题(。
非常感谢你的回答(如果有人知道如何重置装饰器中的计数器,我也会很感激(。
from HMT import HMT
count = 0
def counter(f):
def wrap(*args, **kwargs):
global count
count += 1
return f(*args, **kwargs)
return wrap
class test_HMT(unittest.TestCase):
def setUp(self):
self.hmt = HMT()
# Add decorator.
self.hmt_no_decorator = self.hmt.doCoolThings
self.hmt.doCoolThings = counter(self.hmt.doCoolThings)
def test_doCoolThings_count(self):
repeat = 3
[self.hmt.doCoolThings() for _ in range(repeat)]
self.assertEqual(counter, repeat)
def tearDown(self):
# Remove decorator.
self.hmt.doCoolThings = self.hmt_no_decorator
...
- doCoolThings不会在业务代码中修改。您只需获取计数行为即可进行测试
- 您可以通过用对象替换count var来消除全局var。。或者真的做任何其他事情。但这在测试中重要吗