【问题标题】:Own log file for every testcase / Get name of next testcase每个测试用例都有自己的日志文件/获取下一个测试用例的名称
【发布时间】:2010-12-31 01:54:32
【问题描述】:

我想为每个测试用例设置一个新的日志文件。类似于以下内容:

import unittest
import logging

log = logging.getLogger()

class TestExample(unittest.TestCase):
    def setUp(self):
        next_testcase = ???
        self.hdl = logging.FileHandler(
                'testcase_%s.log' % next_testcase, mode='w')
        log.addHandler(self.hdl)

    def tearDown(self):
        log.removeHandler(self.hdl)

如何找到testcase的名称?

或者你会如何实现类似上面的东西?

【问题讨论】:

    标签: python unit-testing logging installation


    【解决方案1】:

    棘手! :-)

    这里的问题是你不知道下一个要调用的函数是什么——不是 不直接干扰单元测试代码。

    但是,如果可以将每个测试用例更改为另一种方法, 这将调用为该测试用例定制的“设置”,然后执行原始的 测试用例,就解决了。

    换句话说:需要自动更改您声明的类中的每个测试用例 进入另一个功能:执行个性化设置,然后他们执行 原始测试。这应该在类创建时完成。

    这可能看起来很复杂,但它相当适合“元类” - 因为我们只是在做它们的本意:自定义类的创建。

    因此,通过将 TestCase 的元类更改为检查类中每个项目的元类 - 如果它是一个测试(即,如果它的名称以“test”开头),则创建一个新的包装函数 完成上述功能,你就可以开始了。

    (还需要进一步的步骤:由于方法名称和(用于)原始测试方法的(对象)在创建后必须保持不变,因此必须创建一个中间函数来为每个测试用例保留闭包。否则,下面代码中的变量method_nameoriginal_method都将设置为for循环结束时类中最后一个函数的名称和内容)

    你去吧:

    # -*- coding: utf-8 -*-
    import unittest
    import logging
    
    #template method:
    def log_setup(self, name):
        #self.hdl = logging.FileHandler('testcase_%s.log' % name, mode='w')
        #log.addHandler(self.hdl)
        self.name = name
    
    
    class MetaTestCase(type):
        def __new__(cls, cls_name, bases, dict):
            for name, item in dict.items():
                if name.startswith("test"):
                    def scope_freezer(method_name, original_method):
                        def wrapper(self, *args, **kw):
                            log_setup(self, method_name)
                            return original_method(self, *args, **kw)
                        return wrapper
                    dict[name] = scope_freezer(name, item)
            return type.__new__(cls, cls_name, bases, dict)
    
    
    class TestExample(unittest.TestCase):
        __metaclass__ = MetaTestCase
        def test_a(self):
            print self.name
    
        def test_b(self):
            print self.name
    
        def tearDown(self):
            pass
            #log.removeHandler(self.hdl)
    
    unittest.main()
    

    (为了简化我这边的测试,我注释掉了实际的日志记录行 - “打印”工作正常 - log_setup 函数中的任何代码都将在 selfname 正确设置的情况下运行。)

    当然,您可以将这个元类分解到另一个模块中,然后将其导入以用于您的测试。

    【讨论】:

    • 感谢您更改方法而不是尝试挂钩单元测试的提示,非常优雅!我过去广泛使用过元类,是的,我同意它们有点难以理解,但它是一个非常强大的 Python 特性。而且由于我只需要接触一次类,因此我将使用一个简单的类装饰器。
    【解决方案2】:
    
    
    import unittest
    import logging
    
    def log_setup(self, name):
        print name
    
    
    class TestExample(unittest.TestCase):
    
        def test_method_name(self):
            print self.method_name
    
        def __getattribute__(self, name):
            safe_getattr =  super(TestExample, self).__getattribute__
    
            if name.startswith("test_"):
                self.method_name = name
                log_setup(self, name)
    
            return safe_getattr(name)
    
    
    
    if __name__ == "__main__":
        unittest.main()
    

    【讨论】:

      猜你喜欢
      • 2020-08-05
      • 1970-01-01
      • 1970-01-01
      • 2013-08-31
      • 1970-01-01
      • 1970-01-01
      • 2021-11-18
      • 1970-01-01
      • 2021-12-10
      相关资源
      最近更新 更多