Python 如何使用自己的方法从外部库扩充类?
我需要在django测试一些特殊情况。我试图通过编写自己的测试用例来扩展现有的django测试。以下是我目前的做法Python 如何使用自己的方法从外部库扩充类?,python,class,inheritance,methods,monkeypatching,Python,Class,Inheritance,Methods,Monkeypatching,我需要在django测试一些特殊情况。我试图通过编写自己的测试用例来扩展现有的django测试。以下是我目前的做法 from django.tests import TestCase # define my own method as a function def assertOptionsEqual(self, first, second): # logic here pass # Attach the method to the TestCase class. This
from django.tests import TestCase
# define my own method as a function
def assertOptionsEqual(self, first, second):
# logic here
pass
# Attach the method to the TestCase class. This feels inelegant!
TestCase.assertOptionsEqual = assertOptionsEqual
# tests go here
class KnownGoodInputs(TestCase):
def test_good_options(self):
self.assertOptionsEqual(...)
虽然这样做有效,但将方法定义为以self
作为第一个参数的函数,然后将其附加到TestCase
会让人觉得不雅观。有没有更好的方法用我自己的方法扩充TestCase
类?我可以做到这一点
class MyTestCase(TestCase):
def assertOptionsEqual(self, first, second):
...
并对所有测试使用
MyTestCase
,但不知道是否有更好的替代方案。谢谢 我想你已经涵盖了这两个选项。您可以使用子类或monkeypatch。通常,monkeypatching,即在运行时实际更改第三方类是不受欢迎的,但根据您需要进行的更改,这可能是解决bug或确保每次使用该类时都有新方法的唯一方法
因为使用您的方法的唯一测试将是您的测试,所以monkeypatching是不必要的,并且子类化TestCase
是非常合理的。通常,当需要扩充现有类的方法时,您会使用monkeypatching。例如,如果您希望在现有测试用例中对TestCase.assertEqual
的调用增加逻辑以与Option
对象进行比较,您可以通过执行以下操作来monkeypatchTestCase.assertEqual
以包括自定义逻辑及其正常逻辑:
originalAssertEqual = TestCase.assertEqual
def newAssertEqual(self, first, second):
result = originalAssertEqual(first, second)
if isinstance(first, Option) and isinstance(second, Option):
# do your custom comparison
return result
TestCase.assertEqual = newAssertEqual
然而,至少在这个例子中,似乎子类和monkeypatches都是不必要的
假设问题是调用self.assertEqual(firstOptions,secondOptions)
失败,即使选项
实例相等,也不需要编写新的assertOptionsEqual
方法。您可能只需要使用选项
对象来正确定义\uuuuueq\uuuu
假设你有:
class KnownGoodInputs(TestCase):
def test_good_options(self):
first, second = systemUnderTestGetOptions(...)
self.assertOptionsEqual(first, second)
上面的first
和second
的类别是什么
对于所有Python内置类型,assertEqual
应该可以工作。对于自定义选项
类,只需执行以下操作:
类选项(对象):
def初始化(自身):
使用_foo=False
使用_bar=True
def __eq__(self, other):
if (self.use_foo == other.use_foo and
self.use_bar == other.use_bar):
return True
return False
然后假设first
和second
是Option
的实例,您可以编写测试,如下所示:
class KnownGoodInputs(TestCase):
def test_good_options(self):
first, second = systemUnderTestGetOptions(...)
self.assertEqual(first, second)
那就直接子类化并使用另一个方法名怎么样?谢谢你的详细回答!尝试定义
\uuuu eq\uuuu
是第一选择。但是,被比较的对象是Django原生对象(聚合、查询集等),它们没有定义\uuuuueq\uuuuuu
。因此,我要么必须为一些本地Django对象monkeypatch一个\uuuuuueq\uuuuuu
方法,要么monkeypatch测试用例。所以我想我是想从这两种罪恶中选择较小的一种!;)