0%

Bewijs het gedrag van de database · oefening

Ontdek een defect in de controle op verwijzende sleutels

Een geconfigureerde verbinding moet een uitlening weigeren waarvan het voorwerp of lid niet bestaat. Alleen zien dat PRAGMA foreign_keys een waarde meldt, is minder sterk bewijs dan de verboden schrijfopdracht proberen en zowel de exception als de ongewijzigde database waarnemen.

Bewerk tests/test_catalog.py en maak test_foreign_keys_reject_missing_parents(tmp_path) af. Begin met create_fresh_database(tmp_path, "foreign-keys.db") en open de database daarna via catalog_db.open_database(database_path). Die publieke functie voor het openen van verbindingen is de interface die je test.

Zet één echt voorwerp en één echt lid klaar met gebonden INSERT-aanroepen en commit die bekende beginsituatie. Probeer een uitlening met een ontbrekend voorwerp-ID terwijl het lid-ID geldig is. Zet pytest.raises(sqlite3.IntegrityError) om de ene execute()-aanroep en voer daarna een rollback uit, zodat de verbinding klaar is voor de volgende poging. Herhaal dit met een geldig voorwerp-ID en een ontbrekend lid-ID. Beide fouten moeten een sqlite3.IntegrityError van de database zijn, niet een fout door een dubbele primaire sleutel die de test zelf heeft gekozen.

Sluit de verbinding die de handelingen uitvoerde. Open hetzelfde pad met een nieuwe verbinding en selecteer de uitleen-ID’s. Controleer met een assertion dat er geen uitleenrij bestaat. Deze laatste waarneming beantwoordt een andere vraag dan de exception: de fout trad op en liet geen blijvend opgeslagen gedeeltelijke toestand achter.

Het kan verleidelijk zijn om alleen te controleren dat de controle op verwijzende sleutels is ingeschakeld. Daarmee controleer je een instelling, maar bewijs je niet dat de beloofde interface werkt met echte verwijzingen naar bovenliggende records. Alleen via de oorspronkelijke verbinding query’s uitvoeren bewijst evenmin wat een andere verbinding ziet.

Druk op Run. Het vaste startpunt roept pytest.main(["-q", "-p", "no:cacheprovider", "tests/test_catalog.py"]) aan en moet dit melden:

Database tests passed: 3

Submit voert de opgebouwde tests twee keer uit en controleert dit scenario daarna met een verbindingsfunctie die de controle op verwijzende sleutels niet meer inschakelt. Als de nieuwe test de exacte exception verwacht en na heropenen de uitleningen inspecteert, ontdekt die de gedragsverandering. De andere twee tests blijven onafhankelijk, omdat elke functie haar eigen tmp_path ontvangt en een eigen bestandsnaam kiest.

Opdracht

Maak test_foreign_keys_reject_missing_parents(tmp_path) in tests/test_catalog.py af. Zet via catalog_db.open_database één geldig voorwerp en lid klaar, verwacht sqlite3.IntegrityError voor een ontbrekend voorwerp en voor een ontbrekend lid, draai elke poging terug, sluit, open opnieuw en controleer met een assertion dat er geen uitleenrij is achtergebleven.