ProvenPin Install

pytest fixtures + factory_boy with SQLAlchemy 2 sessions: working versions (tested 2026-10-15)

Transactional pytest fixtures that roll back per test, plus factory_boy SQLAlchemy factories with sequences, SubFactory and traits.

passed3 passed · 0 failed2026-10-15 13:32 UTC
Status
passed
Last passed
2026-10-15 13:32 UTC
Tests
3 / 3
Language
Python
Runtime
Python 3.13.16
pinned versions3
sqlalchemy@2.1.4factory-boy@3.3.3pytest@9.1.1
run it
uv venv -q .venv && uv pip install -q --python .venv/bin/python -r requirements.txt
.venv/bin/python -m pytest -q
test environment
Python 3.13.16
linux 6.17.0-1022-azure
x64
runner: github-actions 38742087302

The code

Exactly the files that passed. Your agent can pull them with get_recipe("pytest-factory-boy-sqlalchemy") (install), or see them on GitHub.

requirements.txt
sqlalchemy==2.1.4
factory-boy==3.3.3
pytest==9.1.1
models.py
from sqlalchemy import ForeignKey
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship

class Base(DeclarativeBase):
    pass

class User(Base):
    __tablename__ = "users"
    id: Mapped[int] = mapped_column(primary_key=True)
    email: Mapped[str] = mapped_column(unique=True)
    is_admin: Mapped[bool] = mapped_column(default=False)

class Order(Base):
    __tablename__ = "orders"
    id: Mapped[int] = mapped_column(primary_key=True)
    user_id: Mapped[int] = mapped_column(ForeignKey("users.id"))
    total_cents: Mapped[int]
    user: Mapped[User] = relationship()
tests/factories.py
import factory
from models import Order, User

class UserFactory(factory.alchemy.SQLAlchemyModelFactory):
    class Meta:
        model = User
        sqlalchemy_session_persistence = "flush"  # get ids without committing
    email = factory.Sequence(lambda n: f"user{n}@example.com")
    is_admin = False

    class Params:
        admin = factory.Trait(is_admin=True, email=factory.Sequence(lambda n: f"admin{n}@example.com"))

class OrderFactory(factory.alchemy.SQLAlchemyModelFactory):
    class Meta:
        model = Order
        sqlalchemy_session_persistence = "flush"
    user = factory.SubFactory(UserFactory)
    total_cents = factory.Faker("pyint", min_value=100, max_value=10000)
tests/__init__.py
tests/conftest.py
import pytest
from sqlalchemy import create_engine
from sqlalchemy.orm import Session
from models import Base
from tests.factories import OrderFactory, UserFactory

@pytest.fixture(scope="session")
def engine():
    eng = create_engine("sqlite://")
    Base.metadata.create_all(eng)
    return eng

@pytest.fixture
def session(engine):
    # each test runs inside a transaction that is rolled back afterwards
    conn = engine.connect()
    tx = conn.begin()
    s = Session(bind=conn, join_transaction_mode="create_savepoint")
    for f in (UserFactory, OrderFactory):
        f._meta.sqlalchemy_session = s
    yield s
    s.close()
    tx.rollback()
    conn.close()
tests/test_factories.py
from sqlalchemy import func, select
from models import Order, User
from tests.factories import OrderFactory, UserFactory

def test_subfactory_creates_user(session):
    o = OrderFactory()
    assert o.id and o.user.id and 100 <= o.total_cents <= 10000

def test_trait_and_batch(session):
    UserFactory.create_batch(3)
    admin = UserFactory(admin=True)
    assert admin.is_admin and admin.email.startswith("admin")
    assert session.scalar(select(func.count()).select_from(User)) == 4

def test_isolation_between_tests(session):
    assert session.scalar(select(func.count()).select_from(Order)) == 0
pytest.ini
[pytest]
pythonpath = .

Connect to ProvenPin

Add the free MCP server so your agent can pull this recipe and others like it. Same setup as the docs.

terminal
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp

Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.