Search code examples
pythonpytestthriftcoverage.pypytest-cov

How can I run a thrift server or TCP server as a pytest fixture?


platform linux2, python 2.7.12-final-0

My integration tests ping an external server but I would like to change that to use a test fixture.

I have been trying a few days to run a Thrift library TCP server as a session-scope fixture in pytest. I have arrived at trying to run the server as a background thread so that my tests are not blocked from running.

@pytest.fixture(scope="session", autouse=True)
def thrift_server():
    config = get_config()
    nprocesses = 4

    try:
        nprocesses = config['num_processes']
    except:
        pass

    args = (Handler, config['db_credentials'], config['server_port'])
    kwargs = ({'env': config['env'], 'processpool': True, 'num_processes': nprocesses,
        'handler_config': config, 'logfile': 'tests/test_server_log.txt'})

    tserver = ThriftServer()
    tserver.add_path(config['thrift_path'])
    tserver.set_service("search")

    try:
        thread = threading.Thread(target=tserver.runserver, args=args, kwargs=kwargs)
        thread.daemon = True
        thread.start()
        yield tserver
    except:
        print("BOOHOO")
    print("TEARDOWN: test server")

For each of my tests, I get an error from the pytest library code:

ERROR at setup of Tests.test_item_is_found 
venv/lib/python2.7/site-packages/_pytest/runner.py:226: in from_call
    result = func()
venv/lib/python2.7/site-packages/_pytest/runner.py:198: in <lambda>
    lambda: ihook(item=item, **kwds), when=when, reraise=reraise
venv/lib/python2.7/site-packages/pluggy/hooks.py:289: in __call__
    return self._hookexec(self, self.get_hookimpls(), kwargs)
venv/lib/python2.7/site-packages/pluggy/manager.py:87: in _hookexec
    return self._inner_hookexec(hook, methods, kwargs)
venv/lib/python2.7/site-packages/pluggy/manager.py:81: in <lambda>
    firstresult=hook.spec.opts.get("firstresult") if hook.spec else False,
venv/lib/python2.7/site-packages/_pytest/runner.py:116: in pytest_runtest_setup
    item.session._setupstate.prepare(item)
venv/lib/python2.7/site-packages/_pytest/runner.py:362: in prepare
    col.setup()
venv/lib/python2.7/site-packages/_pytest/unittest.py:119: in setup
    self._request._fillfixtures()
venv/lib/python2.7/site-packages/_pytest/fixtures.py:469: in _fillfixtures
    item.funcargs[argname] = self.getfixturevalue(argname)
venv/lib/python2.7/site-packages/_pytest/fixtures.py:479: in getfixturevalue
    return self._get_active_fixturedef(argname).cached_result[0]
venv/lib/python2.7/site-packages/_pytest/fixtures.py:502: in _get_active_fixturedef
    self._compute_fixture_value(fixturedef)
venv/lib/python2.7/site-packages/_pytest/fixtures.py:587: in _compute_fixture_value
    fixturedef.execute(request=subrequest)
venv/lib/python2.7/site-packages/_pytest/fixtures.py:894: in execute
    return hook.pytest_fixture_setup(fixturedef=self, request=request)
venv/lib/python2.7/site-packages/pluggy/hooks.py:289: in __call__
    return self._hookexec(self, self.get_hookimpls(), kwargs)
venv/lib/python2.7/site-packages/pluggy/manager.py:87: in _hookexec
    return self._inner_hookexec(hook, methods, kwargs)
venv/lib/python2.7/site-packages/pluggy/manager.py:81: in <lambda>
    firstresult=hook.spec.opts.get("firstresult") if hook.spec else False,
venv/lib/python2.7/site-packages/_pytest/fixtures.py:936: in pytest_fixture_setup
    result = call_fixture_func(fixturefunc, request, kwargs)
venv/lib/python2.7/site-packages/_pytest/fixtures.py:791: in call_fixture_func
    res = next(it)
E   StopIteration

This is a problem for which I have not found great documentation or support, so I have to ask the question..How can I set up a TCP server as a pytest fixture that my tests can consume?

As a corollary, is this a situation where I should roll-my-own or is there a good plugin to support this pytest use-case? Again, my search has turned up little on this.


Solution

  • I was able to set up a Thrift server as a pytest fixture using the following setup:

    import pytest
    import threading
    from pythrift import ThriftServer
    from myHandler import Handler
    
    
    @pytest.fixture(scope="session", autouse=True)
    def thrift_server():
         config = get_config()
         nprocesses = 4
    
         try:
             nprocesses = config['num_processes']
         except:
             pass
    
         args = (Handler, config['db_credentials'], config['server_port'])
         kwargs = ({'env': config['env'], 'processpool': True, 'num_processes': nprocesses,
             'handler_config': config, 'logfile': 'tests/test_server_log.txt'})
    
         tserver = ThriftServer()
         tserver.add_path(config['thrift_path'])
         tserver.set_service("search")
    
         try:
             thread = threading.Thread(target=tserver.run_server, args=args, kwargs=kwargs)
             thread.daemon = True
             thread.start()
             yield tserver
         except Exception as e:
             print(e)
         print("TEARDOWN: test server")