Skip to main content
 首页 » 编程设计

python之如何使用自己的方法从外部库扩充类

2025年05月04日14Terrylee

我有一些特殊情况需要在 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 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,实际上在运行时更改 3rd 方类是不受欢迎的,但根据您需要进行的更改,它可能是解决错误或确保每次使用该类时都有您的新方法的唯一方法.

因为使用你的方法的唯一测试将是你的测试,所以猴子补丁是不必要的,并且子类化 TestCase 是非常合理的。通常,当您需要扩充现有类的方法时,您会使用 monkeypatching。例如,如果您希望在现有测试用例中对 TestCase.assertEqual 的调用增加逻辑以与 Option 对象进行比较,您可以使用 monkeypatch TestCase.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) 失败,即使 Option 实例相等,您也不需要编写新的 assertOptionsEqual 方法。您可能只需要 Option 对象来正确定义 __eq__。

所以假设你有:

class KnownGoodInputs(TestCase): 
    def test_good_options(self): 
        first, second = systemUnderTestGetOptions(...) 
        self.assertOptionsEqual(first, second) 

上面的first和second是什么类?

对于所有 Python 内置类型,assertEqual 应该有效。对于自定义 Option 类,只需执行如下操作:

类选项(对象): def init( self ): use_foo = 假 use_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)