Skip to content

Commit 7751eeb

Browse files
committed
testing: remove need to pass viceroy_server around
We hide the viceroy_server by making it be an autouse fixture on the class which lets us clean things up a fair bit. It stands to reason that all viceroy based tests will want a server.
1 parent 2bc81e9 commit 7751eeb

4 files changed

Lines changed: 60 additions & 56 deletions

File tree

fastly_compute/testing.py

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,14 @@ class ViceroyTestBase:
4545
@pytest.mark.integration
4646
class TestMyService(ViceroyTestBase):
4747
def test_my_endpoint(self, viceroy_server):
48-
response = self.get("/my-endpoint", viceroy_server)
48+
response = self.get("/my-endpoint")
4949
assert response.status_code == 200
5050
```
5151
"""
5252

5353
REQUEST_TIMEOUT = 10
5454
WASM_FILE = "app.wasm" # Override this in subclasses if needed
55+
server: ViceroyServer = None # Will be set by the fixture
5556

5657
@staticmethod
5758
def _find_free_port() -> int:
@@ -61,8 +62,9 @@ def _find_free_port() -> int:
6162
port = s.getsockname()[1]
6263
return port
6364

64-
@pytest.fixture(scope="class")
65-
def viceroy_server(self) -> ViceroyServer:
65+
@pytest.fixture(scope="class", autouse=True)
66+
@classmethod
67+
def viceroy_server(cls) -> ViceroyServer:
6668
"""Start viceroy server for the duration of the test class.
6769
6870
Note: This assumes the WASM file already exists. Use your build system
@@ -74,22 +76,22 @@ def viceroy_server(self) -> ViceroyServer:
7476
print("Starting viceroy server...")
7577

7678
# Check if WASM file exists
77-
wasm_path = Path(self.WASM_FILE)
79+
wasm_path = Path(cls.WASM_FILE)
7880
if not wasm_path.exists():
7981
pytest.fail(
80-
f"WASM file '{self.WASM_FILE}' not found. Please build it first."
82+
f"WASM file '{cls.WASM_FILE}' not found. Please build it first."
8183
)
8284

8385
# Find an available port
84-
port = self._find_free_port()
86+
port = cls._find_free_port()
8587
base_url = f"http://127.0.0.1:{port}"
8688
output_lines = [] # Capture all output for debugging
8789
output_lock = threading.Lock()
8890
stop_capture = threading.Event()
8991

9092
# Start viceroy process
9193
process = subprocess.Popen(
92-
["viceroy", "serve", self.WASM_FILE, "--addr", f"127.0.0.1:{port}", "-v"],
94+
["viceroy", "serve", cls.WASM_FILE, "--addr", f"127.0.0.1:{port}", "-v"],
9395
stdout=subprocess.PIPE,
9496
stderr=subprocess.STDOUT,
9597
text=True,
@@ -147,6 +149,9 @@ def capture_output_thread():
147149
process=process, base_url=base_url, output_lines=output_lines
148150
)
149151

152+
# Set the server as a class attribute so methods can access it
153+
cls.server = server
154+
150155
yield server
151156

152157
# Cleanup: stop output capture and terminate the process
@@ -159,52 +164,51 @@ def capture_output_thread():
159164
process.kill()
160165
process.wait()
161166

162-
def get(self, path: str, server: ViceroyServer, **kwargs) -> requests.Response:
167+
def get(self, path: str, **kwargs) -> requests.Response:
163168
"""Make a GET request to the viceroy server.
164169
165170
Args:
166171
path: URL path to request
167-
server: ViceroyServer instance from fixture
168172
**kwargs: Additional arguments passed to requests.get()
169173
170174
Returns:
171175
requests.Response: The HTTP response
172176
"""
173177
timeout = kwargs.pop("timeout", self.REQUEST_TIMEOUT)
174-
response = requests.get(f"{server.base_url}{path}", timeout=timeout, **kwargs)
178+
response = requests.get(
179+
f"{self.server.base_url}{path}", timeout=timeout, **kwargs
180+
)
175181
return response
176182

177-
def post(self, path: str, server: ViceroyServer, **kwargs) -> requests.Response:
183+
def post(self, path: str, **kwargs) -> requests.Response:
178184
"""Make a POST request to the viceroy server.
179185
180186
Args:
181187
path: URL path to request
182-
server: ViceroyServer instance from fixture
183188
**kwargs: Additional arguments passed to requests.post()
184189
185190
Returns:
186191
requests.Response: The HTTP response
187192
"""
188193
timeout = kwargs.pop("timeout", self.REQUEST_TIMEOUT)
189-
response = requests.post(f"{server.base_url}{path}", timeout=timeout, **kwargs)
194+
response = requests.post(
195+
f"{self.server.base_url}{path}", timeout=timeout, **kwargs
196+
)
190197
return response
191198

192-
def request(
193-
self, method: str, path: str, server: ViceroyServer, **kwargs
194-
) -> requests.Response:
199+
def request(self, method: str, path: str, **kwargs) -> requests.Response:
195200
"""Make an HTTP request to the viceroy server.
196201
197202
Args:
198203
method: HTTP method (GET, POST, PUT, DELETE, etc.)
199204
path: URL path to request
200-
server: ViceroyServer instance from fixture
201205
**kwargs: Additional arguments passed to requests.request()
202206
203207
Returns:
204208
requests.Response: The HTTP response
205209
"""
206210
timeout = kwargs.pop("timeout", self.REQUEST_TIMEOUT)
207211
response = requests.request(
208-
method, f"{server.base_url}{path}", timeout=timeout, **kwargs
212+
method, f"{self.server.base_url}{path}", timeout=timeout, **kwargs
209213
)
210214
return response

tests/README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,18 @@ from fastly_compute.testing import ViceroyTestBase
1111

1212
@pytest.mark.integration
1313
class TestMyService(ViceroyTestBase):
14-
def test_endpoint(self, viceroy_server):
15-
response = self.get("/test", viceroy_server)
14+
def test_endpoint(self):
15+
response = self.get("/test")
1616
assert response.status_code == 200
1717
```
1818

