Skip to content

Commit

Permalink
Mock GitHub API responses in test suite
Browse files Browse the repository at this point in the history
  • Loading branch information
khaeru committed Jan 22, 2024
1 parent c5f3d59 commit 503e3c3
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 17 deletions.
1 change: 1 addition & 0 deletions sdmx/format/xml/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ def _gh_zipball(version: Version) -> Generator["zipfile.ZipFile", None, None]:

# Map SDMX-ML schema versions to repo paths
url_part = {Version["2.1"]: "sdmx-ml-v2_1", Version["3.0.0"]: "sdmx-ml"}

# Check the latest release to get the URL to the schema zip
url = f"https://api.github.com/repos/sdmx-twg/{url_part[version]}/releases/latest"
gh_headers = {
Expand Down
54 changes: 37 additions & 17 deletions sdmx/tests/format/test_format_xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,35 @@ def test_class_for_tag():
assert xml.v30.class_for_tag("str:DataStructure") is not None


@pytest.fixture(scope="module")
def mock_gh_api():
"""Mock GitHub API responses to avoid hitting rate limits.
For each API endpoint URL queried by :func:.`_gh_zipball`, return a pared-down JSON
response that contains the required "zipball_url" key.
"""
import requests_mock

base = "https://api.github.com/repos/sdmx-twg/"

with requests_mock.Mocker(real_http=True) as m:
for api_url, zipball_url in (
("sdmx-ml-v2_1/releases/latest", "sdmx-ml-v2_1/zipball/v1.0.2"),
("sdmx-ml/releases/latest", "sdmx-ml/zipball/v3.0.0"),
):
m.get(f"{base}{api_url}", json=dict(zipball_url=f"{base}{zipball_url}"))
yield


@pytest.fixture(scope="module")
def installed_schemas(mock_gh_api, tmp_path_factory):
"""Fixture that ensures schemas are installed locally in a temporary directory."""
dir = tmp_path_factory.mktemp("schemas")
sdmx.install_schemas(dir, Version["2.1"])
sdmx.install_schemas(dir, Version["3.0.0"])
yield dir


@pytest.mark.parametrize("version", ["1", 1, None])
def test_install_schemas_invalid_version(version):
"""Ensure invalid versions throw ``NotImplementedError``."""
Expand All @@ -38,15 +67,11 @@ def test_install_schemas_invalid_version(version):

@pytest.mark.network
@pytest.mark.parametrize("version", ["2.1", "3.0"])
def test_install_schemas(tmp_path, version):
def test_install_schemas(installed_schemas, version):
"""Test that XSD files are downloaded and ready for use in validation."""
sdmx.install_schemas(schema_dir=tmp_path, version=version)

# Look for a couple of the expected files
files = ["SDMXCommon.xsd", "SDMXMessage.xsd"]
for schema_doc in files:
doc = tmp_path.joinpath(schema_doc)
assert doc.exists()
for schema_doc in ("SDMXCommon.xsd", "SDMXMessage.xsd"):
assert installed_schemas.joinpath(schema_doc).exists()


@pytest.mark.network
Expand All @@ -72,15 +97,15 @@ def test_validate_xml_invalid_version(version):
sdmx.validate_xml("samples/common/common.xml", version=version)


def test_validate_xml_no_schemas(specimen, tmp_path):
def test_validate_xml_no_schemas(tmp_path, specimen, installed_schemas):
"""Check that supplying an invalid schema path will raise ``ValueError``."""
with specimen("IPI-2010-A21-structure.xml", opened=False) as msg_path:
with pytest.raises(ValueError):
sdmx.validate_xml(msg_path, schema_dir=tmp_path)


@pytest.mark.network
def test_validate_xml_from_v2_1_samples(tmp_path):
def test_validate_xml_from_v2_1_samples(tmp_path, installed_schemas):
"""Use official samples to ensure validation of v2.1 messages works correctly."""
with _gh_zipball(Version["2.1"]) as zf:
zf.extractall(path=tmp_path)
Expand Down Expand Up @@ -109,7 +134,7 @@ def test_validate_xml_from_v2_1_samples(tmp_path):


@pytest.mark.network
def test_validate_xml_invalid_doc(tmp_path):
def test_validate_xml_invalid_doc(tmp_path, installed_schemas):
"""Ensure that an invalid document fails validation."""
msg_path = tmp_path / "invalid.xml"

Expand Down Expand Up @@ -138,13 +163,8 @@ def test_validate_xml_invalid_doc(tmp_path):

msg_path.write_bytes(sdmx.to_xml(msg))

# Install schemas for use in validation
schema_dir = tmp_path / "schemas"
schema_dir.mkdir(exist_ok=True, parents=True)
sdmx.install_schemas(schema_dir=schema_dir)

# Expect validation to fail
assert not sdmx.validate_xml(msg_path, schema_dir=schema_dir)
assert not sdmx.validate_xml(msg_path, schema_dir=installed_schemas)


def test_validate_xml_invalid_message_type():
Expand All @@ -158,7 +178,7 @@ def test_validate_xml_invalid_message_type():


@pytest.mark.network
def test_validate_xml_from_v3_0_samples(tmp_path):
def test_validate_xml_from_v3_0_samples(tmp_path, installed_schemas):
"""Use official samples to ensure validation of v3.0 messages works correctly."""
with _gh_zipball(Version["3.0.0"]) as zf:
zf.extractall(path=tmp_path)
Expand Down

0 comments on commit 503e3c3

Please sign in to comment.