在 Django TestCase 派生类中优雅地添加公共测试方法

89 阅读3分钟

1.在 Django 中,测试用例通常继承自 TestCase 类,以便访问框架提供的各种测试帮助方法,比如 setUp()tearDown() 方法。有时我们需要为一组测试用例添加一个公共的测试方法,以便在所有这些测试用例中都运行相同的测试。例如,我们可能需要检查一个方法是否返回一个现有文件的文件名。一种常见的方法是在所有需要运行该测试的测试用例中复制粘贴相同的测试方法。然而,这种方法既不优雅也不可维护,尤其是当我们需要维护大量测试用例时。

  1. 解决方案

我们可以使用 mixin 来优雅地解决这个问题。mixin 是一个类,它包含了我们希望在其他类中使用的公共方法和属性。我们可以创建一个 mixin 类,其中包含公共的测试方法,然后让所有需要运行该测试的测试用例继承自这个 mixin 类。这样,就不需要在每个测试用例中复制粘贴相同的测试方法了。

mixni 还允许你将公共的方法和属性导入到一个类中。这样,你就可以在类中使用公共的方法和属性,而无需继承自公共的基类。这可以使你的代码更加灵活和可重用。

下面是一个使用 mixin 来为一组测试用例添加公共测试方法的示例:

# module app.utils.test
class SharedTestMixin(object):
    # This class will not be executed by the test runner (it inherits from object, not unittest.TestCase.)
    # This means that the test runner won't try to run the test_common method.
    def test_common(self):
        self.assertEquals(1, 1)

# module app.tests
from app.utils.test import SharedTestMixin
class TestOne(TestCase, SharedTestMixin):
    def test_something(self):
        pass

    # test_common is also run

class TestTwo(TestCase, SharedTestMixin):
    def test_another_thing(self):
        pass

    # test_common is also run

在上面的示例中,我们创建了一个 mixin 类 SharedTestMixin,其中包含了公共的测试方法 test_common()。然后,我们让两个测试用例 TestOneTestTwo 继承自这个 mixin 类。这样,当我们运行测试时,test_common() 方法就会在所有这些测试用例中运行。

还可以使用元类来解决这个问题。元类是创建一个类的类。我们可以在元类中定义一个方法,该方法会在创建类时自动执行。我们可以使用这个方法将公共的测试方法添加到类中。

下面是一个使用元类来为一组测试用例添加公共测试方法的示例:

# module app.utils.test
class SharedTestMeta(type):
    def __new__(mcs, name, bases, attrs):
        # Check if the class is a subclass of TestCase.
        if not issubclass(attrs.get('__base__'), unittest.TestCase):
            # The class is not a subclass of TestCase.
            # Do nothing and return the class as is.
            return super(SharedTestMeta, mcs).__new__(mcs, name, bases, attrs)

        # The class is a subclass of TestCase.
        # Add the test_common method to the class.
        attrs['test_common'] = lambda self: self.assertEqual(1, 1)

        # Return the class with the added test_common method.
        return super(SharedTestMeta, mcs).__new__(mcs, name, bases, attrs)

# module app.tests
from app.utils.test import SharedTestMeta
class TestOne(TestCase, metaclass=SharedTestMeta):
    def test_something(self):
        pass

class TestTwo(TestCase, metaclass=SharedTestMeta):
    def test_another_thing(self):
        pass

在上面的示例中,我们创建了一个元类 SharedTestMeta,并在其 __new__() 方法中,我们检查类是否是 TestCase 的子类。如果是,我们就将公共的测试方法 test_common() 添加到类中。然后,我们让两个测试用例 TestOneTestTwo 使用这个元类。这样,当我们运行测试时,test_common() 方法就会在所有这些测试用例中运行。