tests: refactor to pytest (conftest session fixture, sync wrappers for async, importorskip for playwright)
This commit is contained in:
1 parent
bb1297f8e2
commit
29fab7ff5f
5 files changed
+130
-135
No files matched your search
@@ -0,0 +1,81 @@
|
||||
"""Session fixture for the ani-web test suite.
|
||||
|
||||
Spins up a throwaway server (127.0.0.1:8399, temp data dir, seeded
|
||||
users admin/alice/bob/dave/erin) once per pytest run, tears it down
|
||||
afterwards. The real server on :8321 and its data are never touched.
|
||||
|
||||
Usage: .venv/bin/pytest tests/ -q
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
import signal
|
||||
import socket
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
import urllib.request
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
ROOT = Path(__file__).parent.parent
|
||||
PORT = 8399
|
||||
BASE = f"http://127.0.0.1:{PORT}"
|
||||
USERS = (("admin", "adminpw12345"), ("alice", "alicepw12345"), ("bob", "bobpw12345"),
|
||||
("dave", "davepw12345"), ("erin", "erinpw12345"))
|
||||
|
||||
|
||||
def _wait_ready():
|
||||
for _ in range(120):
|
||||
try:
|
||||
urllib.request.urlopen(BASE + "/login", timeout=1)
|
||||
return
|
||||
except Exception:
|
||||
time.sleep(0.5)
|
||||
raise RuntimeError("server did not start")
|
||||
|
||||
|
||||
@pytest.fixture(scope="session", autouse=True)
|
||||
def server():
|
||||
# fail fast instead of silently testing a leftover server.
|
||||
# SO_REUSEADDR: the suite's own TIME_WAIT sockets (no listener, but
|
||||
# thousands of connections) would otherwise wedge this bind for ~60s.
|
||||
s = socket.socket()
|
||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
try:
|
||||
s.bind(("127.0.0.1", PORT))
|
||||
except OSError:
|
||||
pytest.exit(f"port {PORT} is busy - is a leftover test server running?")
|
||||
finally:
|
||||
s.close()
|
||||
|
||||
data = Path(tempfile.mkdtemp(prefix="aniweb-test-"))
|
||||
os.environ["ANIWEB_DATA"] = str(data)
|
||||
sys.path.insert(0, str(ROOT))
|
||||
from server import users # noqa: E402
|
||||
for name, pw in USERS:
|
||||
users.add(name, pw)
|
||||
(data / "history").mkdir()
|
||||
(data / "history" / "admin.json").write_text(json.dumps([
|
||||
{"title": "Seed Anime", "slug_id": "seed-1", "season_id": 1, "ep_id": "1",
|
||||
"lang": "eng", "ep": "1", "pos": 10.0, "t": time.time()}]))
|
||||
|
||||
proc = subprocess.Popen(
|
||||
[sys.executable, "-m", "uvicorn", "server.app:app",
|
||||
"--host", "127.0.0.1", "--port", str(PORT)],
|
||||
cwd=ROOT, env=os.environ,
|
||||
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
|
||||
start_new_session=True)
|
||||
try:
|
||||
_wait_ready()
|
||||
yield
|
||||
finally:
|
||||
os.killpg(proc.pid, signal.SIGTERM)
|
||||
try:
|
||||
proc.wait(timeout=5)
|
||||
except subprocess.TimeoutExpired:
|
||||
os.killpg(proc.pid, signal.SIGKILL)
|
||||
proc.wait()
|
||||
shutil.rmtree(data, ignore_errors=True)
|
||||
Reference in new issue
Block a user