Python的unittest模块如何检测测试用例?

stu*_*guy 18 python unit-testing

我想知道我们何时运行unittest.main(),Python如何知道子类unittest.Testcase有哪些?

例如,如果我添加一个类FromRomanBadInput(unittest.TestCase),怎么unittest知道运行它?

Kar*_*tel 30

所以我在我的Python27/Lib目录中环顾四周......

unittest.main实际上是一个类的别名unittest.TestProgram.那么你要构建一个这样的实例及其__init__运行,它会进行一系列的健全性检查和配置,包括动态导入你调用它的模块(它使用__import__函数,__main__作为模块的名称)默认情况下导入).所以它现在有一个self.module包含代表你的源的模块对象的属性.

最终,它得到了这个代码:

self.test = self.testLoader.loadTestsFromModule(self.module)
Run Code Online (Sandbox Code Playgroud)

在哪里self.testLoader是一个实例unittest.TestLoader.该方法包含以下内容:

    for name in dir(module):
        obj = getattr(module, name)
        if isinstance(obj, type) and issubclass(obj, case.TestCase):
            tests.append(self.loadTestsFromTestCase(obj))
Run Code Online (Sandbox Code Playgroud)

所以它使用dir你的模块对象来获取你定义的所有全局变量的名称(包括类),过滤那些派生自的类unittest.TestCase(本地,case.TestCase是它的别名),然后查找里面的测试方法那些要添加到tests列表中的类.该搜索行为类似:

    def isTestMethod(attrname, testCaseClass=testCaseClass,
                     prefix=self.testMethodPrefix):
        return attrname.startswith(prefix) and \
            hasattr(getattr(testCaseClass, attrname), '__call__')
    testFnNames = filter(isTestMethod, dir(testCaseClass))
Run Code Online (Sandbox Code Playgroud)

所以它使用dir的类的拿到的名单去尝试,寻找与这些名字的属性,并选择那些以启动self.testMethodPrefix('test'默认),并且是可调用的(有,反过来,一个__call__属性).(我真的很惊讶他们在callable这里没有使用内置函数.我想这是为了避免使用嵌套类.)

  • @KarlKnechtel:嗯,事实上你真的用这个答案帮我**了.:)我为单元测试和整个测试用例编写了一个装饰器,并想知道测试运行器为什么不执行装饰测试用例.运行上面的代码,我意识到我忘了我的装饰器(没有参数)将我的unittest.TestCase子类变成一个完全不同的对象...... (3认同)

pyl*_*ver 7

'main'函数搜索在导入的模块中继承unittest.TestCase的所有类.和当前路径,然后尝试运行以'test'开头的每个方法

来自python的文档:

import random
import unittest

class TestSequenceFunctions(unittest.TestCase):

    def setUp(self):
        self.seq = range(10)

    def test_shuffle(self):
        # make sure the shuffled sequence does not lose any elements
        random.shuffle(self.seq)
        self.seq.sort()
        self.assertEqual(self.seq, range(10))

        # should raise an exception for an immutable sequence
        self.assertRaises(TypeError, random.shuffle, (1,2,3))

    def test_choice(self):
        element = random.choice(self.seq)
        self.assertTrue(element in self.seq)

    def test_sample(self):
        with self.assertRaises(ValueError):
            random.sample(self.seq, 20)
        for element in random.sample(self.seq, 5):
            self.assertTrue(element in self.seq)

if __name__ == '__main__':
    unittest.main()
Run Code Online (Sandbox Code Playgroud)

通过继承unittest.TestCase创建一个测试用例.使用名称以字母test开头的方法定义三个单独的测试.此命名约定通知测试运行器哪些方法代表测试.