首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Python的unittest模块如何检测测试用例?

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

Stack Overflow用户
提问于 2012-04-11 11:40:36
回答 2查看 7.1K关注 0票数 22

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

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

EN

回答 2

Stack Overflow用户

发布于 2012-04-11 13:07:22

所以我查看了一下我的Python27/Lib目录...

unittest.main实际上是一个类unittest.TestProgram的别名。因此,您构建了一个实例,它的__init__将运行,该实例将执行一系列健全性检查和配置,包括动态导入从中调用它的模块(它使用__import__函数,默认情况下使用__main__作为要导入的模块的名称)。因此,现在它有一个self.module属性,其中包含一个表示源代码的模块对象。

最后,它转到下面的代码:

代码语言:javascript
复制
self.test = self.testLoader.loadTestsFromModule(self.module)

其中self.testLoaderunittest.TestLoader的一个实例。该方法除了其他内容外,还包含:

代码语言:javascript
复制
    for name in dir(module):
        obj = getattr(module, name)
        if isinstance(obj, type) and issubclass(obj, case.TestCase):
            tests.append(self.loadTestsFromTestCase(obj))

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

代码语言:javascript
复制
    def isTestMethod(attrname, testCaseClass=testCaseClass,
                     prefix=self.testMethodPrefix):
        return attrname.startswith(prefix) and \
            hasattr(getattr(testCaseClass, attrname), '__call__')
    testFnNames = filter(isTestMethod, dir(testCaseClass))

因此,它使用类的dir来获取要尝试的名称列表,查找具有这些名称的属性,并选择以self.testMethodPrefix开头的属性(缺省情况下为'test')和可调用的属性(具有__call__属性)。(我真的很惊讶他们在这里没有使用内置的callable函数。我猜这是为了避免拾取嵌套类。)

票数 31
EN

Stack Overflow用户

发布于 2016-07-13 21:18:45

我写了一些代码,试图实现与下面的unittest.main()类似的行为。总之,我遍历模块,对于不是以“unittest”开头的模块,我检查它的成员。然后,如果这些成员是一个类,并且是unittest.TestCase的子类,我将解析该类的成员。然后,如果这些类的成员是以“test”开头的函数或方法,我会将其添加到测试列表中。类对象的__dict__用于内省方法/函数,因为使用inspect.getmembers可能会显示太多内容。最后,将测试列表转换为元组并包装为套件。然后在详细级别2使用运行器运行套件。当然,请注意,如果您不想要这个限制,可以删除函数/方法名称开头的检查'test‘的正则表达式,以便将bar_test()包含在测试列表中。

代码语言:javascript
复制
#!/usr/bin/env python

import unittest
import inspect
import sys
import re

class Foo(unittest.TestCase):
   @staticmethod
   def test_baz():
      pass

   @classmethod
   def test_mu(cls):
      pass

   def test_foo(self):
      self.assertEqual('foo', 'foo')

   def bar_test(self):
      self.assertEqual('bar', 'bar')

class Bar:
   pass

if __name__ == '__main__':
   runner = unittest.TextTestRunner(verbosity=2)
   tests = []
   is_member_valid_test_class = lambda member: inspect.isclass(member) and \
      issubclass(member, unittest.TestCase)

   for module_name, module_obj in sys.modules.items():
      if not re.match(r'unittest', module_name):
         for cls_name, cls in inspect.getmembers(
            module_obj, is_member_valid_test_class):
            for methname, methobj in cls.__dict__.items():
               if inspect.isroutine(methobj) and re.match(r'test', methname):
                  tests.append(cls(methname))

   suite = unittest.TestSuite(tests=tuple(tests))
   runner.run(suite)

结果输出为:

代码语言:javascript
复制
test_foo (__main__.Foo) ... ok
test_baz (__main__.Foo) ... ok
test_mu (__main__.Foo) ... ok

----------------------------------------------------------------------
Ran 3 tests in 0.001s

OK
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10099491

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档