././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1741782893.5693185 pytest_xvfb-3.1.1/0000755000175100001660000000000014764277556013523 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1741782886.0 pytest_xvfb-3.1.1/CHANGELOG.rst0000644000175100001660000000451414764277546015547 0ustar00runnerdockerpytest-xvfb changelog ===================== v3.1.1 ------ - Same as v3.1.0, but with proper version number and fully released. v3.1.0 ------ - Support for Python 3.7 and 3.8 is now dropped, while official support for 3.12 and 3.13 was added (with no code changes required). - ``pytest.ini`` (required to run self-tests) is now included in sdists (#39). - New ``pytest_xvfb_disable`` hook to dynamically disable pytest-xvfb. v3.0.0 ------ - New ``--xvfb-backend`` argument, which can be used to run Xephyr or Xvnc in place of Xvfb (e.g. for visual inspection but on a remote system or a consistent screen size needed). - Support for Python 3.5 and 3.6 is now dropped, while official support for 3.9, 3.10 and 3.11 was added (with no code changes required). - The ``Xvfb`` instance is now no longer saved in pytest's ``config`` object as ``config.xvfb`` anymore, and only available via the ``xvfb`` fixture. - Xvfb is now shut down as late as possible (via an ``atexit`` hook registered at import time), seemingly avoiding errors such as "XIO: fatal IO error 0 (Success)". - Code reformatting using black/shed. - Packaging refresh using ``pyproject.toml``. v2.0.0 ------ - PyVirtualDisplay 1.3 and newer is now supported, support for older versions was dropped. - Support for Python 2.7, 3.3 and 3.4 is now dropped. - Support for Python 3.6, 3.7 and 3.8 was added (no code changes required). - Xvfb is now not started anymore in the xdist master process. v1.2.0 ------ - ``Item.get_closest_marker`` is now used, which restores compatibility with pytest 4.1.0 and requires pytest 3.6.0 or newer. v1.1.0 ------ - The ``xvfb_args`` option is now a single line parsed with ``shlex.split``. - The ``XvfbExitedError`` exception now includes stdout and stderr. v1.0.0 ------ - Use `PyVirtualDisplay`_ to start/stop Xvfb - Show a warning on Linux if Xvfb is unavailable .. _PyVirtualDisplay: https://pypi.python.org/pypi/PyVirtualDisplay v0.3.0 ------ - Add a new ``xvfb_xauth`` setting which creates an ``XAUTHORITY`` file. v0.2.1 ------ - The temporary directory searched for logfiles is now hardcoded to /tmp as that's what X11 does as well. v0.2.0 ------ - The ``no_xvfb``-marker is now registered automatically so pytest doesn't fail when run with ``--strict``. - The ``xvfb`` fixture is now session-scoped. v0.1.0 ------ - Initial release ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1741782886.0 pytest_xvfb-3.1.1/LICENSE0000644000175100001660000000207114764277546014527 0ustar00runnerdockerThe MIT License (MIT) Copyright (c) 2016 Florian Bruhin Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1741782886.0 pytest_xvfb-3.1.1/MANIFEST.in0000644000175100001660000000012614764277546015257 0ustar00runnerdockerinclude CHANGELOG.rst include LICENSE include pytest.ini recursive-include tests *.py ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1741782893.5683186 pytest_xvfb-3.1.1/PKG-INFO0000644000175100001660000001154614764277556014627 0ustar00runnerdockerMetadata-Version: 2.2 Name: pytest-xvfb Version: 3.1.1 Summary: A pytest plugin to run Xvfb (or Xephyr/Xvnc) for tests. Author-email: Florian Bruhin Maintainer-email: Florian Bruhin License: MIT Project-URL: Homepage, https://github.com/The-Compiler/pytest-xvfb Classifier: Development Status :: 4 - Beta Classifier: Intended Audience :: Developers Classifier: Topic :: Software Development :: Testing Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 :: Only Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 Classifier: Programming Language :: Python :: 3.12 Classifier: Programming Language :: Python :: 3.13 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Operating System :: OS Independent Classifier: License :: OSI Approved :: MIT License Requires-Python: >=3.9 Description-Content-Type: text/x-rst License-File: LICENSE Requires-Dist: pytest>=2.8.1 Requires-Dist: pyvirtualdisplay>=1.3 pytest-xvfb =================================== A pytest plugin to run `Xvfb`_ (or `Xephyr`_/`Xvnc`_) for tests. ---- Installation ------------ You can install "`pytest-xvfb`_" via `pip`_ from `PyPI`_:: $ pip install pytest-xvfb Usage ----- With Xvfb and the plugin installed, your testsuite automatically runs with `Xvfb`_. This allows tests to be run without windows popping up during GUI tests or on systems without a display (like a CI). The plugin sees Xvfb being installed as "optional", since the tests can still run without it installed. If it's unavailable, it will show an informational message, if on Linux and a ``DISPLAY`` is available. When using ``--xvfb-backend xvfb``, this message will turn into a hard error instead. If you're currently using ``xvfb-run`` in something like a GitHub Actions YAML file simply remove the wrapper and install this plugin instead - then you'll also have the benefits of Xvfb locally. Features -------- You can pass ``--no-xvfb`` to explicitly turn off Xvfb (e.g. to visually inspect a failure). With ``--xvfb-backend xephyr`` or ``--xvfb-backend xvnc``, you can use Xephyr or Xvnc in place of Xvfb, e.g. to visually inspect failures. **NOTE:** Support for ``xvnc`` is currently experimental and not tested on CI, due to incompatibilities with PyVirtualDisplay and Ubuntu 22.04's tightvncserver. You can mark tests with ``@pytest.mark.no_xvfb`` to skip them when they're running with Xvfb. By implementing the `pytest_xvfb_disable(config: pytest.Config)` pytest hook, you can dynamically decide whether pytest-xvfb should be disabled (by returning `True` from such a hook). A ``xvfb`` fixture is available with the following attributes: - ``width``: The configured width of the screen. - ``height``: The configured height of the screen. - ``colordepth``: The configured colordepth of the screen. - ``args``: The arguments to be passed to Xvfb. - ``display``: The display number (as int) which is used. - ``backend``: Either ``None`` (Xvfb), ``"xvfb"``, ``"xephyr"``, or ``"xvnc"``. In a pytest.ini, ``xvfb_width``, ``xvfb_height``, ``xvfb_colordepth`` and ``xvfb_args`` can be used to configure the respective values. In addition, ``xvfb_xauth`` can be set to ``true`` to generate an ``Xauthority`` token. Contributing ------------ Contributions are very welcome. Tests can be run with `tox`_, please ensure the coverage at least stays the same before you submit a pull request. License ------- Distributed under the terms of the `MIT`_ license, "pytest-xvfb" is free and open source software Thanks ------ This `pytest`_ plugin was generated with `Cookiecutter`_ along with `@hackebrot`_'s `Cookiecutter-pytest-plugin`_ template. Thanks to `@cgoldberg`_ for `xvfbwrapper`_ which was the inspiration for this project. Issues ------ If you encounter any problems, please `file an issue`_ along with a detailed description. .. _`pytest-xvfb`: https://pypi.python.org/pypi/pytest-xvfb/ .. _`Cookiecutter`: https://github.com/audreyr/cookiecutter .. _`@hackebrot`: https://github.com/hackebrot .. _`@cgoldberg`: https://github.com/cgoldberg .. _`xvfbwrapper`: https://github.com/cgoldberg/xvfbwrapper .. _`MIT`: http://opensource.org/licenses/MIT .. _`cookiecutter-pytest-plugin`: https://github.com/pytest-dev/cookiecutter-pytest-plugin .. _`file an issue`: https://github.com/The-Compiler/pytest-xvfb/issues .. _`pytest`: https://github.com/pytest-dev/pytest .. _`tox`: https://tox.readthedocs.org/en/latest/ .. _`pip`: https://pypi.python.org/pypi/pip/ .. _`PyPI`: https://pypi.python.org/pypi .. _`Xvfb`: https://en.wikipedia.org/wiki/Xvfb .. _`Xephyr`: https://www.freedesktop.org/wiki/Software/Xephyr/ .. _`Xvnc`: https://tigervnc.org/doc/Xvnc.html ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1741782886.0 pytest_xvfb-3.1.1/README.rst0000644000175100001660000000722314764277546015215 0ustar00runnerdockerpytest-xvfb =================================== A pytest plugin to run `Xvfb`_ (or `Xephyr`_/`Xvnc`_) for tests. ---- Installation ------------ You can install "`pytest-xvfb`_" via `pip`_ from `PyPI`_:: $ pip install pytest-xvfb Usage ----- With Xvfb and the plugin installed, your testsuite automatically runs with `Xvfb`_. This allows tests to be run without windows popping up during GUI tests or on systems without a display (like a CI). The plugin sees Xvfb being installed as "optional", since the tests can still run without it installed. If it's unavailable, it will show an informational message, if on Linux and a ``DISPLAY`` is available. When using ``--xvfb-backend xvfb``, this message will turn into a hard error instead. If you're currently using ``xvfb-run`` in something like a GitHub Actions YAML file simply remove the wrapper and install this plugin instead - then you'll also have the benefits of Xvfb locally. Features -------- You can pass ``--no-xvfb`` to explicitly turn off Xvfb (e.g. to visually inspect a failure). With ``--xvfb-backend xephyr`` or ``--xvfb-backend xvnc``, you can use Xephyr or Xvnc in place of Xvfb, e.g. to visually inspect failures. **NOTE:** Support for ``xvnc`` is currently experimental and not tested on CI, due to incompatibilities with PyVirtualDisplay and Ubuntu 22.04's tightvncserver. You can mark tests with ``@pytest.mark.no_xvfb`` to skip them when they're running with Xvfb. By implementing the `pytest_xvfb_disable(config: pytest.Config)` pytest hook, you can dynamically decide whether pytest-xvfb should be disabled (by returning `True` from such a hook). A ``xvfb`` fixture is available with the following attributes: - ``width``: The configured width of the screen. - ``height``: The configured height of the screen. - ``colordepth``: The configured colordepth of the screen. - ``args``: The arguments to be passed to Xvfb. - ``display``: The display number (as int) which is used. - ``backend``: Either ``None`` (Xvfb), ``"xvfb"``, ``"xephyr"``, or ``"xvnc"``. In a pytest.ini, ``xvfb_width``, ``xvfb_height``, ``xvfb_colordepth`` and ``xvfb_args`` can be used to configure the respective values. In addition, ``xvfb_xauth`` can be set to ``true`` to generate an ``Xauthority`` token. Contributing ------------ Contributions are very welcome. Tests can be run with `tox`_, please ensure the coverage at least stays the same before you submit a pull request. License ------- Distributed under the terms of the `MIT`_ license, "pytest-xvfb" is free and open source software Thanks ------ This `pytest`_ plugin was generated with `Cookiecutter`_ along with `@hackebrot`_'s `Cookiecutter-pytest-plugin`_ template. Thanks to `@cgoldberg`_ for `xvfbwrapper`_ which was the inspiration for this project. Issues ------ If you encounter any problems, please `file an issue`_ along with a detailed description. .. _`pytest-xvfb`: https://pypi.python.org/pypi/pytest-xvfb/ .. _`Cookiecutter`: https://github.com/audreyr/cookiecutter .. _`@hackebrot`: https://github.com/hackebrot .. _`@cgoldberg`: https://github.com/cgoldberg .. _`xvfbwrapper`: https://github.com/cgoldberg/xvfbwrapper .. _`MIT`: http://opensource.org/licenses/MIT .. _`cookiecutter-pytest-plugin`: https://github.com/pytest-dev/cookiecutter-pytest-plugin .. _`file an issue`: https://github.com/The-Compiler/pytest-xvfb/issues .. _`pytest`: https://github.com/pytest-dev/pytest .. _`tox`: https://tox.readthedocs.org/en/latest/ .. _`pip`: https://pypi.python.org/pypi/pip/ .. _`PyPI`: https://pypi.python.org/pypi .. _`Xvfb`: https://en.wikipedia.org/wiki/Xvfb .. _`Xephyr`: https://www.freedesktop.org/wiki/Software/Xephyr/ .. _`Xvnc`: https://tigervnc.org/doc/Xvnc.html ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1741782886.0 pytest_xvfb-3.1.1/pyproject.toml0000644000175100001660000000260514764277546016441 0ustar00runnerdocker[build-system] requires = ["setuptools>=61.2"] build-backend = "setuptools.build_meta" [project] name = "pytest-xvfb" version = "3.1.1" authors = [{name = "Florian Bruhin", email = "me@the-compiler.org"}] maintainers = [{name = "Florian Bruhin", email = "me@the-compiler.org"}] license = {text = "MIT"} description = "A pytest plugin to run Xvfb (or Xephyr/Xvnc) for tests." readme = "README.rst" classifiers = [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "Topic :: Software Development :: Testing", "Programming Language :: Python", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Operating System :: OS Independent", "License :: OSI Approved :: MIT License", ] requires-python = ">=3.9" dependencies = ["pytest>=2.8.1", "pyvirtualdisplay>=1.3"] [project.urls] Homepage = "https://github.com/The-Compiler/pytest-xvfb" [project.entry-points] pytest11 = {xvfb = "pytest_xvfb"} [tool.setuptools] py-modules = ["pytest_xvfb"] include-package-data = false ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1741782886.0 pytest_xvfb-3.1.1/pytest.ini0000644000175100001660000000005214764277546015550 0ustar00runnerdocker[pytest] addopts = --runpytest=subprocess ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1741782893.5683186 pytest_xvfb-3.1.1/pytest_xvfb.egg-info/0000755000175100001660000000000014764277556017572 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1741782893.0 pytest_xvfb-3.1.1/pytest_xvfb.egg-info/PKG-INFO0000644000175100001660000001154614764277555020675 0ustar00runnerdockerMetadata-Version: 2.2 Name: pytest-xvfb Version: 3.1.1 Summary: A pytest plugin to run Xvfb (or Xephyr/Xvnc) for tests. Author-email: Florian Bruhin Maintainer-email: Florian Bruhin License: MIT Project-URL: Homepage, https://github.com/The-Compiler/pytest-xvfb Classifier: Development Status :: 4 - Beta Classifier: Intended Audience :: Developers Classifier: Topic :: Software Development :: Testing Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 :: Only Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 Classifier: Programming Language :: Python :: 3.12 Classifier: Programming Language :: Python :: 3.13 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Operating System :: OS Independent Classifier: License :: OSI Approved :: MIT License Requires-Python: >=3.9 Description-Content-Type: text/x-rst License-File: LICENSE Requires-Dist: pytest>=2.8.1 Requires-Dist: pyvirtualdisplay>=1.3 pytest-xvfb =================================== A pytest plugin to run `Xvfb`_ (or `Xephyr`_/`Xvnc`_) for tests. ---- Installation ------------ You can install "`pytest-xvfb`_" via `pip`_ from `PyPI`_:: $ pip install pytest-xvfb Usage ----- With Xvfb and the plugin installed, your testsuite automatically runs with `Xvfb`_. This allows tests to be run without windows popping up during GUI tests or on systems without a display (like a CI). The plugin sees Xvfb being installed as "optional", since the tests can still run without it installed. If it's unavailable, it will show an informational message, if on Linux and a ``DISPLAY`` is available. When using ``--xvfb-backend xvfb``, this message will turn into a hard error instead. If you're currently using ``xvfb-run`` in something like a GitHub Actions YAML file simply remove the wrapper and install this plugin instead - then you'll also have the benefits of Xvfb locally. Features -------- You can pass ``--no-xvfb`` to explicitly turn off Xvfb (e.g. to visually inspect a failure). With ``--xvfb-backend xephyr`` or ``--xvfb-backend xvnc``, you can use Xephyr or Xvnc in place of Xvfb, e.g. to visually inspect failures. **NOTE:** Support for ``xvnc`` is currently experimental and not tested on CI, due to incompatibilities with PyVirtualDisplay and Ubuntu 22.04's tightvncserver. You can mark tests with ``@pytest.mark.no_xvfb`` to skip them when they're running with Xvfb. By implementing the `pytest_xvfb_disable(config: pytest.Config)` pytest hook, you can dynamically decide whether pytest-xvfb should be disabled (by returning `True` from such a hook). A ``xvfb`` fixture is available with the following attributes: - ``width``: The configured width of the screen. - ``height``: The configured height of the screen. - ``colordepth``: The configured colordepth of the screen. - ``args``: The arguments to be passed to Xvfb. - ``display``: The display number (as int) which is used. - ``backend``: Either ``None`` (Xvfb), ``"xvfb"``, ``"xephyr"``, or ``"xvnc"``. In a pytest.ini, ``xvfb_width``, ``xvfb_height``, ``xvfb_colordepth`` and ``xvfb_args`` can be used to configure the respective values. In addition, ``xvfb_xauth`` can be set to ``true`` to generate an ``Xauthority`` token. Contributing ------------ Contributions are very welcome. Tests can be run with `tox`_, please ensure the coverage at least stays the same before you submit a pull request. License ------- Distributed under the terms of the `MIT`_ license, "pytest-xvfb" is free and open source software Thanks ------ This `pytest`_ plugin was generated with `Cookiecutter`_ along with `@hackebrot`_'s `Cookiecutter-pytest-plugin`_ template. Thanks to `@cgoldberg`_ for `xvfbwrapper`_ which was the inspiration for this project. Issues ------ If you encounter any problems, please `file an issue`_ along with a detailed description. .. _`pytest-xvfb`: https://pypi.python.org/pypi/pytest-xvfb/ .. _`Cookiecutter`: https://github.com/audreyr/cookiecutter .. _`@hackebrot`: https://github.com/hackebrot .. _`@cgoldberg`: https://github.com/cgoldberg .. _`xvfbwrapper`: https://github.com/cgoldberg/xvfbwrapper .. _`MIT`: http://opensource.org/licenses/MIT .. _`cookiecutter-pytest-plugin`: https://github.com/pytest-dev/cookiecutter-pytest-plugin .. _`file an issue`: https://github.com/The-Compiler/pytest-xvfb/issues .. _`pytest`: https://github.com/pytest-dev/pytest .. _`tox`: https://tox.readthedocs.org/en/latest/ .. _`pip`: https://pypi.python.org/pypi/pip/ .. _`PyPI`: https://pypi.python.org/pypi .. _`Xvfb`: https://en.wikipedia.org/wiki/Xvfb .. _`Xephyr`: https://www.freedesktop.org/wiki/Software/Xephyr/ .. _`Xvnc`: https://tigervnc.org/doc/Xvnc.html ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1741782893.0 pytest_xvfb-3.1.1/pytest_xvfb.egg-info/SOURCES.txt0000644000175100001660000000061714764277555021461 0ustar00runnerdockerCHANGELOG.rst LICENSE MANIFEST.in README.rst pyproject.toml pytest.ini pytest_xvfb.py setup.py pytest_xvfb.egg-info/PKG-INFO pytest_xvfb.egg-info/SOURCES.txt pytest_xvfb.egg-info/dependency_links.txt pytest_xvfb.egg-info/entry_points.txt pytest_xvfb.egg-info/requires.txt pytest_xvfb.egg-info/top_level.txt tests/conftest.py tests/test_qtwe_xio_error.py tests/test_xvfb.py tests/test_xvfb_windows.py././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1741782893.0 pytest_xvfb-3.1.1/pytest_xvfb.egg-info/dependency_links.txt0000644000175100001660000000000114764277555023637 0ustar00runnerdocker ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1741782893.0 pytest_xvfb-3.1.1/pytest_xvfb.egg-info/entry_points.txt0000644000175100001660000000003614764277555023066 0ustar00runnerdocker[pytest11] xvfb = pytest_xvfb ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1741782893.0 pytest_xvfb-3.1.1/pytest_xvfb.egg-info/requires.txt0000644000175100001660000000004414764277555022167 0ustar00runnerdockerpytest>=2.8.1 pyvirtualdisplay>=1.3 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1741782893.0 pytest_xvfb-3.1.1/pytest_xvfb.egg-info/top_level.txt0000644000175100001660000000001414764277555022316 0ustar00runnerdockerpytest_xvfb ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1741782886.0 pytest_xvfb-3.1.1/pytest_xvfb.py0000644000175100001660000001111414764277546016447 0ustar00runnerdockerfrom __future__ import annotations import atexit import os import os.path import sys import pytest import pyvirtualdisplay import pyvirtualdisplay.display xvfb_instance = None def shutdown_xvfb() -> None: if xvfb_instance is not None: xvfb_instance.stop() # This needs to be done as early as possible (before importing QtWebEngine for # example), so that Xvfb gets shut down as late as possible. atexit.register(shutdown_xvfb) def is_xdist_master(config: pytest.Config) -> bool: return config.getoption("dist", "no") != "no" and not os.environ.get( "PYTEST_XDIST_WORKER" ) def has_executable(name: str) -> bool: # http://stackoverflow.com/a/28909933/2085149 return any( os.access(os.path.join(path, name), os.X_OK) for path in os.environ["PATH"].split(os.pathsep) ) class XvfbExitedError(Exception): pass class Hookspec: def pytest_xvfb_disable(self, config: pytest.Config) -> bool: # type: ignore[empty-body] """Return bool from this hook to disable pytest-xvfb.""" ... class Xvfb: def __init__(self, config: pytest.Config) -> None: self.width = int(config.getini("xvfb_width")) self.height = int(config.getini("xvfb_height")) self.colordepth = int(config.getini("xvfb_colordepth")) self.args = config.getini("xvfb_args") or [] self.xauth = config.getini("xvfb_xauth") self.backend = config.getoption("--xvfb-backend") self.display: int | None = None self._virtual_display: pyvirtualdisplay.display.Display | None = None def start(self) -> None: self._virtual_display = pyvirtualdisplay.display.Display( backend=self.backend, size=(self.width, self.height), color_depth=self.colordepth, use_xauth=self.xauth, extra_args=self.args, ) self._virtual_display.start() self.display = self._virtual_display.display assert self._virtual_display.is_alive() def stop(self) -> None: if self.display is not None: # starting worked assert self._virtual_display is not None # mypy self._virtual_display.stop() def pytest_addoption(parser: pytest.Parser) -> None: group = parser.getgroup("xvfb") group.addoption("--no-xvfb", action="store_true", help="Disable Xvfb for tests.") group.addoption( "--xvfb-backend", action="store", choices=["xvfb", "xvnc", "xephyr"], help="Use Xephyr or Xvnc instead of Xvfb for tests. Will be ignored if --no-xvfb is given.", ) parser.addini("xvfb_width", "Width of the Xvfb display", default="800") parser.addini("xvfb_height", "Height of the Xvfb display", default="600") parser.addini("xvfb_colordepth", "Color depth of the Xvfb display", default="16") parser.addini("xvfb_args", "Additional arguments for Xvfb", type="args") parser.addini( "xvfb_xauth", "Generate an Xauthority token for Xvfb. Needs xauth.", default=False, type="bool", ) def pytest_addhooks(pluginmanager: pytest.PytestPluginManager) -> None: pluginmanager.add_hookspecs(Hookspec) def pytest_configure(config: pytest.Config) -> None: global xvfb_instance no_xvfb = ( config.getoption("--no-xvfb") or is_xdist_master(config) or any(config.pluginmanager.hook.pytest_xvfb_disable(config=config)) ) backend = config.getoption("--xvfb-backend") if no_xvfb: pass elif backend is None and not has_executable("Xvfb"): # soft fail if sys.platform.startswith("linux") and "DISPLAY" in os.environ: print( "pytest-xvfb could not find Xvfb. " "You can install it to prevent windows from being shown." ) elif ( backend == "xvfb" and not has_executable("Xvfb") or backend == "xvnc" and not has_executable("Xvnc") or backend == "xephyr" and not has_executable("Xephyr") ): raise pytest.UsageError(f"xvfb backend {backend} requested but not installed.") else: xvfb_instance = Xvfb(config) xvfb_instance.start() config.addinivalue_line("markers", "no_xvfb: Skip test when using Xvfb") def pytest_collection_modifyitems(items: list[pytest.Item]) -> None: for item in items: if item.get_closest_marker("no_xvfb") and xvfb_instance is not None: skipif_marker = pytest.mark.skipif(True, reason="Skipped with Xvfb") item.add_marker(skipif_marker) @pytest.fixture(scope="session") def xvfb() -> Xvfb | None: return xvfb_instance ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1741782893.5693185 pytest_xvfb-3.1.1/setup.cfg0000644000175100001660000000004614764277556015344 0ustar00runnerdocker[egg_info] tag_build = tag_date = 0 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1741782886.0 pytest_xvfb-3.1.1/setup.py0000644000175100001660000000004614764277546015234 0ustar00runnerdockerfrom setuptools import setup setup() ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1741782893.5683186 pytest_xvfb-3.1.1/tests/0000755000175100001660000000000014764277556014665 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1741782886.0 pytest_xvfb-3.1.1/tests/conftest.py0000644000175100001660000000003414764277546017060 0ustar00runnerdockerpytest_plugins = "pytester" ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1741782886.0 pytest_xvfb-3.1.1/tests/test_qtwe_xio_error.py0000644000175100001660000000124514764277546021347 0ustar00runnerdockerfrom __future__ import annotations import os import sys import pytest if sys.version_info == (3, 12, 0, "beta", 1) and "CI" in os.environ: pytest.skip( reason="Segfaults on GHA for unknown reasons", allow_module_level=True, ) pytest.importorskip("PyQt5.QtWebEngineWidgets") def test_qt_output(pytester: pytest.Pytester) -> None: pytester.makepyfile( """ import sys import PyQt5.QtWebEngineWidgets from PyQt5.QtWidgets import QWidget, QApplication app = QApplication(sys.argv) def test_widget(): widget = QWidget() widget.show() """ ) res = pytester.runpytest() assert res.ret == 0 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1741782886.0 pytest_xvfb-3.1.1/tests/test_xvfb.py0000644000175100001660000002241214764277546017243 0ustar00runnerdockerfrom __future__ import annotations import os from typing import Iterator import pytest import pyvirtualdisplay import pytest_xvfb xauth_available = any( os.access(os.path.join(path, "xauth"), os.X_OK) for path in os.environ.get("PATH", "").split(os.pathsep) ) @pytest.fixture(autouse=True, scope="session") def ensure_xvfb() -> None: if not pytest_xvfb.has_executable("Xvfb"): raise Exception("Tests need Xvfb to run.") needs_xephyr = pytest.mark.skipif( not pytest_xvfb.has_executable("Xephyr"), reason="Needs Xephyr" ) needs_xvnc = pytest.mark.skipif( not pytest_xvfb.has_executable("Xvnc"), reason="Needs Xvnc" ) @pytest.fixture( params=[ None, "xvfb", pytest.param("xephyr", marks=needs_xephyr), pytest.param("xvnc", marks=needs_xvnc), ] ) def backend_args( request: pytest.FixtureRequest, monkeypatch: pytest.MonkeyPatch ) -> Iterator[list[str]]: monkeypatch.delenv("DISPLAY") args = [] if request.param is None else ["--xvfb-backend", request.param] if request.param == "xephyr": # we need a host display for it... PyVirtualDisplay and Xvfb to the # rescue! display = pyvirtualdisplay.Display() # type: ignore[attr-defined] display.start() yield args display.stop() else: yield args def test_xvfb_available(pytester: pytest.Pytester, backend_args: list[str]) -> None: pytester.makepyfile( """ import os def test_display(): assert 'DISPLAY' in os.environ """ ) result = pytester.runpytest(*backend_args) assert result.ret == 0 def test_empty_display( pytester: pytest.Pytester, monkeypatch: pytest.MonkeyPatch, backend_args: list[str] ) -> None: if backend_args == ["--xvfb-backend", "xephyr"]: pytest.skip("Xephyr needs a host display") monkeypatch.setenv("DISPLAY", "") pytester.makepyfile( """ import os def test_display(): assert 'DISPLAY' in os.environ """ ) result = pytester.runpytest(*backend_args) assert os.environ["DISPLAY"] == "" assert result.ret == 0 def test_xvfb_unavailable( pytester: pytest.Pytester, monkeypatch: pytest.MonkeyPatch ) -> None: monkeypatch.setenv("PATH", "") monkeypatch.setenv("DISPLAY", ":42") pytester.makepyfile( """ import os def test_display(): assert os.environ['DISPLAY'] == ':42' """ ) assert os.environ["DISPLAY"] == ":42" result = pytester.runpytest() result.stdout.fnmatch_lines("* could not find Xvfb.*") assert result.ret == 0 def test_xvfb_unavailable_explicit( pytester: pytest.Pytester, monkeypatch: pytest.MonkeyPatch, backend_args: list[str] ) -> None: """If an explicitly chosen backend is unavailable: Hard error.""" if not backend_args: pytest.skip("Already tested above") monkeypatch.setenv("PATH", "") monkeypatch.setenv("DISPLAY", ":42") pytester.makepyfile( """ import os def test_display(): assert False # never run """ ) assert os.environ["DISPLAY"] == ":42" result = pytester.runpytest(*backend_args) result.stderr.fnmatch_lines("*xvfb backend * requested but not installed.") assert result.ret == pytest.ExitCode.USAGE_ERROR def test_no_xvfb_arg( pytester: pytest.Pytester, monkeypatch: pytest.MonkeyPatch, backend_args: list[str] ) -> None: monkeypatch.setenv("DISPLAY", ":42") pytester.makepyfile( """ import os def test_display(): assert os.environ['DISPLAY'] == ':42' """ ) assert os.environ["DISPLAY"] == ":42" result = pytester.runpytest("--no-xvfb", *backend_args) assert result.ret == 0 def test_disable_hook( pytester: pytest.Pytester, monkeypatch: pytest.MonkeyPatch, backend_args: list[str] ) -> None: monkeypatch.setenv("DISPLAY", ":42") pytester.makepyfile( conftest=""" def pytest_xvfb_disable(config): return True """ ) pytester.makepyfile( """ import os def test_display(): assert os.environ['DISPLAY'] == ':42' """ ) assert os.environ["DISPLAY"] == ":42" result = pytester.runpytest(*backend_args) assert result.ret == 0 @pytest.mark.parametrize("configured", [True, False]) def test_screen_size( pytester: pytest.Pytester, configured: bool, backend_args: list[str] ) -> None: if backend_args == ["--xvfb-backend", "xvnc"]: pytest.skip("Seems to be unsupported with Xvnc") try: import tkinter # noqa except ImportError: pytest.importorskip("Tkinter") if configured: pytester.makeini( """ [pytest] xvfb_width = 1024 xvfb_height = 768 xvfb_colordepth = 8 """ ) expected_width = 1024 expected_height = 768 expected_depth = 8 else: expected_width = 800 expected_height = 600 expected_depth = 16 pytester.makepyfile( """ try: import tkinter as tk except ImportError: import Tkinter as tk def test_screen_size(): root = tk.Tk() assert root.winfo_screenwidth() == {width} assert root.winfo_screenheight() == {height} assert root.winfo_screendepth() == {depth} """.format(width=expected_width, height=expected_height, depth=expected_depth) ) result = pytester.runpytest(*backend_args) assert result.ret == 0 def test_failing_start( pytester: pytest.Pytester, monkeypatch: pytest.MonkeyPatch, backend_args: list[str] ) -> None: pytester.makeini( """ [pytest] xvfb_args = -foo """ ) pytester.makepyfile( """ def test_none(): pass """ ) result = pytester.runpytest(*backend_args) result.stderr.fnmatch_lines( [ "INTERNALERROR> *.XStartError: X* program closed. *", ] ) assert "OSError" not in str(result.stderr) @pytest.mark.parametrize( "args, outcome", [ ([], "1 passed, 1 skipped"), (["--no-xvfb"], "2 passed"), ], ) def test_no_xvfb_marker( pytester: pytest.Pytester, args: list[str], outcome: str, backend_args: list[str] ) -> None: pytester.makepyfile( """ import pytest @pytest.mark.no_xvfb def test_marked(): pass def test_unmarked(): pass """ ) res = pytester.runpytest(*args, *backend_args) res.stdout.fnmatch_lines(f"*= {outcome}*") def test_xvfb_fixture(pytester: pytest.Pytester, backend_args: list[str]) -> None: pytester.makepyfile( """ import os def test_display(xvfb): assert ':{}'.format(xvfb.display) == os.environ['DISPLAY'] def test_screen(xvfb): assert xvfb.width == 800 assert xvfb.height == 600 assert xvfb.colordepth == 16 def test_args(xvfb): assert xvfb.args == [] """ ) result = pytester.runpytest(*backend_args) assert result.ret == 0 def test_early_display( monkeypatch: pytest.MonkeyPatch, pytester: pytest.Pytester, backend_args: list[str] ) -> None: """Make sure DISPLAY is set in a session-scoped fixture already.""" pytester.makepyfile( """ import os import pytest @pytest.yield_fixture(scope='session', autouse=True) def fixt(): assert 'DISPLAY' in os.environ yield def test_foo(): pass """ ) result = pytester.runpytest(*backend_args) assert result.ret == 0 def test_strict_markers(pytester: pytest.Pytester) -> None: pytester.makepyfile( """ import pytest @pytest.mark.no_xvfb def test_marked(): pass """ ) result = pytester.runpytest("--strict") assert result.ret == 0 def test_xvfb_session_fixture(pytester: pytest.Pytester) -> None: """Make sure the xvfb fixture can be used from a session-wide one.""" pytester.makepyfile( """ import pytest @pytest.fixture(scope='session') def fixt(xvfb): pass def test_fixt(fixt): pass """ ) result = pytester.runpytest() assert result.ret == 0 @pytest.mark.skipif(not xauth_available, reason="no xauth") def test_xvfb_with_xauth(pytester: pytest.Pytester, backend_args: list[str]) -> None: original_auth = os.environ.get("XAUTHORITY") pytester.makeini( """ [pytest] xvfb_xauth = True """ ) pytester.makepyfile( """ import os def test_xauth(): print('\\nXAUTHORITY: ' + os.environ['XAUTHORITY']) assert os.path.isfile(os.environ['XAUTHORITY']) assert os.access(os.environ['XAUTHORITY'], os.R_OK) """ ) result = pytester.runpytest("-s", *backend_args) # Get and parse the XAUTHORITY: line authline = next(line for line in result.outlines if line.startswith("XAUTHORITY:")) authfile = authline.split(" ", 1)[1] assert result.ret == 0 # Make sure the authfile is deleted assert not os.path.exists(authfile) assert os.environ.get("XAUTHORITY") == original_auth ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1741782886.0 pytest_xvfb-3.1.1/tests/test_xvfb_windows.py0000644000175100001660000000052514764277546021016 0ustar00runnerdockerfrom __future__ import annotations import pytest def test_xvfb_windows(pytester: pytest.Pytester) -> None: """Make sure things don't break on Windows with no Xvfb available.""" pytester.makepyfile( """ def test_nothing(): pass """ ) result = pytester.runpytest() assert result.ret == 0