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

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_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 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_sessionstartpytest_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

【讨论】:

以上是关于如何在所有类的所有测试之前运行方法?的主要内容,如果未能解决你的问题,请参考以下文章

TestNG配置注解

Java--TestNG

使用 Test::Unit,如何在所有测试(但不是每个测试)之前运行一些代码?

如何使用Maven运行多个测试类或测试方法?

如何在测试失败后但在任何 @After 方法之前让 JUnit 4.8 运行代码?

testNG 常用的注解