在同一上下文管理器中执行多个测试

2024-09-30 22:18:22 发布

您现在位置:Python中文网/ 问答频道 /正文

我有这样的测试设置:

def test1():
    with Manager1() as m1, m1.get_m2() as m2:
        do_test1(m1, m2)

def test2():
    with Manager1() as m1, m1.get_m2() as m2:
        do_test2(m1, m2)

我用nosetests运行它。现在发现上下文管理器的__enter__()__exit__()方法非常昂贵,所以我想改为如下设置:

def test():
    with Manager1() as m1, m1.get_m2() as m2:
        do_test1(m1, m2)
        do_test2(m1, m2)

但我还是想为每个测试分别报告。我研究了模块级和类级的setup()teardown()方法,但它们似乎没有为异常情况下的清理提供相同的保证。有没有干净的方法让nose与上下文管理器协作?你知道吗


Tags: 方法管理器getdefaswithexitnosetests
2条回答

看看鼻子test generation。如果您将代码更改为使用yield,它可能会起作用,例如:

from nose.tools import nottest

@nottest
def do_test1(m1, m2):
    m1.write('do_test1 f1')
    m2.write('do_test1 f2')

@nottest
def do_test2(m1, m2):
    m1.write('do_test2 f1')
    m2.write('do_test2 f2')


def test():
    with open('f1.txt', 'wb') as m1, open('f2.txt', 'wb') as m2:
        yield do_test1, m1, m2
        yield do_test2, m1, m2

运行测试可以让您:

$ nosetests context.py -v
context.test(<open file 'f1.txt', mode 'wb' at 0x06A5BF40>, <open file 'f2.txt', mode 'wb' at 0x06A5BF98>) ... ok
context.test(<open file 'f1.txt', mode 'wb' at 0x06A5BF40>, <open file 'f2.txt', mode 'wb' at 0x06A5BF98>) ... ok

                                   
Ran 2 tests in 0.004s

OK

如果您担心setup中引发的异常导致teardown方法无法调用,那么可以使用^{}中的^{}类。如果ExitStack中出现异常,setup可以确保管理器类正确关闭。你知道吗

from io import StringIO
from contextlib import ExitStack

managers = []
close_managers = None

def setup():
    global close_managers
    with ExitStack() as exit_stack:
        managers[:] = [exit_stack.enter_context(StringIO()) for _ in range(2)]
        # any exception raised before this line will will cause all the __exit__
        # methods of the given context managers to be called. So this should
        # be the last part of setup
        close_managers = exit_stack.pop_all().close

def teardown():
    m1, m2 = managers
    assert m1.getvalue() == 'test1 m1\ntest2 m1\n'
    assert m2.getvalue() == 'test1 m2\ntest2 m2\n'
    close_managers()

def test1():
    m1, m2 = managers
    m1.write('test1 m1\n')
    m2.write('test1 m2\n')    

def test2():
    m1, m2 = managers
    m1.write('test2 m1\n')
    m2.write('test2 m2\n')

相关问题 更多 >