what2do/tests/conftest.py

113 lines
3.3 KiB
Python

import json
from pathlib import Path
import pytest
def pytest_addoption(parser):
parser.addoption("--results-file", help="Write the human-readable terminal report to this file.")
def pytest_configure(config):
results_file = config.getoption("--results-file")
if results_file:
config.pluginmanager.register(_ResultsFilePlugin(Path(results_file)), "results-file")
class _ResultsFilePlugin:
def __init__(self, path):
self.path = path
self.reports = []
def pytest_runtest_logreport(self, report):
if report.when == "call" or report.failed:
self.reports.append(report)
def pytest_sessionfinish(self, session, exitstatus):
lines = ["What2Do automated test results", "=" * 32, ""]
for report in self.reports:
outcome = report.outcome.upper()
lines.append(f"{outcome:7} {report.nodeid} ({report.duration:.3f}s)")
if report.failed:
lines.extend(("", str(report.longrepr), ""))
counts = {outcome: sum(report.outcome == outcome for report in self.reports) for outcome in ("passed", "failed", "skipped")}
lines.extend(("", "Summary", "-------", f"Passed: {counts['passed']}", f"Failed: {counts['failed']}", f"Skipped: {counts['skipped']}", f"Exit status: {exitstatus}"))
self.path.parent.mkdir(parents=True, exist_ok=True)
self.path.write_text("\n".join(lines) + "\n")
@pytest.fixture
def source():
return {
"url": "https://example.org/events",
"timezone": "Australia/Sydney",
"venue_name": "Example Venue",
"venue_address": "1 Example St, Wollongong NSW 2500",
"latitude": -34.42,
"longitude": 150.89,
}
@pytest.fixture
def fixture_html():
def load(name):
return (Path(__file__).resolve().parent / "fixtures" / name).read_text()
return load
@pytest.fixture
def html_cards(fixture_html):
return fixture_html("event_cards.html")
class FakeResponse:
def __init__(self, *, text="", payload=None, status_code=200, url="https://example.org/events"):
self.text = text
self._payload = payload
self.status_code = status_code
self.url = url
self.content = text.encode() if payload is None else json.dumps(payload).encode()
def json(self):
return self._payload
def raise_for_status(self):
if self.status_code >= 400:
import httpx
raise httpx.HTTPStatusError("failed", request=httpx.Request("GET", self.url), response=httpx.Response(self.status_code))
class RecordingClient:
def __init__(self, responses):
self.responses = list(responses)
self.calls = []
def request(self, method, url, **kwargs):
self.calls.append((method, url, kwargs))
return self.responses.pop(0)
@pytest.fixture
def fake_response():
return FakeResponse
@pytest.fixture
def recording_client():
return RecordingClient
@pytest.fixture
def temp_db(tmp_path, monkeypatch):
import app.db as db_module
path = tmp_path / "nested" / "what2do.db"
monkeypatch.setattr(db_module, "DB_PATH", str(path))
db_module.init_db()
return path
@pytest.fixture
def source_manifest():
path = Path(__file__).parent / "fixtures" / "illawarra_sources.json"
return json.loads(path.read_text())