Add constraints to the SQL entities (#186)

This commit is contained in:
2023-10-06 18:48:58 +02:00
committed by GitHub
parent ea9c777217
commit 63325e7faa
2 changed files with 273 additions and 0 deletions

View File

@ -36,6 +36,18 @@ class Company(Base):
sa.UniqueConstraint("name", "city"), sa.UniqueConstraint("name", "city"),
sa.UniqueConstraint("name", "zip_code"), sa.UniqueConstraint("name", "zip_code"),
sa.UniqueConstraint("name"), sa.UniqueConstraint("name"),
sa.CheckConstraint(
"(longitude IS NULL AND latitude IS NULL AND pos_accuracy IS NULL) OR "
"(longitude IS NOT NULL AND latitude IS NOT NULL AND pos_accuracy IS NOT NULL)"
),
sa.CheckConstraint(
"longitude IS NULL OR (longitude >= -180 AND longitude <= 180)"
),
sa.CheckConstraint("latitude IS NULL OR (latitude >= -90 AND latitude <= 90)"),
sa.CheckConstraint(
"(capital_value IS NULL AND original_currency IS NULL AND capital_type IS NULL) OR "
"(capital_value IS NOT NULL AND original_currency IS NOT NULL AND capital_type IS NOT NULL)"
),
) )
id = sa.Column(sa.Integer, primary_key=True, autoincrement=True) id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)

View File

