Alexander Hess
4b6d92958d
- this code is not unit-tested due to the complexity involving interactive `folium.Map`s => visual checks give high confidence
154 lines
4.8 KiB
Python
154 lines
4.8 KiB
Python
"""Test the ORM's `Address` model."""
|
|
|
|
import pytest
|
|
import sqlalchemy as sqla
|
|
from sqlalchemy import exc as sa_exc
|
|
|
|
from urban_meal_delivery import db
|
|
from urban_meal_delivery.db import utils
|
|
|
|
|
|
class TestSpecialMethods:
|
|
"""Test special methods in `Address`."""
|
|
|
|
def test_create_address(self, address):
|
|
"""Test instantiation of a new `Address` object."""
|
|
assert address is not None
|
|
|
|
def test_text_representation(self, address):
|
|
"""`Address` has a non-literal text representation."""
|
|
result = repr(address)
|
|
|
|
assert result == f'<Address({address.street} in {address.city_name})>'
|
|
|
|
|
|
@pytest.mark.db
|
|
@pytest.mark.no_cover
|
|
class TestConstraints:
|
|
"""Test the database constraints defined in `Address`."""
|
|
|
|
def test_insert_into_database(self, db_session, address):
|
|
"""Insert an instance into the (empty) database."""
|
|
assert db_session.query(db.Address).count() == 0
|
|
|
|
db_session.add(address)
|
|
db_session.commit()
|
|
|
|
assert db_session.query(db.Address).count() == 1
|
|
|
|
def test_delete_a_referenced_address(self, db_session, address, make_address):
|
|
"""Remove a record that is referenced with a FK."""
|
|
db_session.add(address)
|
|
# Fake another_address that has the same `.primary_id` as `address`.
|
|
db_session.add(make_address(primary_id=address.id))
|
|
db_session.commit()
|
|
|
|
db_session.delete(address)
|
|
|
|
with pytest.raises(
|
|
sa_exc.IntegrityError, match='fk_addresses_to_addresses_via_primary_id',
|
|
):
|
|
db_session.commit()
|
|
|
|
def test_delete_a_referenced_city(self, db_session, address):
|
|
"""Remove a record that is referenced with a FK."""
|
|
db_session.add(address)
|
|
db_session.commit()
|
|
|
|
# Must delete without ORM as otherwise an UPDATE statement is emitted.
|
|
stmt = sqla.delete(db.City).where(db.City.id == address.city.id)
|
|
|
|
with pytest.raises(
|
|
sa_exc.IntegrityError, match='fk_addresses_to_cities_via_city_id',
|
|
):
|
|
db_session.execute(stmt)
|
|
|
|
@pytest.mark.parametrize('latitude', [-91, 91])
|
|
def test_invalid_latitude(self, db_session, address, latitude):
|
|
"""Insert an instance with invalid data."""
|
|
address.latitude = latitude
|
|
db_session.add(address)
|
|
|
|
with pytest.raises(
|
|
sa_exc.IntegrityError, match='latitude_between_90_degrees',
|
|
):
|
|
db_session.commit()
|
|
|
|
@pytest.mark.parametrize('longitude', [-181, 181])
|
|
def test_invalid_longitude(self, db_session, address, longitude):
|
|
"""Insert an instance with invalid data."""
|
|
address.longitude = longitude
|
|
db_session.add(address)
|
|
|
|
with pytest.raises(
|
|
sa_exc.IntegrityError, match='longitude_between_180_degrees',
|
|
):
|
|
db_session.commit()
|
|
|
|
@pytest.mark.parametrize('zip_code', [-1, 0, 9999, 100000])
|
|
def test_invalid_zip_code(self, db_session, address, zip_code):
|
|
"""Insert an instance with invalid data."""
|
|
address.zip_code = zip_code
|
|
db_session.add(address)
|
|
|
|
with pytest.raises(sa_exc.IntegrityError, match='valid_zip_code'):
|
|
db_session.commit()
|
|
|
|
@pytest.mark.parametrize('floor', [-1, 41])
|
|
def test_invalid_floor(self, db_session, address, floor):
|
|
"""Insert an instance with invalid data."""
|
|
address.floor = floor
|
|
db_session.add(address)
|
|
|
|
with pytest.raises(sa_exc.IntegrityError, match='realistic_floor'):
|
|
db_session.commit()
|
|
|
|
|
|
class TestProperties:
|
|
"""Test properties in `Address`."""
|
|
|
|
def test_is_primary(self, address):
|
|
"""Test `Address.is_primary` property."""
|
|
assert address.id == address.primary_id
|
|
|
|
result = address.is_primary
|
|
|
|
assert result is True
|
|
|
|
def test_is_not_primary(self, address):
|
|
"""Test `Address.is_primary` property."""
|
|
address.primary_id = 999
|
|
|
|
result = address.is_primary
|
|
|
|
assert result is False
|
|
|
|
def test_location(self, address):
|
|
"""Test `Address.location` property."""
|
|
latitude = float(address.latitude)
|
|
longitude = float(address.longitude)
|
|
|
|
result = address.location
|
|
|
|
assert isinstance(result, utils.Location)
|
|
assert result.latitude == pytest.approx(latitude)
|
|
assert result.longitude == pytest.approx(longitude)
|
|
|
|
def test_location_is_cached(self, address):
|
|
"""Test `Address.location` property."""
|
|
result1 = address.location
|
|
result2 = address.location
|
|
|
|
assert result1 is result2
|
|
|
|
def test_x_is_positive(self, address):
|
|
"""Test `Address.x` property."""
|
|
result = address.x
|
|
|
|
assert result > 0
|
|
|
|
def test_y_is_positive(self, address):
|
|
"""Test `Address.y` property."""
|
|
result = address.y
|
|
|
|
assert result > 0
|