8

I am spinning up a Waitress web server in a background thread to run functional tests. How it is possible to clean up and quit waitress at the end of test run in clean(ish) manner? The public waitress API gives only one way entry point which expects KeyboardInterrupt as the quit signal.

Currently I just run the server in a daemon thread and all new web servers are pending clean up until the test runner quits.

My test web server code:

"""py.test fixtures for spinning up a WSGI server for functional test run."""

import threading
import time
from pyramid.router import Router
from waitress import serve
from urllib.parse import urlparse

import pytest

from backports import typing

#: The URL where WSGI server is run from where Selenium browser loads the pages
HOST_BASE = "http://localhost:8521"


class ServerThread(threading.Thread):
    """Run WSGI server on a background thread.

    This thread starts a web server for a given WSGI application. Then the Selenium WebDriver can connect to this web server, like to any web server, for running functional tests.
    """

    def __init__(self, app:Router, hostbase:str=HOST_BASE):
        threading.Thread.__init__(self)
        self.app = app
        self.srv = None
        self.daemon = True
        self.hostbase = hostbase

    def run(self):
        """Start WSGI server on a background to listen to incoming."""
        parts = urlparse(self.hostbase)
        domain, port = parts.netloc.split(":")

        try:
            # TODO: replace this with create_server call, so we can quit this later
            serve(self.app, host='127.0.0.1', port=int(port))
        except Exception as e:
            # We are a background thread so we have problems to interrupt tests in the case of error. Try spit out something to the console.
            import traceback
            traceback.print_exc()

    def quit(self):
        """Stop test webserver."""

        # waitress has no quit

        # if self.srv:
        #    self.srv.shutdown()
Mikko Ohtamaa
  • 82,057
  • 50
  • 264
  • 435
  • 1
    Have you looked into using `webtest` instead of spinning up a web server? – X-Istence Sep 19 '15 at 19:47
  • WebTest does not offer a real web server, does not serve real web pages, thus making it impossible to test front-end code. Anything having JavaScript logic cannot be tested. – Mikko Ohtamaa Sep 19 '15 at 22:45

1 Answers1

4

Webtest provides a WSGI server named StopableWSGIServer that gets started in a separate thread, and then can be shutdown() when you are done running your tests.

Check out: https://docs.pylonsproject.org/projects/webtest/en/latest/api.html#module-webtest.http

According to the documentation it was specifically built for use with casperjs or selenium.

gene_wood
  • 1,960
  • 4
  • 26
  • 39
X-Istence
  • 16,324
  • 6
  • 57
  • 74
  • Thank you for the answer. I was using WebTest before but I switched to Waitress due to low performance with WebTest. My tests execute 3x - 4x faster when served by Waitress. I don't know why, but I assume that it's because Waitress has been optimized for real workloads. – Mikko Ohtamaa Sep 30 '15 at 21:12
  • 1
    Webtest's StopableWSGIServer is using Waitress: https://github.com/Pylons/webtest/blob/master/webtest/http.py#L17 – X-Istence Oct 01 '15 at 19:03
  • Ok. Let me investigate this little deeper. – Mikko Ohtamaa Oct 01 '15 at 19:29
  • Looks like Waitress was added in webtest 2.0 and I must have been using old recipe (from 1.x? era) with wsgiref. This is perfect. thank you! – Mikko Ohtamaa Oct 01 '15 at 19:40