J'ai créé un « gestionnaire » objet autour d'un moteur de base de données SQLAlchemy/connexion/session:Créer une transaction à DB opérations Rollback Autour de ce `manager` Structure
Base = declarative_base()
class Manager(object):
def __init__(self, connection: str = 'sqlite://'):
self.engine = create_engine(connection, echo=True)
Base.metadata.create_all(self.engine)
self.sessionmaker = sessionmaker(bind=self.engine)
self.session = scoped_session(self.sessionmaker)
def do_db_stuff(self):
self.session.query(Whatever).all()
def ensure_thing(self):
thing = Thing()
self.session.add(thing)
self.session.commit()
Je voudrais créer deux py.test fixtures: une pour instancier le gestionnaire et une pour envelopper et annuler les transactions dans les tests qui peuvent appeler commit. This is the pattern J'ai essayé de suivre, sans succès:
@pytest.fixture(scope='session')
def manager():
m = Manager()
return m
@pytest.fixture(scope='function')
def manager_session(manager):
connection = manager.session.connection()
transaction = connection.begin()
yield manager
manager.session.close()
transaction.rollback()
connection.close()
Malheureusement, les objets créés par le gestionnaire, même quand ils sont entourés par le bâton au-dessus autour après l'appel à transaction.rollback()
.
Quelle est la bonne façon d'encapsuler une transaction autour d'une session existante comme celle-ci?
EDIT:
Une autre, différente tentative:
@pytest.fixture(scope='function')
def manager_session(manager):
connection = manager.engine.connect()
transaction = connection.begin()
manager.sessionmaker.configure(bind=connection)
yield manager
manager.session.close()
transaction.rollback()
EDIT 2:
Une troisième tentative qui semble fonctionner, avec la mise en garde mentionnée dans Ilja Everilä's answer below ce code enfilée causerait des ennuis.
@pytest.fixture(scope='session')
def manager():
return Manager()
@pytest.fixture(scope='function')
def manager_transaction(manager):
connection = manager.engine.connect()
transaction = connection.begin()
manager.session_maker.configure(bind=connection)
yield manager
manager.session_maker.configure(bind=manager.engine)
manager.session.remove()
transaction.rollback()
connection.close()
Comment la 2ème tentative a-t-elle échoué? –
La panne est survenue après le premier test en utilisant l'appareil terminé et le deuxième test a commencé. Je pense (mais je ne suis pas sûr) que le deuxième test a eu la même session malgré que je l'aie fermée. Passer à 'session.remove' a corrigé cela, semble-t-il. –