Drops the schools with neither results nor an Ofsted grade, adds /admissions which was never listed, replaces the invented priority and changefreq with a lastmod taken from each school's Ofsted date. lastmod is omitted where no date is known rather than defaulted to now. An always-now lastmod is a claim Google learns to distrust; absent honestly means unknown. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015mWQnpye9F299NVRCCSRvj
95 lines
2.9 KiB
Python
95 lines
2.9 KiB
Python
"""Tests for sitemap generation (spec 2026-08-20, workstream W1).
|
|
|
|
The sitemap is built from the in-memory school DataFrame, so these inject a
|
|
small frame via monkeypatch rather than touching a database.
|
|
"""
|
|
|
|
import numpy as np
|
|
import pandas as pd
|
|
import pytest
|
|
|
|
|
|
def _schools_df() -> pd.DataFrame:
|
|
"""Two schools: one with results, one with neither results nor Ofsted."""
|
|
base = {
|
|
"local_authority": "Testshire",
|
|
"school_type": "Academy",
|
|
"phase": "Primary",
|
|
"year": 202425,
|
|
"ofsted_date": None,
|
|
}
|
|
return pd.DataFrame(
|
|
[
|
|
{**base, "urn": 100001, "school_name": "Alpha Primary",
|
|
"rwm_expected_pct": 62.0, "attainment_8_score": np.nan,
|
|
"ofsted_grade": 2.0},
|
|
{**base, "urn": 100002, "school_name": "Ghost Primary",
|
|
"rwm_expected_pct": np.nan, "attainment_8_score": np.nan,
|
|
"ofsted_grade": np.nan},
|
|
]
|
|
)
|
|
|
|
|
|
@pytest.fixture()
|
|
def sitemap(monkeypatch) -> str:
|
|
from backend import app as app_module
|
|
|
|
monkeypatch.setattr(app_module, "load_school_data", _schools_df)
|
|
return app_module.build_sitemap()
|
|
|
|
|
|
def test_every_loc_uses_the_www_host(sitemap):
|
|
# The apex 301s to www. A <loc> that redirects burns a crawl per URL.
|
|
assert "https://www.schoolcompare.co.uk" in sitemap
|
|
assert "https://schoolcompare.co.uk" not in sitemap
|
|
|
|
|
|
def test_school_with_results_is_listed(sitemap):
|
|
assert "/school/100001-alpha-primary" in sitemap
|
|
|
|
|
|
def test_school_with_no_results_and_no_ofsted_is_omitted(sitemap):
|
|
# Nothing for a search result to say about it. Submitting it spends crawl
|
|
# budget and drags the corpus-wide quality signal down.
|
|
assert "/school/100002" not in sitemap
|
|
|
|
|
|
def test_no_invented_priority_or_changefreq(sitemap):
|
|
# Google ignores both. They were noise dressed as signal.
|
|
assert "<priority>" not in sitemap
|
|
assert "<changefreq>" not in sitemap
|
|
|
|
|
|
def test_ofsted_date_becomes_lastmod(monkeypatch):
|
|
from backend import app as app_module
|
|
import datetime
|
|
|
|
def _df():
|
|
base = _schools_df()
|
|
base.loc[base["urn"] == 100001, "ofsted_date"] = datetime.date(2024, 3, 14)
|
|
return base
|
|
|
|
monkeypatch.setattr(app_module, "load_school_data", _df)
|
|
xml = app_module.build_sitemap()
|
|
assert "<lastmod>2024-03-14</lastmod>" in xml
|
|
|
|
|
|
def test_no_lastmod_invented_when_date_unknown(monkeypatch):
|
|
# An always-now lastmod is a claim Google learns to distrust. Absent
|
|
# honestly means unknown.
|
|
from backend import app as app_module
|
|
|
|
def _df():
|
|
df = _schools_df()
|
|
df["ofsted_date"] = None
|
|
return df
|
|
|
|
monkeypatch.setattr(app_module, "load_school_data", _df)
|
|
xml = app_module.build_sitemap()
|
|
assert "<lastmod>" not in xml
|
|
|
|
|
|
def test_static_routes_are_listed(sitemap):
|
|
for path in ("/", "/rankings", "/compare", "/admissions"):
|
|
assert f"<loc>https://www.schoolcompare.co.uk{path}</loc>" in sitemap
|