如何在所有类中的所有测试之前运行方法?

时间:2013-07-23 04:04:10

标签: python selenium pytest

我正在编写selenium测试,其中包含一组类,每个类包含多个测试。每个类当前打开然后关闭Firefox,这有两个结果:

  • 超级慢,打开firefox需要比在课堂上运行测试更长的时间......
  • 崩溃了,因为在firefox关闭后,试图从selenium中快速重新打开它会导致'错误54'

我可以通过添加睡眠来解决错误54,但它仍然会超级慢。

所以,我想要做的是在所有测试类中重用相同的Firefox实例。这意味着我需要在所有测试类之前运行一个方法,在所有测试类之后运行另一个方法。因此,'setup_class'和'teardown_class'是不够的。

4 个答案:

答案 0 :(得分:34)

使用hpk42建议的会话夹具对于很多情况都是很好的解决方案, 但夹具只有在收集完所有测试后才会运行。

以下是另外两个解决方案:

conftest hooks

conftest.py文件中写下pytest_configurepytest_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_configurepytest_unconfigure个钩子创建pytest pluginconftest.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

答案 1 :(得分:32)

您可能希望使用会话范围的“autouse”夹具:

# 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)

这将在所有测试之前运行。最终测试完成后将调用终结器。

答案 2 :(得分:11)

Starting from version 2.10 there is a cleaner way to tear down the fixture as well as defining its scope. So you may use this syntax:

@pytest.fixture(scope="module", autouse=True)
def my_fixture():
    print ('INITIALIZATION')
    yield param
    print ('TEAR DOWN')

The autouse parameter: From documentation:

Here is how autouse fixtures work in other scopes:

  • autouse fixtures obey the scope= keyword-argument: if an autouse fixture has scope='session' it will only be run once, no matter where it is defined. scope='class' means it will be run once per class, etc.

  • if an autouse fixture is defined in a test module, all its test functions automatically use it.

  • if an autouse fixture is defined in a conftest.py file then all tests in all test modules below its directory will invoke the fixture.

    ...

The "request" parameter: Note that the "request" parameter is not necessary for your purpose although you might want to use it for other purposes. From documentation:

"Fixture function can accept the request object to introspect the “requesting” test function, class or module context.."

答案 3 :(得分:1)

尝试在pytest_sessionstart(session)中使用conftest.py

示例:

# 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