与 selenium 并行运行 pytest 时出现 pytest_sessionfinish 错误

问题描述 投票:0回答:1

我在

conftest
文件中有此代码(使用
pytest
+
selenium
运行自动化):

import os
from urllib import request

import pytest
from selenium.webdriver.chrome.options import Options
import allure
from selenium import webdriver


@pytest.fixture(autouse=True)
def setup(request):
    global driver
    options = Options()
    options.add_experimental_option("detach", True)
    options.add_argument("--headless")
    # options.add_argument("--no-sandbox")
    options.add_argument("--disable-dev-shm-usage")
    # options = webdriver.ChromeOptions()
    driver = webdriver.Chrome(options=options)
    request.cls.driver = driver
    driver.maximize_window()
    driver.get("https://magento.softwaretestingboard.com/")
    yield
    driver.quit()


def pytest_exception_interact(report):
    if report.failed:
        allure.attach(body=driver.get_screenshot_as_png(), name="screenshot",
                      attachment_type=allure.attachment_type.PNG)


def pytest_sessionfinish() -> None:
    environment_properties = {
     'browser': driver.name,
     'driver_version': driver.capabilities['browserVersion']
    }
    allure_env_path = os.path.join("allure-results", 'environment.properties')
    with open(allure_env_path, 'w') as f:
        data = '\n'.join([f'{variable}={value}' for variable, value in environment_properties.items()])
        f.write(data)

并行运行 pytest 时会出现问题(

pytest -n 5 --dist loadgroup --alluredir=allure-results --reruns 2 --reruns-delay 2
)。这是由于
pytest_sessionfinish
在 allure 报告中添加了环境变量(例如浏览器和浏览器版本)。运行时出现错误:

  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "C:\Users\benik\PycharmProjects\pythonAutomationStore\.venv\Scripts\pytest.exe\__main__.py", line 7, in <module>
  File "C:\Users\benik\PycharmProjects\pythonAutomationStore\.venv\Lib\site-packages\_pytest\config\__init__.py", line 198, in console_main
    code = main()
           ^^^^^^
  File "C:\Users\benik\PycharmProjects\pythonAutomationStore\.venv\Lib\site-packages\_pytest\config\__init__.py", line 175, in main
    ret: Union[ExitCode, int] = config.hook.pytest_cmdline_main(
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\benik\PycharmProjects\pythonAutomationStore\.venv\Lib\site-packages\pluggy\_hooks.py", line 493, in __call__
    return self._hookexec(self.name, self._hookimpls, kwargs, firstresult)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\benik\PycharmProjects\pythonAutomationStore\.venv\Lib\site-packages\pluggy\_manager.py", line 115, in _hookexec
    return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\benik\PycharmProjects\pythonAutomationStore\.venv\Lib\site-packages\pluggy\_callers.py", line 113, in _multicall
    raise exception.with_traceback(exception.__traceback__)
  File "C:\Users\benik\PycharmProjects\pythonAutomationStore\.venv\Lib\site-packages\pluggy\_callers.py", line 77, in _multicall
    res = hook_impl.function(*args)
          ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\benik\PycharmProjects\pythonAutomationStore\.venv\Lib\site-packages\_pytest\main.py", line 320, in pytest_cmdline_main
    return wrap_session(config, _main)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\benik\PycharmProjects\pythonAutomationStore\.venv\Lib\site-packages\_pytest\main.py", line 308, in wrap_session
    config.hook.pytest_sessionfinish(
  File "C:\Users\benik\PycharmProjects\pythonAutomationStore\.venv\Lib\site-packages\pluggy\_hooks.py", line 493, in __call__
    return self._hookexec(self.name, self._hookimpls, kwargs, firstresult)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\benik\PycharmProjects\pythonAutomationStore\.venv\Lib\site-packages\pluggy\_manager.py", line 115, in _hookexec
    return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\benik\PycharmProjects\pythonAutomationStore\.venv\Lib\site-packages\pluggy\_callers.py", line 113, in _multicall
    raise exception.with_traceback(exception.__traceback__)
  File "C:\Users\benik\PycharmProjects\pythonAutomationStore\.venv\Lib\site-packages\pluggy\_callers.py", line 96, in _multicall
    teardown.throw(exception)  # type: ignore[union-attr]
    ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\benik\PycharmProjects\pythonAutomationStore\.venv\Lib\site-packages\_pytest\logging.py", line 861, in pytest_sessionfinish
    return (yield)
            ^^^^^
  File "C:\Users\benik\PycharmProjects\pythonAutomationStore\.venv\Lib\site-packages\pluggy\_callers.py", line 96, in _multicall
    teardown.throw(exception)  # type: ignore[union-attr]
    ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\benik\PycharmProjects\pythonAutomationStore\.venv\Lib\site-packages\_pytest\terminal.py", line 854, in pytest_sessionfinish        
    result = yield
             ^^^^^
  File "C:\Users\benik\PycharmProjects\pythonAutomationStore\.venv\Lib\site-packages\pluggy\_callers.py", line 96, in _multicall
    teardown.throw(exception)  # type: ignore[union-attr]
    ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\benik\PycharmProjects\pythonAutomationStore\.venv\Lib\site-packages\_pytest\warnings.py", line 138, in pytest_sessionfinish        
    return (yield)
            ^^^^^
  File "C:\Users\benik\PycharmProjects\pythonAutomationStore\.venv\Lib\site-packages\pluggy\_callers.py", line 77, in _multicall
    res = hook_impl.function(*args)
          ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\benik\PycharmProjects\pythonAutomationStore\tests\conftest.py", line 48, in pytest_sessionfinish
    driver = session.config._driver
             ^^^^^^^^^^^^^^^^^^^^^^

当 pytest 运行多个进程(或并行测试)时,我还尝试将环境变量添加到 allure 报告中。

python selenium-webdriver automation pytest allure
1个回答
0
投票

您可以使用https://github.com/seleniumbase/SeleniumBase(selenium + pytest的完整框架)来解决您的多线程问题: 在

pip install seleniumbase
之后,您可以使用
pytest
运行以下命令:

allure-pytest
单独安装。激活:
pytest --alluredir=allure_results
:

from seleniumbase import BaseCase


class BaseTestCase(BaseCase):
    def setUp(self):
        super().setUp()
        self.driver.get("https://magento.softwaretestingboard.com/")

    def tearDown(self):
        self.save_teardown_screenshot()  # If test fails, or if "--screenshot"
        if self.has_exception():
            pass  # <<< Run custom code if the test failed. >>>
        else:
            pass  # <<< Run custom code if the test passed. >>>
        # <<< Run custom tearDown() code BEFORE the super().tearDown() >>>
        super().tearDown()


class MyTests(BaseTestCase):
    def test_1(self):
        self.click('''span:contains("What's New")''')
        self.sleep(1)

    def test_2(self):
        self.type("#search", "Tees and Tops\n")
        self.sleep(1)

    def test_3(self):
        self.hover_and_js_click('span:contains("Gear")', 'span:contains("Bags")')
        self.sleep(1)

    def test_4(self):
        self.hover_and_js_click('span:contains("Gear")', 'span:contains("Watches")')
        self.sleep(1)

    def test_5(self):
        self.click('''span:contains("Sale")''')
        self.sleep(1)

您可以自定义

setUp()
tearDown()
,但请确保保留
super()
部分。如果测试失败,屏幕截图会自动保存到
./latest_logs/
文件夹中。如果您想使用 Allure 保存屏幕截图,请添加到
tearDown()
部分。

Headless Selenium 模式可以通过 pytest 激活:

pytest --headless

© www.soinside.com 2019 - 2024. All rights reserved.