Database rollback fixtures in PyTest - Build an Automation Script
import pytest from sqlalchemy import create_engine, text from sqlalchemy.orm import sessionmaker # Setup database engine and sessionmaker engine = create_engine('sqlite:///test.db', echo=False, future=True) Session = sessionmaker(bind=engine, future=True) @pytest.fixture(scope='function') def db_session(): session = Session() connection = session.connection() trans = connection.begin() # start transaction try: yield session finally: trans.rollback() # rollback after test session.close() def test_insert_user(db_session): # Insert user db_session.execute(text("INSERT INTO users (id, name) VALUES (1, 'Test User')")) db_session.commit() # commit inside session to persist in transaction # Query to verify insertion result = db_session.execute(text("SELECT name FROM users WHERE id=1")).fetchone() assert result is not None assert result[0] == 'Test User' def test_user_not_persisted(): # New session to check if user exists after rollback with Session() as session: result = session.execute(text("SELECT name FROM users WHERE id=1")).fetchone() assert result is None
The db_session fixture creates a new database session and starts a transaction before each test. It yields the session to the test function. After the test finishes, the fixture rolls back the transaction to undo any changes made during the test, ensuring the database stays clean.
In test_insert_user, we insert a user and commit inside the transaction so the data is visible within the test. We then query to confirm the user exists. Because the fixture rolls back after the test, the inserted user is not saved permanently.
The test_user_not_persisted test opens a new session and verifies that the user inserted in the previous test does not exist, confirming the rollback worked.
This approach keeps tests isolated and prevents side effects between tests.
Now add data-driven testing with 3 different user names to insert and verify rollback for each