urban-meal-delivery/tests/db/test_addresses_pixels.py
Alexander Hess cc75307e5a
Add DistanceMatrix class
- the class stores the data of a distance matrix between all addresses
  + air distances
  + bicycle distances
- in addition, the "path" returned by the Google Directions API are
  also stored as a JSON serialized sequence of latitude-longitude pairs
- we assume a symmetric graph
2021-09-12 16:51:10 +02:00

135 lines
4.8 KiB
Python

"""Test the ORM's `AddressPixelAssociation` model.
Implementation notes:
The test suite has 100% coverage without the test cases in this module.
That is so as the `AddressPixelAssociation` model is imported into the
`urban_meal_delivery.db` namespace so that the `Address` and `Pixel` models
can find it upon initialization. Yet, none of the other unit tests run any
code associated with it. Therefore, we test it here as non-e2e tests and do
not measure its coverage.
"""
import pytest
import sqlalchemy as sqla
from sqlalchemy import exc as sa_exc
from urban_meal_delivery import db
@pytest.fixture
def assoc(address, pixel):
"""An association between `address` and `pixel`."""
return db.AddressPixelAssociation(address=address, pixel=pixel)
@pytest.mark.no_cover
class TestSpecialMethods:
"""Test special methods in `AddressPixelAssociation`."""
def test_create_an_address_pixel_association(self, assoc):
"""Test instantiation of a new `AddressPixelAssociation` object."""
assert assoc is not None
@pytest.mark.db
@pytest.mark.no_cover
class TestConstraints:
"""Test the database constraints defined in `AddressPixelAssociation`.
The foreign keys to `City` and `Grid` are tested via INSERT and not
DELETE statements as the latter would already fail because of foreign
keys defined in `Address` and `Pixel`.
"""
def test_insert_into_database(self, db_session, assoc):
"""Insert an instance into the (empty) database."""
assert db_session.query(db.AddressPixelAssociation).count() == 0
db_session.add(assoc)
db_session.commit()
assert db_session.query(db.AddressPixelAssociation).count() == 1
def test_delete_a_referenced_address(self, db_session, assoc):
"""Remove a record that is referenced with a FK."""
db_session.add(assoc)
db_session.commit()
# Must delete without ORM as otherwise an UPDATE statement is emitted.
stmt = sqla.delete(db.Address).where(db.Address.id == assoc.address.id)
with pytest.raises(
sa_exc.IntegrityError,
match='fk_addresses_pixels_to_addresses_via_address_id_city_id',
):
db_session.execute(stmt)
def test_reference_an_invalid_city(self, db_session, address, pixel):
"""Insert a record with an invalid foreign key."""
db_session.add(address)
db_session.add(pixel)
db_session.commit()
# Must insert without ORM as otherwise SQLAlchemy figures out
# that something is wrong before any query is sent to the database.
stmt = sqla.insert(db.AddressPixelAssociation).values(
address_id=address.id,
city_id=999,
grid_id=pixel.grid.id,
pixel_id=pixel.id,
)
with pytest.raises(
sa_exc.IntegrityError,
match='fk_addresses_pixels_to_addresses_via_address_id_city_id',
):
db_session.execute(stmt)
def test_reference_an_invalid_grid(self, db_session, address, pixel):
"""Insert a record with an invalid foreign key."""
db_session.add(address)
db_session.add(pixel)
db_session.commit()
# Must insert without ORM as otherwise SQLAlchemy figures out
# that something is wrong before any query is sent to the database.
stmt = sqla.insert(db.AddressPixelAssociation).values(
address_id=address.id,
city_id=address.city.id,
grid_id=999,
pixel_id=pixel.id,
)
with pytest.raises(
sa_exc.IntegrityError,
match='fk_addresses_pixels_to_grids_via_grid_id_city_id',
):
db_session.execute(stmt)
def test_delete_a_referenced_pixel(self, db_session, assoc):
"""Remove a record that is referenced with a FK."""
db_session.add(assoc)
db_session.commit()
# Must delete without ORM as otherwise an UPDATE statement is emitted.
stmt = sqla.delete(db.Pixel).where(db.Pixel.id == assoc.pixel.id)
with pytest.raises(
sa_exc.IntegrityError,
match='fk_addresses_pixels_to_pixels_via_pixel_id_grid_id',
):
db_session.execute(stmt)
def test_put_an_address_on_a_grid_twice(self, db_session, address, assoc, pixel):
"""Insert a record that violates a unique constraint."""
db_session.add(assoc)
db_session.commit()
# Create a neighboring `Pixel` and put the same `address` as in `pixel` in it.
neighbor = db.Pixel(grid=pixel.grid, n_x=pixel.n_x, n_y=pixel.n_y + 1)
another_assoc = db.AddressPixelAssociation(address=address, pixel=neighbor)
db_session.add(another_assoc)
with pytest.raises(sa_exc.IntegrityError, match='duplicate key value'):
db_session.commit()