14

我有一组测试用例,它们都应该完成完全相同的测试,按照“方法 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,但我想了解它为什么不起作用。

4

2 回答 2

31

您可以通过利用测试运行unittest.TestCase器仅运行继承自(DjangoTestCase继承自)的测试来使用 mixin。例如:

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 方法解析顺序和多重继承。

于 2010-08-31T04:50:03.657 回答
4

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

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所说,mixin 是正确的方法。为什么我以前没看到?

更新 2

(阅读评论后)如果(1)超类方法可以避免hackishif 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):
    ...
于 2010-08-31T04:46:10.170 回答