-
Notifications
You must be signed in to change notification settings - Fork 981
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cannot test database-created objects in the context of a webtest #15634
Comments
Oh, and the motivation behind this is that this kind of setup would allow us to write more functional (integration) tests that create a database state, and then perform actions via the web/api interface (a la browsing, logging in, uploading things, etc) with fewer mocks. |
Hi @miketheman - I opened a draft PR that doesn't fix anything, but maybe helps others reason with the code a bit. I've at least confirmed that the db contains an object :-) In my projects I sometimes do db-level queries to assert table state. I also do cleanup prior to running tests, usually doing a simple and stupid The |
I took another look today, and am still scratching my head. There's a bunch of pieces involved, and trying to tease them apart with what I know so far. We use (from the bottom up?) these libraries:
Then we layer on our own logic in config.py and db.py. THEN we create fixtures to take advantage of behaviors in tests:
So something in all of these layers is not joining the active transaction/session correctly, or potentially the step that inserts data into the database isn't closing, or sqlalchemy's implicit |
Was reading some other SQLAlchemy docs today, and saw this, might have something to do with the issue: https://docs.sqlalchemy.org/en/20/orm/session_transaction.html#joining-a-session-into-an-external-transaction-such-as-for-test-suites |
This is pretty much already what we're doing here: Lines 343 to 366 in 97d8de8
I added I also tried removing the session nesting that we have, in addition to that, but that didn't change anything either. |
The good news is I think we can use this to simplify the fixture a little bit: #15826 |
I've proposed solving this by reusing the same db session, rather than always creating a new db session in Approach was like this:
In the output, I note that there are two different PIDs (3727 and 3791) mentioned. I haven't found any definitive documentation about whether the PID indicates a new connection or session, but it was enough to start playing with a hypothesis that the WSGI application had created a new db session/connection. View postgres log
|
I could be wrong, but I think CI failures like https://github.com/pypi/warehouse/actions/runs/11057423074/job/30721387457?pr=16778 indicate that the current approach isn't 100% right -- I haven't fully triaged it, but from what I can tell:
For reference, here's the warehouse/tests/common/db/__init__.py Line 17 in 684ff39
and here's where it gets loaded into each model factory, via warehouse/tests/common/db/base.py Lines 18 to 21 in 684ff39
If I understand the lifetimes correctly here, the end result is that calls like I can't tell if this is the actual root cause, but it seems like a decent candidate for the strange test behavior I've seen (e.g. where tests sometimes pass, sometimes fail because the models appear to not be updated, sometimes fail because a route that traverses them 404s instead of 200ing). I think the fix for the above is to somehow bind these model factories' sessions to the custom TM, but I'm not sure how best to do that. |
@woodruffw that might indeed be the case. Here's something that I load in my Pytest db session fixtures:
|
Nice, thanks @benjaoming! I was trying to get something similar with patching |
Just sharing someone else's idea - open source ftw 🎉 |
Here's an example test case:
This fails with a 404 Not Found. I want to get a 200.
db_session
fixture to allow us to use theUserFactory
webtest
fixture for testingpyramid_tm
to handle transactionsI tried following the guidance here https://docs.pylonsproject.org/projects/pyramid_tm/en/latest/#testing
but I'm overlooking something with how we create sessions/transactions, and can't seem to figure out how to share the session from
db_session
into thewebtest
test app, sincepyramid_tm
will start a fresh transaction for the web request.There might be something to restructure between our
database
,app_config
fixtures to allow this - I'm a little lost, so I thought I'd write it down for anyone else to poke at.The text was updated successfully, but these errors were encountered: