Python nose 测试继承:从子类加载单元测试夹具

7 投票
1 回答
3095 浏览
提问于 2025-04-17 16:13

我正在把一个Python项目的测试套件从unittest转换到nose。这个项目原来的框架(基于unittest)有点笨重,里面有很多定制的代码来发现和运行测试,所以我想迁移到nose,让一切变得更简单。

不过,我在生成测试套件的代码上遇到了一些问题。

这个项目的框架有两种运行测试的方法。第一种是

class TestSomething(unittest.TestCase):

    def setUp(self):
        ...

    def test_x(self):
        ...

    def test_y(self):
        ...

suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestSomething))

这是“直接”的方法,所有的Nose示例和教程都是这样讲的,而且确实有效。但是第二种方法是定义一个测试类,这个类包含所有的测试逻辑,然后在不同的子类中创建测试用例,这些子类有不同的设置配置,并且从父类继承测试:

class TestSomething(unittest.TestCase):

    def test_x(self):
        ...

    def test_y(self):
        ...

class TestCase1(TestSomething):

    def setUp(self):
        ...

class TestCase2(TestSomething):

    def setUp(self):
        ...

suite = unittest.TestSuite()

cases = [TestCase1,TestCase2]
suite.addTests([unittest.makeSuite(case) for case in cases])

但是Nose在这里就出问题了。它试图先运行测试方法,这显然不行,因为父类中没有setUp()方法,而且在test_x()和test_y()中用到的很多变量还没有定义。

我没有找到任何地方有类似的例子,而且Nose的文档(相对稀少且难以浏览)似乎也没有提到这个问题。请问如何才能让这个在nose中正常工作呢?任何帮助都将非常感激。

1 个回答

15

首先,正如unutbu提到的,你不应该给TestSomething这个类起个以Test开头的名字,因为nose会自动把这样的类当作测试用例来处理。而且,nose会运行它找到的所有TestCase的子类,所以这样做:

class Something(unittest.TestCase):
    ...

会得到和你现在一样的结果。我觉得你不应该继承TestCase,而是把这个类当作一个混合类来使用:

class Something(object):
    def test_x(self):
        # here the various assertEqual etc. do not resolve, but you can use them
        # as if they were present, since in real test-cases they will be inherited
        # from unittest.TestCase.
        ...
    ...

class TestCase1(unittest.TestCase, Something):
    def setUp(self):
        ...

另一种方法是把这个类的__test__属性设置为False

class TestSomething(unittest.TestCase):
    __test__ = False
    def test_x(self):
        ...


class TestCase1(TestSomething):
    __test__ = True  #must put this
    def setUp(self):
        ...

或者你可以使用nose.istestnose.nottest来标记哪个类是测试用例,哪个不是:

@tools.nottest
class TestSomething(unittest.TestCase):
    def test_x(self):
        ...

@tools.istest
class TestCase1(TestSomething):
    sef setUp(self):
        ...

撰写回答