py.test SetUp/TearDown for whole test suite
Asked Answered
F

2

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.

Footrace answered 18/1, 2013 at 13:25 Comment(3)
Are all your classes in the same file? Then, you could use setUpModule and tearDownModule to only do this once per moduleAlane
@Dhara: No, the test classes are split up into sub-modules.Footrace
Well, you can still import all your tests in a single file with the appropriate setUpModule calls, and run your tests from thereAlane
F
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.

Footrace answered 18/1, 2013 at 14:22 Comment(4)
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.Hob
@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.Footrace
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.Inspired
@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.Footrace
D
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

Dolly answered 15/2, 2015 at 12:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.