【问题标题】:Get name of current test in setup using nose使用鼻子在设置中获取当前测试的名称
【发布时间】:2013-05-18 14:01:59
【问题描述】:

我目前正在使用鼻子编写一些功能测试。我正在测试的库操纵目录结构。

为了获得可重现的结果,我存储了一个测试目录结构的模板,并在执行测试之前创建了一个副本(我在测试setup 函数中执行此操作)。这可以确保我在测试开始时始终具有明确定义的状态。

现在我还有两个要求:

  1. 如果测试失败,我希望覆盖或删除它操作的目录结构,以便分析问题。
  2. 我希望能够并行运行多个测试。

这两个要求都可以通过为每个执行的测试创建一个具有不同名称的新副本来解决。出于这个原因,我想访问当前在 setup 函数中执行的测试的名称,以便我可以适当地命名副本。有什么方法可以实现吗?

一个说明性的代码示例:

def setup_func(test_name):
    print "Setup of " + test_name

def teardown_func(test_name):
    print "Teardown of " + test_name

@with_setup(setup_func, teardown_func)
def test_one():
    pass

@with_setup(setup_func, teardown_func)
def test_two():
    pass

预期输出:

Setup of test_one
Teardown of test_one
Setup of test_two
Teardown of test_two

将名称作为参数注入将是最好的解决方案,但我也愿意接受其他建议。

【问题讨论】:

    标签: python unit-testing testing nose nosetests


    【解决方案1】:

    如果您不想继承 unittest.TestCase 或使用自定义装饰器(如其他答案中所述),您可以通过挖掘调用堆栈来获取信息:

    import inspect
    
    def get_current_case():
        '''
        Get information about the currently running test case.
    
        Returns the fully qualified name of the current test function
        when called from within a test method, test function, setup or 
        teardown.
    
        Raises ``RuntimeError`` if the current test case could not be
        determined.
    
        Tested on Python 2.7 and 3.3 - 3.6 with nose 1.3.7.
        '''
        for frame_info in inspect.stack():
            if frame_info[1].endswith('unittest/case.py'):
                return frame_info[0].f_locals['self'].id()
        raise RuntimeError('Could not determine test case')
    

    【讨论】:

    • 正是我一直在寻找的。谢谢!
    【解决方案2】:

    我有一个适用于测试功能的解决方案,使用自定义装饰器:

    def with_named_setup(setup=None, teardown=None):
        def wrap(f):
            return with_setup(
                lambda: setup(f.__name__) if (setup is not None) else None, 
                lambda: teardown(f.__name__) if (teardown is not None) else None)(f)
        return wrap
    
    @with_named_setup(setup_func, teardown_func)
    def test_one():
        pass
    
    @with_named_setup(setup_func, teardown_func)
    def test_two():
        pass
    

    这重用了现有的with_setup 装饰器,但将装饰函数的名称绑定到作为参数传递的setupteardown 函数。

    【讨论】:

      【解决方案3】:

      听起来像self._testMethodNameself.id() 应该适合你。这些是unittest.TestCase 类的属性和方法。例如:

      from django.test import TestCase
      
      
      class MyTestCase(TestCase):
          def setUp(self):
              print self._testMethodName
              print self.id()
      
          def test_one(self):
              self.assertIsNone(1)
      
          def test_two(self):
              self.assertIsNone(2)
      

      打印:

      ...
      AssertionError: 1 is not None
      -------------------- >> begin captured stdout << ---------------------
      test_one
      path.MyTestCase.test_one
      
      --------------------- >> end captured stdout << ----------------------
      ...
      AssertionError: 2 is not None
      -------------------- >> begin captured stdout << ---------------------
      test_two
      path.MyTestCase.test_two
      
      --------------------- >> end captured stdout << ----------------------
      

      另见:

      希望对您有所帮助。

      【讨论】:

      • 嗯,感谢您的建议,但我更喜欢不需要从 unittest.TestCase 派生的解决方案。
      • 当然,知道了。我认为您在装饰器中使用__name__ 的解决方案看起来不错。
      猜你喜欢
      • 2012-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-08
      • 1970-01-01
      • 2012-09-26
      • 2014-11-10
      相关资源
      最近更新 更多