SPB Git

spb/countryatlas

Public
8.1 KB · 154 lines python
1from __future__ import annotations23import csv4import io56import pytest78from tests.api.conftest import COUNTRIES, assert_meta, assert_provenance, value91011def test_list_countries(get):12    body = get("/countries").json()13    assert_meta(body)14    assert body["n"] == len(COUNTRIES)15    ids = [c["id"] for c in body["items"]]16    assert ids == sorted(ids, key=lambda i: next(c["name"] for c in body["items"] if c["id"] == i))17    can = next(c for c in body["items"] if c["id"] == "CAN")18    assert can["slug"] == "canada" and can["flag"] and can["region_name"] == "North America" and can["income"] == "HIC"19    assert can["population_latest"] == pytest.approx(value("CAN", "population", 2024))20    assert can["gdp_per_capita_latest"] == pytest.approx(value("CAN", "gdp-per-capita", 2024))21    assert can["coverage_pct"] == 100.0222324def test_list_countries_filters_and_sort(get):25    g7 = get("/countries?region=g7&sort=gdp").json()26    assert {c["id"] for c in g7["items"]} == {"CAN", "USA", "FRA", "DEU", "JPN"}27    vals = [c["gdp_latest"] for c in g7["items"]]28    assert vals == sorted(vals, reverse=True)29    assert get("/countries?region=north-america").json()["n"] == 230    assert {c["id"] for c in get("/countries?income=LMC").json()["items"]} == {"IND", "NGA"}31    assert get("/countries?q=jap").json()["items"][0]["id"] == "JPN"32    assert get("/countries?region=nowhere", status=404)33    assert get("/countries?sort=bogus", status=422)343536def test_country_overview(get):37    body = get("/countries/canada").json()38    assert_meta(body)39    c = body["country"]40    assert c["id"] == "CAN" and c["iso2"] == "CA" and c["capital"] == "Ottawa" and c["borders"] == ["USA"]41    assert "g7" in {g["id"] for g in body["groups"]} and "world" in {g["id"] for g in body["groups"]}42    assert body["coverage"]["n_indicators"] == 1443    assert body["freshness"]["source_updated_at"].startswith("2026-07-01") and body["freshness"]["built_at"]44    headline = {m["indicator"]: m for m in body["headline"]}45    assert list(headline) == ["population", "gdp", "gdp-per-capita", "gdp-growth", "inflation", "unemployment-rate", "life-expectancy",46                              "median-age", "government-debt-pct-gdp", "co2-per-capita", "renewable-electricity-share", "internet-users"]47    gpc = headline["gdp-per-capita"]48    assert gpc["has_data"] and gpc["year"] == 2024 and gpc["value"] == pytest.approx(value("CAN", "gdp-per-capita", 2024))49    assert gpc["change"]["pct"] == pytest.approx(3.0) and gpc["change"]["formatted"] == "+3.0 %"50    assert gpc["rank_world"] and gpc["n_world"] == 8 and gpc["rank_region"] and gpc["n_region"] == 251    assert gpc["formatted"].endswith("k")52    assert len(gpc["sparkline"]) == 30 and gpc["sparkline"][-1][0] == 2024 and isinstance(gpc["sparkline"][-1][0], int)53    assert_provenance(gpc["provenance"])54    assert gpc["provenance"]["url"] == "https://data.worldbank.org/indicator/NY.GDP.PCAP.CD?locations=CA"55    assert gpc["provenance"]["series_code"] == "NY.GDP.PCAP.CD" and gpc["provenance"]["licence"] == "CC BY 4.0"56    # OWID provenance for co257    assert headline["co2-per-capita"]["provenance"]["url"] == "https://github.com/owid/co2-data"58    assert headline["median-age"]["provenance"]["url"] == "https://ourworldindata.org/grapher/median-age"59    topics = {t["id"]: t for t in body["topics"]}60    assert topics["economy"]["n_with_data"] >= 5 and topics["income"]["n_with_data"] == 061    assert [t["order"] for t in body["topics"]] == sorted(t["order"] for t in body["topics"])62    assert body["neighbours"][0]["id"] == "USA"636465def test_country_case_insensitive_and_iso2(get):66    assert get("/countries/can").json()["country"]["id"] == "CAN"67    assert get("/countries/CANADA").json()["country"]["id"] == "CAN"68    assert get("/countries/ca").json()["country"]["id"] == "CAN"697071def test_country_404_problem_json(client):72    r = client.get("/api/v1/countries/atlantis")73    assert r.status_code == 40474    assert r.headers["content-type"].startswith("application/problem+json")75    body = r.json()76    assert body["title"] == "Country not found" and body["status"] == 404 and "atlantis" in body["detail"]77    assert body["instance"] == "/api/v1/countries/atlantis"787980def test_country_topic(get):81    body = get("/countries/CAN/topics/economy").json()82    assert body["topic"]["id"] == "economy" and body["n_indicators"] > body["n_with_data"] > 083    subs = [s["subtopic"] for s in body["subtopics"]]84    assert subs[0] == "Output"  # registry order85    all_inds = [i for s in body["subtopics"] for i in s["indicators"]]86    with_data = [i for i in all_inds if i["has_data"]]87    without = [i for i in all_inds if not i["has_data"]]88    assert with_data and without89    assert without[0]["provenance"] is None and without[0]["value"] is None90    for m in with_data:91        assert_provenance(m["provenance"])92        assert m["sparkline"]93    get("/countries/CAN/topics/astrology", status=404)949596def test_country_series(get):97    body = get("/countries/CAN/series/gdp?from=2010&to=2026&include_alt=true").json()98    assert_meta(body)99    assert body["indicator"]["id"] == "gdp" and body["country"]["id"] == "CAN" and body["unit"] == "current US$"100    years = [v["year"] for v in body["values"]]101    assert years == list(range(2010, 2027))102    fc = [v for v in body["values"] if v["is_forecast"]]103    assert [v["year"] for v in fc] == [2025, 2026] and fc[0]["source_id"] == "imf"104    assert body["values"][0]["value"] == pytest.approx(value("CAN", "gdp", 2010))105    for v in body["values"]:106        assert_provenance(v["provenance"])107    assert body["provenance"]["source"] == "worldbank"108    assert {s["source"] for s in body["sources"]} == {"worldbank", "imf"}109    assert body["alternatives"] and body["alternatives"][0]["source_id"] == "imf"110    assert body["stats"]["last"]["year"] == 2024 and body["stats"]["cagr"] == pytest.approx(4.03, abs=0.01)111    no_fc = get("/countries/CAN/series/gdp?include_forecast=false").json()112    assert all(not v["is_forecast"] for v in no_fc["values"])113    get("/countries/CAN/series/not-an-indicator", status=404)114    get("/countries/CAN/series/gdp?from=2020&to=2010", status=400)115116117def test_country_changes_events(get):118    ch = get("/countries/BRA/changes").json()119    assert ch["n"] > 0120    sev = [c["severity"] for c in ch["items"]]121    assert sev == sorted(sev, reverse=True)122    assert ch["items"][0]["headline"] and ch["items"][0]["indicator"]["slug"]123    assert_provenance(ch["items"][0]["provenance"])124    ev = get("/countries/USA/events?limit=5").json()125    assert 0 < ev["n"] <= 5 and ev["items"][0]["kind"] in ("sign_flip", "yoy_jump")126    get("/countries/ZZZ/changes", status=404)127128129def test_country_similar_insights_dna(get):130    sim = get("/countries/CAN/similar?mode=overall").json()131    assert sim["mode"] == "overall" and "economic" in sim["modes"]132    assert sim["peers"][0]["country"]["id"] in ("USA", "DEU", "FRA", "JPN") and sim["peers"][0]["score"] > 50133    assert sim["peers"][0]["contributions"]134    ins = get("/countries/CAN/insights").json()135    assert ins["items"] and "population grew" in ins["items"][0]["text"] or "Life expectancy" in ins["items"][0]["text"]136    assert any(i["provenance"] for i in ins["items"])137    dna = get("/countries/CAN/dna").json()138    assert dna["year_ref"] == 2024 and 0 <= dna["dims"]["income"] <= 100 and dna["dims"]["trade"] is None139    assert any(d["id"] == "income" and d["label"] == "Income" for d in dna["dimensions"])140141142def test_country_download(client):143    r = client.get("/api/v1/countries/CAN/download.csv")144    assert r.status_code == 200 and r.headers["content-type"].startswith("text/csv")145    assert 'filename="countryatlas-canada.csv"' in r.headers["content-disposition"]146    lines = r.text.splitlines()147    assert lines[0].startswith("# CountryAtlas export")148    rows = list(csv.DictReader(io.StringIO("\n".join(lines[1:]))))149    assert len(rows) > 400 and {"source", "series_code", "retrieved_at", "url", "licence"} <= set(rows[0])150    assert all(r["country_id"] == "CAN" for r in rows)151    j = client.get("/api/v1/countries/CAN/download.json?include_forecast=false").json()152    assert j["n"] == sum(1 for r in rows if r["is_forecast"] == "False") and j["rows"][0]["source"]153    assert client.get("/api/v1/countries/CAN/download.xml").status_code == 400154
Files · b828cc86d5b2223081f42e670e6d1f2379c43230
Menu

Theme