在同一个上下文管理器中执行多个测试
Execute multiple tests in the same context managers
我有这样的测试设置:
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)
但我希望 nose 仍然为每个测试分别报告。我研究了模块级别和 class 级别 setup()
和 teardown()
方法,但它们似乎没有在异常情况下提供相同的清理保证。是否有一种简洁的方式让 nose
与上下文管理器协作?
看看鼻子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
class in contextlib
。如果 setup
.
中出现异常,ExitStack
可以确保您的管理器 类 正确关闭
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')
我有这样的测试设置:
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)
但我希望 nose 仍然为每个测试分别报告。我研究了模块级别和 class 级别 setup()
和 teardown()
方法,但它们似乎没有在异常情况下提供相同的清理保证。是否有一种简洁的方式让 nose
与上下文管理器协作?
看看鼻子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
class in contextlib
。如果 setup
.
ExitStack
可以确保您的管理器 类 正确关闭
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')