Hi there,

When we test, we sometimes create temporary classes just for a specific 
test (or group of tests).  You might want to inherit from a class that is 
part of production code, for example and override a method for testing 
purposes, etc. When these temporary classes are declarative sqlalchemy 
mapped classes, we run into all sorts of problems.

What we do is something along the lines of:
 1) create the tables for the actual model
 2) commit
 3) define the test classes and create their tables
 4) run the test logic
 5) roll back

Steps 1-2 happen one for a test run with many tests.
Steps 3-5 represents one test, so they can be repeated.

However, it seems that some cleanup is needed of mappers / the metadata / 
classes that inherit from Base, etc AFTER 5.
The sqlalchemy Table objects and mappers are now out of sync with the 
database (which has been rolled back).

What can one do to get all the sqlalchemy related stuff (metadata, mappers, 
tables and how these were set on existing classes) back in sync with the 
rolled-back database schema?  We know the metadata can be cleared (and 
reflected); we know we can clear mappers and recreate them... and we've 
tried several of these things to no avail. The example given below, however 
should work without too much clearing, surely?

We always get the first test to work, but some subsequent tests tend to 
fail. Of course, there are a large number of scenarios - test classes with 
relationships to 'real' classes, inheritance, etc. Those scenarios can 
complicate things. But here is the simplest basic example we'd like to get 
working:

from pkg_resources import require

require('sqlalchemy==0.7.7')

from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import *

connection_uri = 'sqlite:///:memory:'

engine = create_engine(connection_uri, echo=True)
Session = sessionmaker(autoflush=True, autocommit=False, bind=engine)
Base = declarative_base()
session = Session()

 
class RealClass(Base):
    __tablename__ = 'normal_class'
    id = Column(Integer, primary_key=True)
    attr =  Column(String(50))

Base.metadata.create_all(bind=session.connection())   # Creating the real 
classes (once per run)
session.commit()                                                       # 
Committed also...


def test():
    class TestClass(Base):
        __tablename__ = 'simple_test_class'
        attr =  Column(String(50))
        id = Column(Integer, primary_key=True)

        __table_args__ = {
            'extend_existing': True
            }

    Base.metadata.create_all(bind=session.connection())  # To create the 
test classes

    session.add(RealClass(attr='sdf'))
    session.flush()
    session.add(TestClass(attr='sdf'))
    session.flush()

    print session.query(RealClass).all()
    print session.query(TestClass).all()


try:
    test()  # Works
finally:
    session.rollback()

try:
    test()  # Breaks the second time round
finally:
    session.rollback()


Regards
- Iwan




-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/sqlalchemy/-/snYsPmsRjOEJ.
To post to this group, send email to sqlalchemy@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.

Reply via email to