Skip to content

Commit ddc8f75

Browse files
committed
Initial commit.
0 parents  commit ddc8f75

File tree

12 files changed

+461
-0
lines changed

12 files changed

+461
-0
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/.cache
2+
/pytest_xvfb.egg-info
3+
/__pycache__
4+
/.tox
5+
*.pyc

.travis.yml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Config file for automatic testing at travis-ci.org
2+
3+
sudo: false
4+
language: python
5+
python:
6+
- "2.7"
7+
- "3.3"
8+
- "3.4"
9+
- "3.5"
10+
- "pypy"
11+
12+
addons:
13+
apt:
14+
packages:
15+
- xvfb
16+
17+
install:
18+
- pip install tox
19+
- "TOX_ENV=${TRAVIS_PYTHON_VERSION/[0-9].[0-9]/py${TRAVIS_PYTHON_VERSION/.}}"
20+
script: tox -e $TOX_ENV
21+
22+
before_cache:
23+
- rm -rf $HOME/.cache/pip/log
24+
cache:
25+
directories:
26+
- $HOME/.cache/pip

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2015 Florian Bruhin
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in
13+
all copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
THE SOFTWARE.

README.rst

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
pytest-xvfb
2+
===================================
3+
4+
.. image:: https://travis-ci.org/The-Compiler/pytest-xvfb.svg?branch=master
5+
:target: https://travis-ci.org/The-Compiler/pytest-xvfb
6+
:alt: See Build Status on Travis CI
7+
8+
.. image:: https://ci.appveyor.com/api/projects/status/github/The-Compiler/pytest-xvfb?branch=master
9+
:target: https://ci.appveyor.com/project/The-Compiler/pytest-xvfb/branch/master
10+
:alt: See Build Status on AppVeyor
11+
12+
A pytest plugin to run Xvfb for tests.
13+
14+
----
15+
16+
Installation
17+
------------
18+
19+
You can install "pytest-xvfb" via `pip`_ from `PyPI`_::
20+
21+
$ pip install pytest-xvfb
22+
23+
24+
Usage
25+
-----
26+
27+
This plugin runs your testsuite with `Xvfb`_ to avoid popping up windows during
28+
GUI tests or allow them to run on systems without a display.
29+
30+
If Xvfb is not installed, it does nothing so your tests will still work.
31+
32+
You can also pass ``--no-xvfb`` to explicitly turn off Xvfb (e.g. to visually
33+
inspect a failure).
34+
35+
Contributing
36+
------------
37+
38+
Contributions are very welcome. Tests can be run with `tox`_, please ensure
39+
the coverage at least stays the same before you submit a pull request.
40+
41+
License
42+
-------
43+
44+
Distributed under the terms of the `MIT`_ license, "pytest-xvfb" is free and open source software
45+
46+
Thanks
47+
------
48+
49+
This `pytest`_ plugin was generated with `Cookiecutter`_ along with
50+
`@hackebrot`_'s `Cookiecutter-pytest-plugin`_ template.
51+
52+
Thanks to `@cgoldberg`_ for `xvfbwrapper`_ which was the inspiration for this
53+
project.
54+
55+
Issues
56+
------
57+
58+
If you encounter any problems, please `file an issue`_ along with a detailed description.
59+
60+
.. _`Xvfb`: http://www.x.org/releases/X11R7.6/doc/man/man1/Xvfb.1.xhtml
61+
.. _`Cookiecutter`: https://github.com/audreyr/cookiecutter
62+
.. _`@hackebrot`: https://github.com/hackebrot
63+
.. _`@cgoldberg`: https://github.com/cgoldberg
64+
.. _`xvfbwrapper`: https://github.com/cgoldberg/xvfbwrapper
65+
.. _`MIT`: http://opensource.org/licenses/MIT
66+
.. _`BSD-3`: http://opensource.org/licenses/BSD-3-Clause
67+
.. _`GNU GPL v3.0`: http://www.gnu.org/licenses/gpl-3.0.txt
68+
.. _`Apache Software License 2.0`: http://www.apache.org/licenses/LICENSE-2.0
69+
.. _`cookiecutter-pytest-plugin`: https://github.com/pytest-dev/cookiecutter-pytest-plugin
70+
.. _`file an issue`: https://github.com/The-Compiler/pytest-xvfb/issues
71+
.. _`pytest`: https://github.com/pytest-dev/pytest
72+
.. _`tox`: https://tox.readthedocs.org/en/latest/
73+
.. _`pip`: https://pypi.python.org/pypi/pip/
74+
.. _`PyPI`: https://pypi.python.org/pypi

appveyor.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# What Python version is installed where:
2+
# http://www.appveyor.com/docs/installed-software#python
3+
4+
environment:
5+
matrix:
6+
- PYTHON: "C:\\Python27"
7+
TOX_ENV: "py27"
8+
9+
- PYTHON: "C:\\Python33"
10+
TOX_ENV: "py33"
11+
12+
- PYTHON: "C:\\Python34"
13+
TOX_ENV: "py34"
14+
15+
- PYTHON: "C:\\Python35"
16+
TOX_ENV: "py35"
17+
18+
19+
init:
20+
- "%PYTHON%/python -V"
21+
- "%PYTHON%/python -c \"import struct;print( 8 * struct.calcsize(\'P\'))\""
22+
23+
install:
24+
- "%PYTHON%/Scripts/easy_install -U pip"
25+
- "%PYTHON%/Scripts/pip install tox"
26+
- "%PYTHON%/Scripts/pip install wheel"
27+
28+
build: false # Not a C# project, build stuff at the test step instead.
29+
30+
test_script:
31+
- "%PYTHON%/Scripts/tox -e %TOX_ENV% -- tests/test_xvfb_windows.py"
32+
33+
after_test:
34+
- "%PYTHON%/python setup.py bdist_wheel"
35+
- ps: "ls dist"
36+
37+
artifacts:
38+
- path: dist\*
39+
40+
#on_success:
41+
# - TODO: upload the content of dist/*.whl to a public wheelhouse

