0
# Live Server
1
2
Run Flask applications in separate processes for integration testing. Provides real HTTP server functionality for testing external service integrations, full-stack workflows, and multi-process scenarios.
3
4
## Capabilities
5
6
### Live Server Fixture
7
8
Creates and manages a Flask application running in a separate process, enabling real HTTP requests for integration testing.
9
10
```python { .api }
11
@pytest.fixture(scope=_determine_scope)
12
def live_server(request, app, pytestconfig):
13
"""
14
Run application in a separate process.
15
16
When the live_server fixture is applied, the url_for function
17
works as expected with external URLs.
18
19
Parameters:
20
request: pytest request object
21
app: Flask application instance
22
pytestconfig: pytest configuration object
23
24
Returns:
25
LiveServer: Live server instance with start/stop control
26
"""
27
```
28
29
**Usage Example:**
30
31
```python
32
import requests
33
from flask import url_for
34
35
def test_live_server_basic(live_server):
36
"""Basic live server functionality"""
37
# Server automatically starts
38
response = requests.get(live_server.url('/ping'))
39
assert response.status_code == 200
40
assert response.json() == {'ping': 'pong'}
41
42
def test_with_external_url(live_server):
43
"""Using url_for with live server generates complete URLs"""
44
# url_for automatically includes host and port when live_server is active
45
index_url = url_for('index', _external=True)
46
assert index_url.startswith('http://localhost:')
47
48
response = requests.get(index_url)
49
assert response.status_code == 200
50
51
def test_integration_with_external_service(live_server):
52
"""Testing integration with external services"""
53
import subprocess
54
55
# Example: test webhook endpoint with external tool
56
webhook_url = live_server.url('/webhooks/github')
57
58
# Simulate external service calling webhook
59
payload = {'action': 'opened', 'pull_request': {'id': 123}}
60
response = requests.post(webhook_url, json=payload)
61
62
assert response.status_code == 200
63
assert response.json()['status'] == 'processed'
64
```
65
66
### LiveServer Class
67
68
The live server management class that handles process lifecycle, port management, and URL generation.
69
70
```python { .api }
71
class LiveServer:
72
"""
73
The helper class used to manage a live server. Handles creation and
74
stopping application in a separate process.
75
76
Parameters:
77
app: The Flask application to run
78
host: The host where to listen (default localhost)
79
port: The port to run application
80
wait: The timeout after which test case is aborted if
81
application is not started
82
clean_stop: Whether to attempt clean shutdown (default False)
83
"""
84
85
def __init__(self, app, host, port, wait, clean_stop=False):
86
"""
87
Initialize live server instance.
88
89
Parameters:
90
app: Flask application instance
91
host: str, host address to bind to
92
port: int, port number to listen on
93
wait: float, timeout in seconds for server startup
94
clean_stop: bool, whether to attempt graceful shutdown
95
"""
96
97
def start(self):
98
"""Start application in a separate process."""
99
100
def stop(self):
101
"""Stop application process."""
102
103
def url(self, url=""):
104
"""
105
Returns the complete url based on server options.
106
107
Parameters:
108
url: str, path to append to base URL (default: "")
109
110
Returns:
111
str: Complete URL including protocol, host, port, and path
112
"""
113
```
114
115
**Usage Example:**
116
117
```python
118
def test_live_server_methods(live_server):
119
"""Test LiveServer methods"""
120
# Get base URL
121
base_url = live_server.url()
122
assert base_url.startswith('http://localhost:')
123
124
# Get URL with path
125
api_url = live_server.url('/api/v1/users')
126
assert api_url == base_url + '/api/v1/users'
127
128
# Server is automatically started
129
response = requests.get(live_server.url('/health'))
130
assert response.status_code == 200
131
132
def test_manual_server_control():
133
"""Manual server lifecycle control (advanced usage)"""
134
from pytest_flask.live_server import LiveServer
135
from myapp import create_app
136
137
app = create_app()
138
server = LiveServer(app, 'localhost', 0, 5)
139
140
try:
141
server.start()
142
response = requests.get(server.url('/ping'))
143
assert response.status_code == 200
144
finally:
145
server.stop()
146
```
147
148
## Configuration Options
149
150
### Command Line Options
151
152
Configure live server behavior through pytest command line options:
153
154
```bash
155
# Start server automatically (enabled by default)
156
pytest --start-live-server
157
158
# Don't start server automatically
159
pytest --no-start-live-server
160
161
# Set server startup timeout in seconds (default: 5.0)
162
pytest --live-server-wait=10
163
164
# Attempt to kill the live server cleanly (default: True)
165
pytest --live-server-clean-stop
166
167
# Terminate the server forcefully after stop
168
pytest --no-live-server-clean-stop
169
170
# Set server host (default: localhost)
171
pytest --live-server-host=0.0.0.0
172
173
# Set fixed port for the live_server fixture (default: 0 for random port)
174
pytest --live-server-port=8080
175
```
176
177
All these options have corresponding defaults defined in the plugin and can be configured via pytest's option system.
178
179
### INI Configuration
180
181
Configure live server scope in pytest.ini or setup.cfg:
182
183
```ini
184
[tool:pytest]
185
live_server_scope = session # Default: session
186
# Options: function, class, module, package, session
187
```
188
189
### Application Configuration
190
191
Configure server behavior through Flask application config:
192
193
```python
194
@pytest.fixture
195
def app():
196
app = create_app()
197
198
# Set fixed port for live server
199
app.config['LIVESERVER_PORT'] = 5555
200
201
return app
202
203
def test_custom_port_config(live_server):
204
"""Test with custom port configuration"""
205
assert ':5555' in live_server.url()
206
```
207
208
## Advanced Usage
209
210
### Multiple Test Scopes
211
212
Control when servers are created and destroyed:
213
214
```python
215
# pytest.ini configuration
216
[tool:pytest]
217
live_server_scope = class
218
219
# Server shared across all test methods in class
220
class TestIntegrationSuite:
221
222
def test_first_endpoint(self, live_server):
223
response = requests.get(live_server.url('/api/users'))
224
assert response.status_code == 200
225
226
def test_second_endpoint(self, live_server):
227
# Same server instance as previous test
228
response = requests.get(live_server.url('/api/posts'))
229
assert response.status_code == 200
230
```
231
232
### External Service Testing
233
234
Test applications that interact with external services:
235
236
```python
237
def test_webhook_processing(live_server):
238
"""Test webhook endpoint with actual HTTP calls"""
239
import threading
240
import time
241
242
# Set up webhook URL
243
webhook_url = live_server.url('/webhooks/payment')
244
245
# Simulate external payment service calling webhook
246
def send_webhook():
247
time.sleep(0.1) # Small delay
248
payload = {
249
'event': 'payment.completed',
250
'payment_id': 'pay_123',
251
'amount': 1000
252
}
253
requests.post(webhook_url, json=payload)
254
255
# Start webhook sender in background
256
thread = threading.Thread(target=send_webhook)
257
thread.start()
258
259
# Test the application processes webhook correctly
260
# (This would typically check database or queue state)
261
thread.join()
262
263
# Verify webhook was processed
264
response = requests.get(live_server.url('/api/payments/pay_123'))
265
assert response.status_code == 200
266
assert response.json()['status'] == 'completed'
267
```