Skip to content

Commit d2003ec

Browse files
committed
blocking_httpserver: add howto and example
1 parent 407ccfe commit d2003ec

File tree

3 files changed

+70
-0
lines changed

3 files changed

+70
-0
lines changed

doc/howto.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,3 +655,19 @@ address to ``127.0.0.1`` (and thereby fixing the host part of the URL returned
655655
by the `url_for` call) solves the issue as the client will receive the address
656656
(``127.0.0.1``) instead of the name (``localhost``) so it won't move on to the
657657
IPv6 address.
658+
659+
Running httpserver in blocking mode
660+
-----------------------------------
661+
662+
In this mode, the code which is being tested (the client) is executed in a
663+
background thread, while the server events are synchronized to the main thread,
664+
so it looks like it is running in the main thread. This allows to catch the
665+
assertions occured on the server side synchronously, it is not needed to call
666+
the `check_assertions` method, assertions are raised to the main thread.
667+
668+
This is an experimental feature so *pytest-httpserver* has no fixture for it.
669+
670+
Example:
671+
672+
.. literalinclude :: ../tests/test_blocking_httpserver_howto.py
673+
:language: python
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import threading
2+
from queue import Queue
3+
4+
import pytest
5+
import requests
6+
7+
from pytest_httpserver import BlockingHTTPServer
8+
9+
# override httpserver fixture
10+
11+
12+
@pytest.fixture
13+
def httpserver():
14+
server = BlockingHTTPServer(timeout=1)
15+
server.start()
16+
17+
yield server
18+
19+
server.clear()
20+
if server.is_running():
21+
server.stop()
22+
23+
24+
def test_simplified(httpserver: BlockingHTTPServer):
25+
def client(response_queue: Queue):
26+
response = requests.get(httpserver.url_for("/foobar"), timeout=10)
27+
response_queue.put(response)
28+
29+
# start the client, server is not yet configured
30+
# it will block until we add a request handler to the server
31+
# (see the timeout parameter of the http server)
32+
response_queue: Queue[requests.models.Response] = Queue(maxsize=1)
33+
thread = threading.Thread(target=client, args=(response_queue,))
34+
thread.start()
35+
36+
try:
37+
# check that the request is for /foobar and it is a GET method
38+
# if this does not match, it will raise AssertionError and test will fail
39+
client_connection = httpserver.assert_request(uri="/foobar", method="GET")
40+
41+
# with the received client_connection, we now need to send back the response
42+
# this makes the request.get() call in client() to return
43+
client_connection.respond_with_json({"foo": "bar"})
44+
45+
finally:
46+
# wait for the client thread to complete
47+
thread.join(timeout=1)
48+
assert not thread.is_alive() # check if join() has not timed out
49+
50+
# check the response the client received
51+
response = response_queue.get(timeout=1)
52+
assert response.status_code == 200
53+
assert response.json() == {"foo": "bar"}

tests/test_release.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ def test_sdist_contents(build: Build, version: str):
187187
"assets",
188188
"conftest.py",
189189
"test_blocking_httpserver.py",
190+
"test_blocking_httpserver_howto.py",
190191
"test_handler_errors.py",
191192
"test_headers.py",
192193
"test_json_matcher.py",

0 commit comments

Comments
 (0)