1919
**Prerequisites**: WASM file must exist (handled by your build system).
2020

2121
## Available Methods
2222

23-
- `self.get(path, viceroy_server, **kwargs)` - GET request
24-
- `self.post(path, viceroy_server, **kwargs)` - POST request
25-
- `self.request(method, path, viceroy_server, **kwargs)` - Any HTTP method
23+
- `self.get(path, **kwargs)` - GET request
24+
- `self.post(path, **kwargs)` - POST request
25+
- `self.request(method, path, **kwargs)` - Any HTTP method
2626

2727
## Configuration
2828

tests/test_app.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,23 @@
99
class TestFastlyComputeApp(ViceroyTestBase):
1010
"""Integration tests for the Fastly Compute service functionality."""
1111

12-
def test_hello_endpoint(self, viceroy_server):
12+
def test_hello_endpoint(self):
1313
"""Test the hello endpoint returns expected content."""
14-
response = self.get("/hello/test", viceroy_server)
14+
response = self.get("/hello/test")
1515

1616
assert response.status_code == 200
1717
assert response.text == "Hello test!"
1818

19-
def test_hello_endpoint_with_different_name(self, viceroy_server):
19+
def test_hello_endpoint_with_different_name(self):
2020
"""Test the hello endpoint with a different name parameter."""
21-
response = self.get("/hello/world", viceroy_server)
21+
response = self.get("/hello/world")
2222

2323
assert response.status_code == 200
2424
assert response.text == "Hello world!"
2525

26-
def test_info_endpoint(self, viceroy_server):
26+
def test_info_endpoint(self):
2727
"""Test the info endpoint returns expected JSON with WIT data."""
28-
response = self.get("/info", viceroy_server)
28+
response = self.get("/info")
2929

3030
assert response.status_code == 200
3131
assert response.headers.get("content-type", "").startswith("application/json")
@@ -45,27 +45,27 @@ def test_info_endpoint(self, viceroy_server):
4545
assert data["request_method"] == "GET"
4646
assert data["path_info"] == "/info"
4747

48-
def test_nonexistent_endpoint(self, viceroy_server):
48+
def test_nonexistent_endpoint(self):
4949
"""Test that nonexistent endpoints return 404."""
50-
response = self.get("/nonexistent", viceroy_server)
50+
response = self.get("/nonexistent")
5151

5252
assert response.status_code == 404
5353

54-
def test_post_request_handling(self, viceroy_server):
54+
def test_post_request_handling(self):
5555
"""Test that POST requests are handled correctly."""
5656
# Current app.py doesn't handle POST to /api/data, so expect 404
57-
response = self.post("/api/data", viceroy_server, json={"key": "value"})
57+
response = self.post("/api/data", json={"key": "value"})
5858
assert response.status_code == 404
5959

60-
def test_custom_headers(self, viceroy_server):
60+
def test_custom_headers(self):
6161
"""Test requests with custom headers are processed."""
6262
headers = {"X-Custom-Header": "test-value"}
63-
response = self.get("/info", viceroy_server, headers=headers)
63+
response = self.get("/info", headers=headers)
6464
assert response.status_code == 200
6565

