Skip to content

Commit 598b372

Browse files
committed
Add tests for cascade deletes
1 parent ba97c14 commit 598b372

File tree

1 file changed

+195
-0
lines changed

1 file changed

+195
-0
lines changed

database/test/test_models.py

+195
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import codes
22
import models
3+
import pytest
4+
from psycopg2 import sql
5+
from sqlalchemy import inspect
36
from sqlalchemy.orm import Session
47

58
"""Tests that check all relationships in sqlalchemy classes are defined correctly.
@@ -421,3 +424,195 @@ def test_interaction_event_date(
421424
assert presentation_to_the_public_interaction.event_dates == [
422425
interaction_event_date_instance
423426
]
427+
428+
429+
@pytest.mark.parametrize(
430+
"fixture_name",
431+
[
432+
pytest.param("land_use_area_instance", id="land_use_area"),
433+
pytest.param("land_use_point_instance", id="land_use_point"),
434+
pytest.param("line_instance", id="line"),
435+
pytest.param("other_point_instance", id="other_point"),
436+
pytest.param("other_area_instance", id="other_area"),
437+
pytest.param("plan_proposition_instance", id="plan_proposition"),
438+
pytest.param("empty_value_plan_regulation_instance", id="plan_regulation"),
439+
],
440+
)
441+
def test_cascade_delete_of_lifecycle_dates_using_orm(
442+
session: Session, request: pytest.FixtureRequest, fixture_name: str
443+
):
444+
"""Test that deleting a plan object cascades to the lifecycle date when using ORM.
445+
This makes sure that the cascade options are configured correctly in the SqlAlchemy models.
446+
"""
447+
448+
plan_base_object = request.getfixturevalue(fixture_name)
449+
assert len(plan_base_object.lifecycle_dates) == 1
450+
lifecycle_date = plan_base_object.lifecycle_dates[0]
451+
session.delete(plan_base_object)
452+
session.commit()
453+
454+
assert inspect(lifecycle_date).was_deleted
455+
456+
457+
@pytest.mark.parametrize(
458+
["parent_fixture_name", "child_fixture_name", "child_collection_name"],
459+
[
460+
pytest.param(
461+
"plan_regulation_group_instance",
462+
"empty_value_plan_regulation_instance",
463+
"plan_regulations",
464+
id="plan_regulation",
465+
),
466+
pytest.param(
467+
"plan_regulation_group_instance",
468+
"plan_proposition_instance",
469+
"plan_propositions",
470+
id="plan_proposition",
471+
),
472+
pytest.param(
473+
"empty_value_plan_regulation_instance",
474+
"main_use_additional_information_instance",
475+
"additional_information",
476+
id="additional_information",
477+
),
478+
],
479+
)
480+
def test_cascade_delete_using_orm(
481+
session: Session,
482+
request: pytest.FixtureRequest,
483+
parent_fixture_name: str,
484+
child_fixture_name: str,
485+
child_collection_name: str,
486+
):
487+
"""Test that deleting a parent object cascades to the child table when using ORM.
488+
This makes sure that the cascade options are configured correctly in the SqlAlchemy models.
489+
"""
490+
491+
parent_object = request.getfixturevalue(parent_fixture_name)
492+
child_object = request.getfixturevalue(child_fixture_name)
493+
494+
assert len(getattr(parent_object, child_collection_name)) == 1
495+
496+
session.delete(parent_object)
497+
session.commit()
498+
499+
assert inspect(child_object).was_deleted
500+
501+
502+
@pytest.mark.parametrize(
503+
"fixture_name",
504+
[
505+
pytest.param("land_use_area_instance", id="land_use_area"),
506+
pytest.param("land_use_point_instance", id="land_use_point"),
507+
pytest.param("line_instance", id="line"),
508+
pytest.param("other_point_instance", id="other_point"),
509+
pytest.param("other_area_instance", id="other_area"),
510+
pytest.param("plan_proposition_instance", id="plan_proposition"),
511+
pytest.param("empty_value_plan_regulation_instance", id="plan_regulation"),
512+
],
513+
)
514+
def test_cascade_delete_of_lifecycle_dates_using_db(
515+
session: Session, request: pytest.FixtureRequest, fixture_name: str
516+
):
517+
"""Test that deleting a plan object cascades to the lifecycle date when using raw SQL.
518+
This makes sure that the ON DELETE cascade options are configured correctly for the foreign keys in the database.
519+
"""
520+
521+
plan_base_object = request.getfixturevalue(fixture_name)
522+
lifecycle_object = plan_base_object.lifecycle_dates[0]
523+
524+
connection = session.connection().connection
525+
cur = connection.cursor()
526+
527+
def lifecycle_date_exists():
528+
cur.execute(
529+
sql.SQL("SELECT EXISTS (SELECT id FROM {table} WHERE id=%s)").format(
530+
table=sql.Identifier(
531+
lifecycle_object.__table__.schema, lifecycle_object.__table__.name
532+
)
533+
),
534+
(lifecycle_object.id,),
535+
)
536+
return cur.fetchone()[0]
537+
538+
def delete_plan_base_object():
539+
cur.execute(
540+
sql.SQL("DELETE FROM {table} WHERE id=%s").format(
541+
table=sql.Identifier(
542+
plan_base_object.__table__.schema, plan_base_object.__table__.name
543+
)
544+
),
545+
(plan_base_object.id,),
546+
)
547+
548+
assert lifecycle_date_exists()
549+
delete_plan_base_object()
550+
assert not lifecycle_date_exists()
551+
552+
cur.close()
553+
connection.rollback()
554+
555+
556+
@pytest.mark.parametrize(
557+
["parent_fixture_name", "child_fixture_name"],
558+
[
559+
pytest.param(
560+
"plan_regulation_group_instance",
561+
"empty_value_plan_regulation_instance",
562+
id="plan_regulation",
563+
),
564+
pytest.param(
565+
"plan_regulation_group_instance",
566+
"plan_proposition_instance",
567+
id="plan_proposition",
568+
),
569+
pytest.param(
570+
"empty_value_plan_regulation_instance",
571+
"main_use_additional_information_instance",
572+
id="additional_information",
573+
),
574+
],
575+
)
576+
def test_cascade_delete_using_db(
577+
session: Session,
578+
request: pytest.FixtureRequest,
579+
parent_fixture_name: str,
580+
child_fixture_name: str,
581+
):
582+
"""Test that deleting a parent object cascades to the child table when using raw SQL.
583+
This makes sure that the ON DELETE cascade options are configured correctly for the foreign keys in the database.
584+
"""
585+
586+
parent_object = request.getfixturevalue(parent_fixture_name)
587+
child_object = request.getfixturevalue(child_fixture_name)
588+
589+
connection = session.connection().connection
590+
cur = connection.cursor()
591+
592+
def child_object_exists():
593+
cur.execute(
594+
sql.SQL("SELECT EXISTS (SELECT id FROM {table} WHERE id=%s)").format(
595+
table=sql.Identifier(
596+
child_object.__table__.schema, child_object.__table__.name
597+
)
598+
),
599+
(child_object.id,),
600+
)
601+
return cur.fetchone()[0]
602+
603+
def delete_parent_object():
604+
cur.execute(
605+
sql.SQL("DELETE FROM {table} WHERE id=%s").format(
606+
table=sql.Identifier(
607+
parent_object.__table__.schema, parent_object.__table__.name
608+
)
609+
),
610+
(parent_object.id,),
611+
)
612+
613+
assert child_object_exists()
614+
delete_parent_object()
615+
assert not child_object_exists()
616+
617+
cur.close()
618+
connection.rollback()

0 commit comments

Comments
 (0)