Prove the Database Behaves · practice
Protect Both Checkout Rules
Continue in tests/test_catalog.py. Complete test_checkout_refuses_active_items_and_full_members(tmp_path) using create_fresh_database(tmp_path, "checkout-rules.db") and catalog_db.open_database(database_path). Insert three items one at a time or in a small 1 and one active loan. Add a separate active loan for one of the first member’s items, then commit the arrangement.
For the active item, call only the public boundary:
catalog_db.checkout_item(connection, loan_id, item_id, member_id, checked_out_on)
Capture its pytest.raises and compare the exact text That item is already checked out.. Next, attempt a different available item for the full member and require the exact text That member has reached the loan limit.. The member-limit wording includes “the loan limit”; keep that complete message.
Close the acting connection and reopen the same path. Select every loan field in ID order and compare the rows with the two committed loans you arranged. That complete comparison proves neither refusal inserted a row or changed an older one.
The test should not call a private validation SELECT COUNT(*). Your arrangement establishes the checkout_item owns the decision. Testing any ValueError is also too broad because it would allow the two meanings to be swapped.
Press Run. The fixed entry invokes pytest.main(["-q", "-p", "no:cacheprovider", "tests/test_catalog.py"]) and should print:
Database tests passed: 4
Submit checks the active-item and member-limit behaviors separately. Removing either rule must make the suite fail while all four tests still collect. You are protecting two public meanings, not one general failure branch.
Task
Complete test_checkout_refuses_active_items_and_full_members(tmp_path) in tests/test_catalog.py. Arrange both conflicts with repeated execute() calls or small catalog_db.checkout_item for each attempt, compare the two exact