如何将测试方法添加到一组Django TestCase派生类?

时间:2010-08-31 03:59:51

标签: python django unit-testing subclassing

我有一组测试用例,所有测试用例都应完全相同,方法是“方法x是否返回现有文件的名称?”

我认为最好的方法是从TestCase派生的基类,它们都共享,并简单地将测试添加到该类。不幸的是,测试框架仍然试图为基类运行测试,它没有意义。

class SharedTest(TestCase):
    def x(self):
        ...do test...

class OneTestCase(SharedTest):
    ...my tests are performed, and 'SharedTest.x()'...

我试图通过检查来简单地跳过测试,如果它是在基类的对象上调用而不是像这样的派生类:

    class SharedTest(TestCase):
        def x(self):
            if type(self) != type(SharedTest()):
                ...do test...
            else:
                pass

但得到了这个错误:

ValueError: no such test method in <class 'tests.SharedTest'>: runTest

首先,我想要做任何优雅的建议。其次,虽然我真的不想使用type()hack,但我想理解为什么它不起作用。

2 个答案:

答案 0 :(得分:24)

你可以利用mixin,利用测试运行器只运行继承自unittest.TestCase的测试(Django的TestCase继承自的测试。)例如:

class SharedTestMixin(object):
    # This class will not be executed by the test runner (it inherits from object, not unittest.TestCase.
    # If it did, assertEquals would fail , as it is not a method that exists in `object`
    def test_common(self):
         self.assertEquals(1, 1)


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

有关其工作原理的更多信息,请搜索python方法解析顺序和多重继承。

答案 1 :(得分:2)

我遇到了类似的问题。我无法阻止正在执行的基类中的测试方法,但我确保它没有执行任何实际的代码。我通过检查属性并在设置时立即返回来完成此操作。此属性仅为Base类设置,因此测试在除基类之外的其他任何地方运行。

class SharedTest(TestCase):
    def setUp(self):
        self.do_not_run = True

    def test_foo(self):
        if getattr(self, 'do_not_run', False):
            return
        # Rest of the test body.

class OneTestCase(SharedTest):
    def setUp(self):
        super(OneTestCase, self).setUp()
        self.do_not_run = False

这有点像黑客。有可能更好的方法来执行此操作但我不确定如何

更新

作为sdolan says,mixin是正确的方法。为什么我之前没有看到它?

更新2

(阅读评论后)如果(1)超类方法可以避免hackish if getattr(self, 'do_not_run', False):检查,那将是很好的; (2)如果测试次数准确计算。

有可能这样做。 Django选择并执行tests中的所有测试类,无论是tests.py还是具有该名称的包。如果测试超类声明测试模块,则不会发生这种情况。它仍然可以由测试类继承。例如,SharedTest可以位于app.utils中,然后由测试用例使用。这将是上述解决方案的更简洁版本。

# module app.utils.test
class SharedTest(TestCase):
    def test_foo(self):
        # Rest of the test body.

# module app.tests
from app.utils import test
class OneTestCase(test.SharedTest):
    ...