@ -1,4 +1,11 @@
"""Tests for the sql entities.""" """Tests for the sql entities."""
import datetime
from typing import Any
import pytest
import sqlalchemy as sa
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import Session
from aki_prj23_transparenzregister.utils.sql import entities from aki_prj23_transparenzregister.utils.sql import entities
@ -6,3 +13,257 @@ from aki_prj23_transparenzregister.utils.sql import entities
def test_import() -> None: # def test_import() -> None: #
"""Tests if the entities can be imported.""" """Tests if the entities can be imported."""
assert entities assert entities
@pytest.mark.parametrize(
"company_data",
[
# Test case 1: All coordinates are set or all are null (Expect failure)
{
"hr": "HR124",
"court_id": 2,
"name": "Invalid Company",
"street": "456 Elm St",
"zip_code": "54321",
"city": "Invalid City",
"longitude": 1.23,
"latitude": None,
"pos_accuracy": 0.1,
"last_update": datetime.date.fromisoformat("2023-10-02"),
"sector": "Tech",
},
# Test case 2: Longitude must not be null if latitude is set (Expect failure)
{
"hr": "HR124",
"court_id": 2,
"name": "Invalid Company",
"street": "456 Elm St",
"zip_code": "54321",
"city": "Invalid City",
"longitude": None,
"latitude": 4.56,
"pos_accuracy": 0.1,
"last_update": datetime.date.fromisoformat("2023-10-02"),
"sector": "Tech",
},
# Test case 3: Unique name and city constraint (Expect failure)
{
"hr": "HR124",
"court_id": 2,
"name": "Unique Company",
"street": "456 Elm St",
"zip_code": "54321",
"city": "City A",
"longitude": 1.23,
"latitude": None,
"pos_accuracy": 0.1,
"last_update": datetime.date.fromisoformat("2023-10-02"),
"sector": "Tech",
},
{
"hr": "HR125",
"court_id": 3,
"name": "Unique Company",
"street": "789 Oak St",
"zip_code": "98765",
"city": "City B",
"longitude": 2.34,
"latitude": 5.67,
"pos_accuracy": None,
"last_update": datetime.date.fromisoformat("2023-10-03"),
"sector": "Tech",
},
],
)
def test_constraint_enforcement(
empty_db: sa.orm.Session, company_data: dict[str, Any]
) -> None:
"""Tests if the constraint around longitude and latitude passes."""
company = entities.Company(**company_data)
empty_db.add(company)
with pytest.raises(IntegrityError):
empty_db.commit()
@pytest.mark.parametrize(
("company_data", "expect_failure"),
[
# Test case 1: Valid longitude and latitude values (Expect success)
(
{
"hr": "HR124",
"court_id": 2,
"name": "Valid Company",
"street": "456 Elm St",
"zip_code": "54321",
"city": "Valid City",
"longitude": 45.0,
"latitude": -20.0,
"pos_accuracy": 0.1,
"last_update": datetime.date.fromisoformat("2023-10-03"),
"sector": "Tech",
},
False,
),
# Test case 2: Longitude out of range (Expect failure)
(
{
"hr": "HR124",
"court_id": 2,
"name": "Invalid Longitude",
"street": "456 Elm St",
"zip_code": "54321",
"city": "Invalid City",
"longitude": 200.0, # Out of valid range
"latitude": 30.0,
"pos_accuracy": 0.1,
"last_update": datetime.date.fromisoformat("2023-10-02"),
"sector": "Tech",
},
True,
),
# Test case 3: Latitude out of range (Expect failure)
(
{
"hr": "HR124",
"court_id": 2,
"name": "Invalid Latitude",
"street": "456 Elm St",
"zip_code": "54321",
"city": "Invalid City",
"longitude": 45.0,
"latitude": -100.0, # Out of valid range
"pos_accuracy": 0.1,
"last_update": datetime.date.fromisoformat("2023-10-02"),
"sector": "Tech",
},
True,
),
],
)
def test_coordinate_range_constraints(
empty_db: sa.orm.Session, company_data: dict[str, Any], expect_failure: bool
) -> None:
company = entities.Company(**company_data)
empty_db.add(company)
if expect_failure:
with pytest.raises(IntegrityError):
empty_db.commit()
else:
empty_db.commit()
@pytest.mark.parametrize(
("company_data", "expect_failure"),
[
# Test case 1: Valid data with all columns set (Expect success)
(
{
"hr": "HR124",
"court_id": 2,
"name": "Valid Company",
"street": "456 Elm St",
"zip_code": "54321",
"city": "Valid City",
"longitude": 45.0,
"latitude": -20.0,
"pos_accuracy": 0.1,
"capital_value": 1000000.0,
"original_currency": "EUR",
"capital_type": "Equity",
"last_update": datetime.date.fromisoformat("2023-10-02"),
"sector": "Tech",
},
False,
),
# Test case 2: All capital-related columns are NULL (Expect success)
(
{
"hr": "HR125",
"court_id": 3,
"name": "No Capital Info",
"street": "789 Oak St",
"zip_code": "98765",
"city": "No Capital City",
"longitude": None,
"latitude": None,
"pos_accuracy": None,
"capital_value": None,
"original_currency": None,
"capital_type": None,
"last_update": datetime.date.fromisoformat("2023-10-03"),
"sector": "Tech",
},
False,
),
# Test case 3: Only some of the capital-related columns are set (Expect failure)
(
{
"hr": "HR126",
"court_id": 4,
"name": "Partial Capital Info",
"street": "101 Elm St",
"zip_code": "54321",
"city": "Partial Capital City",
"longitude": None,
"latitude": None,
"pos_accuracy": None,
"capital_value": 500000.0,
"original_currency": None, # Invalid because not all columns are set
"capital_type": None, # Invalid because not all columns are set
"last_update": datetime.date.fromisoformat("2023-10-04"),
"sector": "Finance",
},
True,
),
(
{
"hr": "HR126",
"court_id": 4,
"name": "Partial Capital Info",
"street": "101 Elm St",
"zip_code": "54321",
"city": "Partial Capital City",
"longitude": None,
"latitude": None,
"pos_accuracy": None,
"capital_value": 500000.0,
"original_currency": "DM",
"capital_type": None, # Invalid because not all columns are set
"last_update": datetime.date.fromisoformat("2023-10-04"),
"sector": "Finance",
},
True,
),
(
{
"hr": "HR126",
"court_id": 4,
"name": "Partial Capital Info",
"street": "101 Elm St",
"zip_code": "54321",
"city": "Partial Capital City",
"longitude": None,
"latitude": None,
"pos_accuracy": None,
"capital_value": None,
"original_currency": "EUR", # Invalid because not all columns are set
"capital_type": "Hafteinlage", # Invalid because not all columns are set
"last_update": datetime.date.fromisoformat("2023-10-04"),
"sector": "Finance",
},
True,
),
],
)
def test_capital_columns_constraints(
empty_db: Session, company_data: dict[str, Any], expect_failure: bool
) -> None:
company = entities.Company(**company_data)
empty_db.add(company)
if expect_failure:
with pytest.raises(IntegrityError):
empty_db.commit()
else:
empty_db.commit()