A simple HTTP server in Python.
Attempting to start a server on the same port as a recently-terminated server would generate this error:
socket.error: [Errno 98] Address already in use
This is because the previous server left the socket in a TIME_WAIT
state,
so it couldn't be immediately reused. Solution to this problem was discovered
in the Python Docs, in the
socket.SO_REUSEADDR
socket flag.
We knew that we needed to somehow run the server in the background for our
tests, otherwise the server would hold onto the prompt and refuse to let any
subsequent tests execute. If CTRL-C
were sent, the server would terminate
and then the following tests would have no server to which to connect.
Hints from the team of
Jonathan Stallings,
Jim Grant, and
Andrew Wilson
(their work here)
pointed us in the direction of Pytest's
yield_fixture
and the
multiprocessing
module.
Progression to spinning up a gevent server was trivial; extending testing to a gevent server was not. In retrospect, all of the tests written for the original server.py work perfectly well for gevent_server.py, once a couple pointers were properly redirected. The bigger issues, though, were the yield fixtures.
We used to have a yield fixture for each of the functional test suites,
which would start up their respective servers and keep them going, we
thought, until the end of the yield fixture's scope. Since these server
fixtures were scoped to module
, we believed they would terminate at
the end of the module. In practice, it seems that a yield fixture doesn't
terminate until the end of the entire testing session, regardless
of defined scope.
The solution - the discovery thereof again facilitated by Jonathan Stallings - is to use just a regular fixture with a process-terminating finalizer. The scope behaves properly, and autouse also still works.