如何在所有类的所有测试之前运行方法?
Posted
技术标签:
【中文标题】如何在所有类的所有测试之前运行方法?【英文标题】:How to run a method before all tests in all classes? 【发布时间】:2013-07-21 23:57:18 【问题描述】:我正在编写 selenium 测试,其中包含一组类,每个类都包含几个测试。每个类当前打开然后关闭 Firefox,这有两个后果:
超级慢,打开 firefox 需要的时间比在课堂上运行测试要长... 崩溃,因为在关闭 firefox 后,尝试从 selenium 快速重新打开它会导致“错误 54”我可以通过添加睡眠来解决错误 54,但它仍然会非常慢。
所以,我想做的是在 所有 测试类中重用相同的 Firefox 实例。这意味着我需要在所有测试类之前运行一个方法,在所有测试类之后运行另一个方法。所以,'setup_class' 和 'teardown_class' 是不够的。
【问题讨论】:
将scope
设置为module
还不够吗?
我需要一个函数在最后运行一次,以关闭网络浏览器。我不想在每个类/模块之后关闭网络浏览器。我也不希望它永远不会被关闭。
那么很简单:使用atexit
并注册将关闭firefox 的函数,以便在解释器退出之前执行。
谢谢。如果可能的话,我更喜欢“py.test”的方式。
您可以使用module-level teardown and setup,我正在使用会话级别的拆解和设置,但不确定它们是否仍然可用。
【参考方案1】:
按照hpk42 的建议使用会话夹具对于许多情况来说是很好的解决方案, 但是夹具只有在收集完所有测试后才会运行。
这里还有两个解决方案:
conftest 钩子
在你的conftest.py
文件中写一个pytest_configure
或pytest_sessionstart
钩子:
# content of conftest.py
def pytest_configure(config):
"""
Allows plugins and conftest files to perform initial configuration.
This hook is called for every plugin and initial conftest
file after command line options have been parsed.
"""
def pytest_sessionstart(session):
"""
Called after the Session object has been created and
before performing collection and entering the run test loop.
"""
def pytest_sessionfinish(session, exitstatus):
"""
Called after whole test run finished, right before
returning the exit status to the system.
"""
def pytest_unconfigure(config):
"""
called before test process is exited.
"""
pytest 插件
使用pytest_configure
和pytest_unconfigure
挂钩创建pytest plugin。
在conftest.py
中启用您的插件:
# content of conftest.py
pytest_plugins = [
'plugins.example_plugin',
]
# content of plugins/example_plugin.py
def pytest_configure(config):
pass
def pytest_unconfigure(config):
pass
【讨论】:
这是最好的答案。将conftest.py
放在与您希望使用相同的pytest_sessionstart
和pytest_sessionfinish
例程运行的其他测试相同的目录中。
我认为如果测试分布在多个文件中,这不起作用
这绝对适用于将测试拆分为多个文件的情况。【参考方案2】:
您可能想要使用会话范围的“自动使用”固定装置:
# content of conftest.py or a tests file (e.g. in your tests or root directory)
@pytest.fixture(scope="session", autouse=True)
def do_something(request):
# prepare something ahead of all tests
request.addfinalizer(finalizer_function)
这将在所有测试之前运行。终结器将在最后一次测试完成后被调用。
【讨论】:
如果我想在这个函数中包含一个函数范围的固定装置,这将不起作用 这是在每次测试前运行还是在测试前总共运行一次?【参考方案3】:从 2.10 版开始,有一种更简洁的方式来拆除夹具并定义其范围。所以你可以使用这个语法:
@pytest.fixture(scope="module", autouse=True)
def my_fixture():
print ('INITIALIZATION')
yield param
print ('TEAR DOWN')
自动使用参数: 来自documentation:
这是 autouse 固定装置在其他范围内的工作方式:
autouse 固定装置遵守 scope= 关键字参数:如果 autouse 固定装置的 scope='session' 它将只运行一次,无论在哪里 它被定义。 scope='class' 表示每个类都会运行一次,等等。
如果在测试模块中定义了 autouse 夹具,它的所有测试函数都会自动使用它。
如果在 conftest.py 文件中定义了 autouse 夹具,则其目录下所有测试模块中的所有测试都将调用该夹具。
...
“请求”参数: 请注意,“请求”参数对于您的目的不是必需的,尽管您可能希望将其用于其他目的。来自documentation:
"夹具函数可以接受请求对象自省 “请求”测试函数、类或模块上下文……”
【讨论】:
【参考方案4】:尝试在conftest.py
中使用pytest_sessionstart(session)
例子:
# project/tests/conftest.py
def pytest_sessionstart(session):
print('BEFORE')
# project/tests/tests_example/test_sessionstart.py
import pytest
@pytest.fixture(scope='module', autouse=True)
def fixture():
print('FIXTURE')
def test_sessonstart():
print('TEST')
日志:
BEFORE
============================================================================ test session starts =============================================================================
platform darwin -- Python 3.7.0, pytest-5.4.1, py-1.8.1, pluggy-0.13.1 -- /Library/Frameworks/Python.framework/Versions/3.7/bin/python3
cachedir: .pytest_cache
rootdir: /Users/user/Documents/test, inifile: pytest.ini
plugins: allure-pytest-2.8.12, env-0.6.2
collected 1 item
tests/6.1/test_sessionstart.py::test_sessonstart FIXTURE
TEST
PASSED
在此处阅读更多信息:https://docs.pytest.org/en/latest/reference.html#_pytest.hookspec.pytest_sessionstart
【讨论】:
以上是关于如何在所有类的所有测试之前运行方法?的主要内容,如果未能解决你的问题,请参考以下文章
使用 Test::Unit,如何在所有测试(但不是每个测试)之前运行一些代码?