19

I have a Python package that needs access to X11. I want to use Xvfb so that I do not have to have a real X11 installed on the build machines -- Hudson in this case. So, I would like to start a Xvfb server when py.test starts, use that one server for all the tests, then close it down.

How can I do that?


Note: I could start(stop) an Xvfb server in the SetUp(TearDown) in each test class but that has two problem: First, it is wasteful. Second, it does not work due to either strange Fatal IO error 0 (Success) on X server if I terminate the server correctly or I get hanging Xvfb processes that do not die. This is using xvfbwrapper if anyone is interested.

Sardathrion - against SE abuse
  • 17,269
  • 27
  • 101
  • 156

2 Answers2

20

You could use pytest-xvfb instead of messing with this… It would be easier.


It is actually fairly simple. Create a file called conftest.py in your project root which contains this:

import pytest
import os
import subprocess
import tempfile

@pytest.fixture(scope="session", autouse=True)
def start_xvfb_server (request):
    tempdir = tempfile.mkdtemp()
    xvfb_cmd = ['Xvfb',
                ':1022',
                '-screen', '0', '800x600x24',
                '-fbdir', tempdir,
                '-noreset'
    ]
    xvfb_proc = subprocess.Popen(xvfb_cmd,
            stdout=open(os.devnull),
            stderr=open(os.devnull),
            shell=False
    )
    request.addfinalizer(xvfb_proc.kill)

Now, all you have to do is to set up each tests to set the DISPLAY to 1022 which is trivial to do.

Sardathrion - against SE abuse
  • 17,269
  • 27
  • 101
  • 156
  • 3
    you might also return the port number so that other fixtures can easily access it by stating "start_xvfb_server" as an argument. Also you might want to not use "autouse=True" but instead put @pytest.mark.usefixtures("start_xvfb_server") on a class or so. This way you don't setup the process for tests not needing it. – hpk42 Jan 20 '13 at 11:33
  • @hpk42: Those would indeed be good features. However, I am not sure how to implement those. I'm struggling with the documentation and time to experiment. Feel free to either edit my code or create an answer of your own. Thanks. – Sardathrion - against SE abuse Jan 21 '13 at 07:01
  • 1
    Another change I would recommend is to use the tmpdir fixture in start_xvfb_server instead of using tmpfile.mkdtemp. That way py.test will manage your directory as strictly speaking you ought to remove the directory created by mkdtemp at some point. – flub Jan 21 '13 at 19:46
  • @flub: It appears that your edit was rejected. Can you just write an answer with it? Could you add an example as to how to use the fixture in a simple unit test? I shall upvote. – Sardathrion - against SE abuse Jan 22 '13 at 08:15
4

Alternatively, you can simply define setUpClass / tearDownClass methods, as described in the unittest module documentation: https://docs.python.org/2/library/unittest.html#unittest.TestCase.setUpClass

Since py.test v2.4, they are fully supported. This official documentation page also documents all xunit-style compatible methods: https://pytest.org/latest/xunit_setup.html

Lucas Cimon
  • 1,859
  • 2
  • 24
  • 33