我正在尝试测试张量流程序。我正在使用参数化 py.test 夹具设置张量流会话:
@pytest.fixture(scope="session", params=configuration)
def session(request):
if request.param == 'tensorflow':
return tf.Session()
elif request.param == 'tensorflow-eager':
tfe.enable_eager_execution()
return tf.Session()
elif ...
Tensorflow 具有全局状态,因此多次测试启动可能会污染它。例如,启用急切执行后无法禁用它。有没有办法指示 py.test 为每个测试创建一个新进程?或者除了使用参数化夹具之外还有另一种配置测试环境的方法?用法示例:
@pytest.mark.parametrize("bias_type", ['variable', 'ndarray', 'list', 'tuple'])
@pytest.mark.parametrize("kernel_type", ['variable', 'ndarray', 'list', 'tuple'])
@pytest.mark.parametrize("input_type", ['variable', 'ndarray', 'list', 'tuple'])
def test_convolution(session, input_type, kernel_type, bias_type):
...
正如评论中所建议的,使用
pytest-xdist
将是解决方案。该插件设计用于并行或分布式执行测试(甚至可以进行多平台执行),但非常适合满足您在单独进程中运行每个测试的请求 - 您可以使用 --forked
参数来实现这一点。
--forked
参数在 Windows 上不起作用,因为 Windows 不支持 fork-exec 模型,并且不提供任何 fork()
的替代品。
让我们定义一个固定装置,在运行每个测试之前尝试打开急切执行:
from tensorflow.contrib.eager.python import tfe
import pytest
@pytest.fixture(scope='function', autouse=True)
def eager(request):
tfe.enable_eager_execution()
这个装置显然会使所有测试失败,但第一个测试除外,因为急切执行只能转动一次。通过一些虚拟测试:
def test_spam():
assert True
def test_eggs():
assert True
def test_bacon():
assert True
运行普通
pytest
如预期失败:
$ pytest -v
============================== test session starts ================================
platform darwin -- Python 3.6.3, pytest-3.3.1, py-1.5.2, pluggy-0.6.0 -- /Users/hoefling/.virtualenvs/stackoverflow/bin/python3.6
cachedir: .cache
rootdir: /Users/hoefling/projects/private/stackoverflow/so-48234032, inifile:
plugins: forked-0.2, mock-1.6.3, hypothesis-3.44.4
collected 3 items
test_spam.py::test_spam PASSED [ 33%]
test_spam.py::test_eggs ERROR [ 66%]
test_spam.py::test_bacon ERROR [100%]
...
E ValueError: Do not call tfe.enable_eager_execution more than once in the
same process. Note eager-mode methods such as tfe.run() also call
tfe.enable_eager_execution.
...
现在安装
pytest-xdist
:
$ pip install pytest-xdist
并重新运行测试:
$ pytest -v --forked
============================== test session starts ================================
platform darwin -- Python 3.6.3, pytest-3.3.1, py-1.5.2, pluggy-0.6.0 -- /Users/hoefling/.virtualenvs/stackoverflow/bin/python3.6
cachedir: .cache
rootdir: /Users/hoefling/projects/private/stackoverflow/so-48234032, inifile:
plugins: forked-0.2, xdist-1.22.0, mock-1.6.3, hypothesis-3.44.4
collected 3 items
test_spam.py::test_spam PASSED [ 33%]
test_spam.py::test_eggs PASSED [ 66%]
test_spam.py::test_bacon PASSED [100%]
============================= 3 passed in 6.09 seconds ============================
测试仍然按顺序运行,但每个测试都在自己的子进程中,因此没有一个失败。
现在您可以开始尝试并行执行,例如
$ pytest -v --forked --numprocesses=auto
等等。请参阅插件文档了解更多信息和更多使用示例。
--forked
选项不再可从 pytest-xdist
获得;它被移动到一个名为 pytest-forked
的单独插件。所以目前您想要安装
$ pip install pytest-forked
然后,要在其自己的分叉进程上运行每个测试,请按前面所述运行
pytest
:
$ pytest --forked [...]