66-
def test_error_endpoint_handling(self, viceroy_server):
66+
def test_error_endpoint_handling(self):
6767
"""Test that the error endpoint returns 500 and triggers viceroy output display."""
68-
response = self.get("/error", viceroy_server)
68+
response = self.get("/error")
6969

7070
# The endpoint should return a 500 error due to the exception
7171
assert response.status_code == 500

tests/test_testing.py

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,67 +10,67 @@
1010
class TestViceroyTestingFramework(ViceroyTestBase):
1111
"""Tests that verify the testing framework itself works correctly."""
1212

13-
def test_viceroy_server_fixture_provides_server_info(self, viceroy_server):
13+
def test_viceroy_server_fixture_provides_server_info(self):
1414
"""Test that the viceroy_server fixture provides expected attributes."""
15-
# Check that the fixture returns a ViceroyServer with expected attributes
16-
assert hasattr(viceroy_server, "process")
17-
assert hasattr(viceroy_server, "base_url")
18-
assert hasattr(viceroy_server, "output_lines")
15+
# Check that the fixture sets up a ViceroyServer with expected attributes
16+
assert hasattr(self.server, "process")
17+
assert hasattr(self.server, "base_url")
18+
assert hasattr(self.server, "output_lines")
1919

2020
# Check that base_url is properly formatted
21-
assert viceroy_server.base_url.startswith("http://127.0.0.1:")
21+
assert self.server.base_url.startswith("http://127.0.0.1:")
2222

2323
# Check that output_lines contains viceroy startup output
24-
assert len(viceroy_server.output_lines) > 0
24+
assert len(self.server.output_lines) > 0
2525
listening_lines = [
26-
line for line in viceroy_server.output_lines if "Listening on" in line
26+
line for line in self.server.output_lines if "Listening on" in line
2727
]
2828
assert len(listening_lines) > 0
2929

30-
def test_get_method_works(self, viceroy_server):
30+
def test_get_method_works(self):
3131
"""Test that the get() helper method works correctly."""
32-
response = self.get("/info", viceroy_server)
32+
response = self.get("/info")
3333

3434
# Verify it returns a requests.Response object
3535
assert isinstance(response, requests.Response)
3636
assert response.status_code == 200
3737

38-
def test_post_method_works(self, viceroy_server):
38+
def test_post_method_works(self):
3939
"""Test that the post() helper method works correctly."""
40-
response = self.post("/nonexistent", viceroy_server, json={"test": "data"})
40+
response = self.post("/nonexistent", json={"test": "data"})
4141

4242
# Verify it returns a requests.Response object
4343
assert isinstance(response, requests.Response)
4444
# POST to nonexistent endpoint should return 404
4545
assert response.status_code == 404
4646

47-
def test_request_method_works(self, viceroy_server):
47+
def test_request_method_works(self):
4848
"""Test that the request() helper method works correctly."""
49-
response = self.request("GET", "/info", viceroy_server)
49+
response = self.request("GET", "/info")
5050

5151
# Verify it returns a requests.Response object
5252
assert isinstance(response, requests.Response)
5353
assert response.status_code == 200
5454

55-
def test_request_timeout_handling(self, viceroy_server):
55+
def test_request_timeout_handling(self):
5656
"""Test that request timeouts work correctly."""
5757
# Test that normal requests work with reasonable timeout
58-
response = self.get("/info", viceroy_server, timeout=5.0)
58+
response = self.get("/info", timeout=5.0)
5959
assert response.status_code == 200
6060

6161
# Test that very short timeouts raise TimeoutError
6262
with pytest.raises(requests.exceptions.ReadTimeout):
63-
self.get("/info", viceroy_server, timeout=0.001)
63+
self.get("/info", timeout=0.001)
6464

65-
def test_custom_request_timeout_setting(self, viceroy_server):
65+
def test_custom_request_timeout_setting(self):
6666
"""Test that custom REQUEST_TIMEOUT class attribute works."""
6767
# Temporarily change the timeout
6868
original_timeout = self.REQUEST_TIMEOUT
6969
self.REQUEST_TIMEOUT = 1
7070

7171
try:
7272
# This should work with 1 second timeout
73-
response = self.get("/info", viceroy_server)
73+
response = self.get("/info")
7474
assert response.status_code == 200
7575
finally:
7676
# Restore original timeout

0 commit comments

Comments
 (0)