【问题标题】:How to log the name of the test class, if the test method resides in a class common for all tests?如果测试方法驻留在所有测试通用的类中,如何记录测试类的名称?
【发布时间】:2019-09-01 17:25:52
【问题描述】:

我的项目结构如下:

/root
  /tests
    common_test_case.py
    test_case_1.py
    test_case_2.py
    ...
  project_file.py
  ...

每个测试test_case_... 都继承自unittest.TestCasecommon_test_case.CommonTestCaseCommonTestCase 类包含应该由所有测试执行的测试方法(尽管使用每个测试唯一的数据,在测试的self.something 中存储和访问)。如果某个特定的测试用例需要一些特定的测试,它们会被直接添加到那个特定的类中。

目前我正在努力将日志记录添加到我的测试中。除其他外,我想记录运行该方法的类(因为上面的方法意味着不同类的相同测试方法名称)。我想坚持使用内置的logging 模块来实现这一点。

我尝试了以下LogRecord attributes:%(filename)s%(module)s%(pathname)s。不过,对于common_test_case.py 中定义的方法,它们都将路径/名称返回到common_test_case.py,而不是它们实际运行的测试模块。

我的问题是:

  1. 有没有办法实现我想要的,只使用内置的logging 模块?
  2. 使用一些第三方/其他模块(我在想可能是inspect 的一些“hacky”解决方案)?
  3. 是否有可能实现(在 Python 中)?

【问题讨论】:

  • 您的记录器是如何配置的?
  • @DroidX86,它实际上是每个测试断言的包装器(我没有在这里包含细节,有点“隔离”问题)。演示记录器配置的代码 sn-p 位于 another question of mine

标签: python python-3.x python-2.7 unit-testing logging


【解决方案1】:

I've found 的解决方案(到目前为止,它确实有效):

import inspect

class_called_from = inspect.stack()[1][0].f_locals['self'].__class__.__name__

不过,我仍然想知道,是否有“更清晰”的方法,或者是否可以使用 logging 模块来实现。


食谱,基于West's answer(在 Python 3.6.1 上测试):

test_name = self.id().split('.')[-1]
class_called_from = self.id().split('.')[-2]

【讨论】:

    【解决方案2】:

    您的问题与one 类似,并通过以下方式解决:

    self.id()
    

    请参阅函数定义here,它调用self.__class__ 以获得实例化的TestCase 类的实例。鉴于您使用的是多重继承,multiple inheritance rules from Python 应用:

    对于大多数目的,在最简单的情况下,您可以将搜索从父类继承的属性视为深度优先,从左到右,而不是在同一类中搜索两次等级制度。

    这意味着common_test_case.CommonTestCase 将被搜索然后unittest.TestCase。如果common_test_case.CommonTestCase 中没有 id 函数,事情应该像它仅派生自 unittest.TestCase 一样工作。如果你觉得需要在CommonTestCase 中添加一个id 函数,类似这样(如果真的有必要的话):

    def id(self):
      if issubclass(self,unittest.TestCase):
        return super(unittest.TestCase,self).id()
    

    【讨论】:

    • 在我的例子中,测试方法不是直接从 test 调用的,而是从另一个类继承的(参见有问题的详细描述)。这就是为什么这种方法将输出的不是当前运行的测试类,而是该方法在其中定义的测试类(这不是我想要的)。我错过了什么吗?
    • 感谢更新中的解释。尽管common_test_case.CommonTestCase 并非继承自unittest.TestCase。我没有这样做,以防止 CommonTestCase 测试自行运行(实际上使用来自 this answer 的配方)。
    • 这无关紧要,除非您的常用测试定义了 id 函数。
    • 确实,它有效(从一开始就应该测试)。 self.id().split('.')[-1] — 给出一个测试名称; self.id().split('.')[-2] — 给出一个类,从中调用了测试 。并且没有 hacky inspect 电话!。感谢您的回答和多次阐述。
    猜你喜欢
    • 1970-01-01
    • 2012-11-10
    • 2023-04-07
    • 2019-04-09
    • 1970-01-01
    • 2012-03-28
    • 2019-01-23
    • 1970-01-01
    • 2011-02-10
    相关资源
    最近更新 更多