从模块中运行unittest.main()?

2 投票
2 回答
5097 浏览
提问于 2025-04-15 11:37

我写了一个小函数,可以动态地定义unittest.TestCase类(下面是个简单的版本)。

当我把这个函数从原来的文件中移到一个新的模块时,我不知道怎么让unittest找到这些新定义的类。从任意一个文件中调用unittest.main()都没有执行任何测试。

factory.py:

import unittest

_testnum = 0
def test_factory(a, b):

    global _testnum

    testname = 'dyntest' + str(_testnum)

    globals()[testname] = type(testname, (unittest.TestCase,), {'testme': lambda self: self.assertEqual(a, b)})

    _testnum += 1


def finish():
    unittest.main()

someotherfile.py:

from factory import test_factory, finish


test_factory(1, 1)
test_factory(1, 2)


if __name__ == '__main__':
    finish()

输出:

----------------------------------------------------------------------
Ran 0 tests in 0.000s

OK

所以没有执行任何测试。

注意,把所有内容放在同一个文件里是可以正常工作的:

import unittest

_testnum = 0
def test_factory(a, b):

    global _testnum

    testname = 'dyntest' + str(_testnum)

    globals()[testname] = type(testname, (unittest.TestCase,), {'testme': lambda self: self.assertEqual(a, b)})

    _testnum += 1


test_factory(1, 1)
test_factory(1, 2)

if __name__ == '__main__':
    unittest.main()

输出(如预期):

.F
======================================================================
FAIL: testme (__main__.dyntest1)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "partb.py", line 11, in <lambda>
    globals()[testname] = type(testname, (unittest.TestCase,), {'testme': lambda self: self.assertEqual(a, b)})
AssertionError: 1 != 2

----------------------------------------------------------------------
Ran 2 tests in 0.008s

FAILED (failures=1)

我该如何使用我的test_factory()函数,以便从一个单独的源文件中执行它定义的所有TestCase对象呢?

2 个回答

10

大致的意思是(unittest.main为你做的事情)是:

suite = unittest.TestLoader().loadTestsFromTestCase(SomeTestCase)
unittest.TextTestRunner(verbosity=2).run(suite)

根据这个链接,你的测试案例被test_factory函数隐藏在globals()里面。所以你只需要用dir()命令,找到那些是unittest.TestCase实例的全局变量(或者名字以'dyntest'开头的),然后就可以这样构建你的测试套件并运行它。

8

默认情况下,unittest.main() 会在主模块中寻找单元测试的 TestCase 对象。而 test_factory 则是在它自己的模块中创建这些 TestCase 对象。这就是为什么把它移到主模块之外会导致你看到的那种情况。

你可以试试:

def finish():
    unittest.main(module=__name__)

撰写回答