././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685361266.2926812 pytest-xvfb-3.0.0/0000755000175100001730000000000014435111162013404 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1685361259.0 pytest-xvfb-3.0.0/CHANGELOG.rst0000644000175100001730000000371214435111153015430 0ustar00runnerdockerpytest-xvfb changelog ===================== 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 chances 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=1685361259.0 pytest-xvfb-3.0.0/LICENSE0000644000175100001730000000207114435111153014411 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=1685361259.0 pytest-xvfb-3.0.0/MANIFEST.in0000644000175100001730000000010314435111153015134 0ustar00runnerdockerinclude CHANGELOG.rst include LICENSE recursive-include tests *.py ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685361266.2926812 pytest-xvfb-3.0.0/PKG-INFO0000644000175100001730000001115114435111162014500 0ustar00runnerdockerMetadata-Version: 2.1 Name: pytest-xvfb Version: 3.0.0 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.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 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.7 Description-Content-Type: text/x-rst License-File: LICENSE 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. 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=1685361259.0 pytest-xvfb-3.0.0/README.rst0000644000175100001730000000673214435111153015103 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. 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=1685361259.0 pytest-xvfb-3.0.0/pyproject.toml0000644000175100001730000000260314435111153016321 0ustar00runnerdocker[build-system] requires = ["setuptools>=61.2"] build-backend = "setuptools.build_meta" [project] name = "pytest-xvfb" version = "3.0.0" 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.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Operating System :: OS Independent", "License :: OSI Approved :: MIT License", ] requires-python = ">=3.7" 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 ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685361266.2926812 pytest-xvfb-3.0.0/pytest_xvfb.egg-info/0000755000175100001730000000000014435111162017453 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1685361266.0 pytest-xvfb-3.0.0/pytest_xvfb.egg-info/PKG-INFO0000644000175100001730000001115114435111162020547 0ustar00runnerdockerMetadata-Version: 2.1 Name: pytest-xvfb Version: 3.0.0 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.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 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.7 Description-Content-Type: text/x-rst License-File: LICENSE 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. 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=1685361266.0 pytest-xvfb-3.0.0/pytest_xvfb.egg-info/SOURCES.txt0000644000175100001730000000060414435111162021337 0ustar00runnerdockerCHANGELOG.rst LICENSE MANIFEST.in README.rst pyproject.toml 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=1685361266.0 pytest-xvfb-3.0.0/pytest_xvfb.egg-info/dependency_links.txt0000644000175100001730000000000114435111162023521 0ustar00runnerdocker ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1685361266.0 pytest-xvfb-3.0.0/pytest_xvfb.egg-info/entry_points.txt0000644000175100001730000000003614435111162022750 0ustar00runnerdocker[pytest11] xvfb = pytest_xvfb ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1685361266.0 pytest-xvfb-3.0.0/pytest_xvfb.egg-info/requires.txt0000644000175100001730000000004414435111162022051 0ustar00runnerdockerpytest>=2.8.1 pyvirtualdisplay>=1.3 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1685361266.0 pytest-xvfb-3.0.0/pytest_xvfb.egg-info/top_level.txt0000644000175100001730000000001414435111162022200 0ustar00runnerdockerpytest_xvfb ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1685361259.0 pytest-xvfb-3.0.0/pytest_xvfb.py0000644000175100001730000001016214435111153016333 0ustar00runnerdockerfrom __future__ import annotations import atexit import os import os.path import sys import pytest import pyvirtualdisplay 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 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 = None self._virtual_display = None def start(self) -> None: self._virtual_display = pyvirtualdisplay.Display( # type: ignore[attr-defined] backend=self.backend, size=(self.width, self.height), color_depth=self.colordepth, use_xauth=self.xauth, extra_args=self.args, ) assert self._virtual_display is not None # mypy 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 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_configure(config: pytest.Config) -> None: global xvfb_instance no_xvfb = config.getoption("--no-xvfb") or is_xdist_master(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=1685361266.2926812 pytest-xvfb-3.0.0/setup.cfg0000644000175100001730000000004614435111162015225 0ustar00runnerdocker[egg_info] tag_build = tag_date = 0 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1685361259.0 pytest-xvfb-3.0.0/setup.py0000644000175100001730000000004614435111153015116 0ustar00runnerdockerfrom setuptools import setup setup() ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685361266.2926812 pytest-xvfb-3.0.0/tests/0000755000175100001730000000000014435111162014546 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1685361259.0 pytest-xvfb-3.0.0/tests/conftest.py0000644000175100001730000000003414435111153016742 0ustar00runnerdockerpytest_plugins = "pytester" ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1685361259.0 pytest-xvfb-3.0.0/tests/test_qtwe_xio_error.py0000644000175100001730000000124514435111153021231 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=1685361259.0 pytest-xvfb-3.0.0/tests/test_xvfb.py0000644000175100001730000002134114435111153017125 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 @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(l for l in result.outlines if l.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=1685361259.0 pytest-xvfb-3.0.0/tests/test_xvfb_windows.py0000644000175100001730000000052514435111153020700 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