pytest.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[pytest]
2+
addopts = --runpytest=subprocess

pytest_xvfb.py

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# -*- coding: utf-8 -*-
2+
3+
import os
4+
import re
5+
import time
6+
import os.path
7+
import fnmatch
8+
import tempfile
9+
import subprocess
10+
11+
import pytest
12+
13+
14+
def xvfb_available():
15+
# http://stackoverflow.com/a/28909933/2085149
16+
return any(
17+
os.access(os.path.join(path, 'Xvfb'), os.X_OK)
18+
for path in os.environ["PATH"].split(os.pathsep)
19+
)
20+
21+
22+
class XvfbExitedError(Exception):
23+
24+
pass
25+
26+
27+
class Xvfb(object):
28+
29+
def __init__(self, config):
30+
self.width = int(config.getini('xvfb_width'))
31+
self.height = int(config.getini('xvfb_height'))
32+
self.colordepth = int(config.getini('xvfb_colordepth'))
33+
self.args = config.getini('xvfb_args') or []
34+
self.display = None
35+
self._old_display = None
36+
self._proc = None
37+
38+
def start(self):
39+
self._old_display = os.environ.get('DISPLAY', None)
40+
self.display = self._get_free_display()
41+
display_str = ':{}'.format(self.display)
42+
os.environ['DISPLAY'] = display_str
43+
44+
cmd = ['Xvfb', display_str, '-screen', '0',
45+
'{}x{}x{}'.format(self.width, self.height, self.colordepth)]
46+
cmd.extend(self.args)
47+
self._proc = subprocess.Popen(cmd)
48+
49+
time.sleep(0.1) # Give Xvfb a bit of time to start/fail
50+
ret = self._proc.poll()
51+
52+
if ret is not None:
53+
raise XvfbExitedError("Xvfb exited with exit code {0}".format(ret))
54+
55+
def stop(self):
56+
if self._old_display is None:
57+
del os.environ['DISPLAY']
58+
else:
59+
os.environ['DISPLAY'] == self._old_display
60+
try:
61+
self._proc.terminate()
62+
self._proc.wait()
63+
except OSError:
64+
pass
65+
66+
def _get_free_display(self):
67+
tmpdir = tempfile.gettempdir()
68+
pattern = '.X*-lock'
69+
lockfiles = fnmatch.filter(os.listdir(tmpdir), pattern)
70+
existing_displays = [int(re.match('^\.X(\d+)-lock$', name).group(1))
71+
for name in lockfiles]
72+
if existing_displays:
73+
return max(existing_displays) + 1
74+
else:
75+
return 0
76+
77+
78+
def pytest_addoption(parser):
79+
group = parser.getgroup('xvfb')
80+
group.addoption(
81+
'--no-xvfb',
82+
action='store_true',
83+
help='Disable Xvfb for tests.'
84+
)
85+
86+
parser.addini('xvfb_width', 'Width of the Xvfb display', default='800')
87+
parser.addini('xvfb_height', 'Height of the Xvfb display', default='600')
88+
parser.addini('xvfb_colordepth', 'Color depth of the Xvfb display',
89+
default='16')
90+
parser.addini('xvfb_args', 'Additional arguments for Xvfb',
91+
type='linelist')
92+
93+
94+
def pytest_configure(config):
95+
if config.getoption('--no-xvfb') or not xvfb_available():
96+
config.xvfb = None
97+
else:
98+
config.xvfb = Xvfb(config)
99+
config.xvfb.start()
100+
101+
102+
def pytest_unconfigure(config):
103+
if config.xvfb is not None:
104+
config.xvfb.stop()

setup.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
import os
5+
import codecs
6+
from setuptools import setup
7+
8+
9+
def read(fname):
10+
file_path = os.path.join(os.path.dirname(__file__), fname)
11+
return codecs.open(file_path, encoding='utf-8').read()
12+
13+
14+
setup(
15+
name='pytest-xvfb',
16+
version='0.1.0',
17+
author='Florian Bruhin',
18+
author_email='[email protected]',
19+
maintainer='Florian Bruhin',
20+
maintainer_email='[email protected]',
21+
license='MIT',
22+
url='https://github.com/The-Compiler/pytest-xvfb',
23+
description='A pytest plugin to run Xvfb for tests.',
24+
long_description=read('README.rst'),
25+
py_modules=['pytest_xvfb'],
26+
install_requires=['pytest>=2.8.1'],
27+
classifiers=[
28+
'Development Status :: 4 - Beta',
29+
'Intended Audience :: Developers',
30+
'Topic :: Software Development :: Testing',
31+
'Programming Language :: Python',
32+
'Programming Language :: Python :: 2',
33+
'Programming Language :: Python :: 2.7',
34+
'Programming Language :: Python :: 3',
35+
'Programming Language :: Python :: 3.3',
36+
'Programming Language :: Python :: 3.4',
37+
'Programming Language :: Python :: 3.5',
38+
'Programming Language :: Python :: Implementation :: CPython',
39+
'Programming Language :: Python :: Implementation :: PyPy',
40+
'Operating System :: OS Independent',
41+
'License :: OSI Approved :: MIT License',
42+
],
43+
entry_points={
44+
'pytest11': [
45+
'xvfb = pytest_xvfb',
46+
],
47+
},
48+
)

tests/conftest.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pytest_plugins = 'pytester'

0 commit comments

Comments
 (0)