On 5/11/15 6:21 AM, José Luis Lafuente wrote:
Maybe not the best title, but I'll try to explain the problem.
I'm using sqlalchemy and pyramid on my app. I'm using a scoped_session
on every request:
from pyramid.threadlocal import get_current_request
Session = scoped_session(sessionmaker(), scopefunc=get_current_request)
I want to write some functional tests, I'm using py.test for it:
import pytest
from myapp import Session, Model
@pytest.fixture(scope='function')
def webapp(request):
from myapp import main
from webtest import TestApp
app = main({}, **settings)
Session.begin(subtransactions=True)
def fin():
Session.rollback()
Session.remove()
request.addfinalizer(fin)
return TestApp(app)
def test_search(webapp):
Session.add(Model(name='dummy'))
res = webapp.get('/', status=200)
assert res.body == 'something'
The problem I have with this code is inside the web request to '/'. I
query Session for the new model, but nothing is found. However, this
assert will success:
assert Session.query(Model).filter_by(name='dummy').one().name == 'Aa'
I think the problem is related to the argument
'scopefunc=get_current_request' of the scoped_session, and the fact
that the point where I add the model have a different scope that the
web request.
To solve it, I'm patching the session this way:
...
from sqlalchemy.util import ThreadLocalRegistry
@pytest.fixture(scope='function')
def webapp(request, monkeypatch):
monkeypatch.setattr('myapp.Session.registry',
ThreadLocalRegistry(Session.session_factory))
...
Is it a correct way? Are there better ways to add models to the
database for a functional test, rolling back them afterwards?
I'm not sure why you need to do something with "thread local" inside of
a test, as I wouldn't expect to support test suites that run
concurrently in multiple threads. If you're looking for a test
fixture where the thing surrounding all of it is "the transaction", you
should create the transaction using the Core API, then associate all
sessions with that connection/transaction. The example at
http://docs.sqlalchemy.org/en/rel_1_0/orm/session_transaction.html#joining-a-session-into-an-external-transaction-such-as-for-test-suites
illustrates this approach in the general sense. In this case, with the
global scoped_session() you probably can just patch in an alternate
sessionmaker that includes the target Connection as the bind, or even
call myapp.Session.configure(bind=my_connection), though you'd have to
revert "bind" to its former value afterwards.
Thanks,
JL
--
You received this message because you are subscribed to the Google
Groups "sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send
an email to sqlalchemy+unsubscr...@googlegroups.com
<mailto:sqlalchemy+unsubscr...@googlegroups.com>.
To post to this group, send email to sqlalchemy@googlegroups.com
<mailto:sqlalchemy@googlegroups.com>.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.