Peewee: playhouse.flask_utils.FlaskDB and testing

Created on 8 Mar 2017  路  7Comments  路  Source: coleifer/peewee

I tried to write some test for a basic app using playhouse.flask_utils.FlaskDB and sqlite but I couldn't manage to make it work with flask.Flask.test_client. This is a tool coming with Flask allowing to make easily request against the app.

Some documentation on the subject would be welcome as test are an important part of an application. I spend a couple of day on the problem then I moved the use bare peewee, without FlaskDB.

Most helpful comment

I wrote a small gist with a small flask app using FlaskDB (30 lines) and a test:
https://gist.github.com/gkrnours/f2fa9609617c27dd7dc621eff8eb898e
The test try to follow http://flask.pocoo.org/docs/0.12/testing/#testing

The app run as excepted but the test fail when using the test_client with peewee.OperationalError: Connection already open.
Maybe I'm doing something wrong.

Traceback (most recent call last):
  File "test.py", line 22, in test_client
    self.app.get("/")
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/werkzeug/test.py", line 778, in get
    return self.open(*args, **kw)
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/flask/testing.py", line 127, in open
    follow_redirects=follow_redirects)
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/werkzeug/test.py", line 751, in open
    response = self.run_wsgi_app(environ, buffered=buffered)
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/werkzeug/test.py", line 668, in run_wsgi_app
    rv = run_wsgi_app(self.application, environ, buffered=buffered)
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/werkzeug/test.py", line 871, in run_wsgi_app
    app_rv = app(environ, start_response)
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/flask/app.py", line 1994, in __call__
    return self.wsgi_app(environ, start_response)
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/flask/app.py", line 1985, in wsgi_app
    response = self.handle_exception(e)
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/flask/app.py", line 1540, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/flask/_compat.py", line 33, in reraise
    raise value
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/flask/app.py", line 1982, in wsgi_app
    response = self.full_dispatch_request()
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/flask/app.py", line 1614, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/flask/app.py", line 1517, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/flask/_compat.py", line 33, in reraise
    raise value
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/flask/app.py", line 1610, in full_dispatch_request
    rv = self.preprocess_request()
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/flask/app.py", line 1831, in preprocess_request
    rv = func()
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/playhouse/flask_utils.py", line 171, in connect_db
    self.database.connect()
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/peewee.py", line 3652, in connect
    raise OperationalError('Connection already open')
peewee.OperationalError: Connection already open

All 7 comments

Welllll... based on your issue description, there's not really anything I can go off of besides that it didn't work for your tests. Can you provide me with something I can reproduce? Some code that exemplifies the issue? What "not working" actually means?

I wrote a small gist with a small flask app using FlaskDB (30 lines) and a test:
https://gist.github.com/gkrnours/f2fa9609617c27dd7dc621eff8eb898e
The test try to follow http://flask.pocoo.org/docs/0.12/testing/#testing

The app run as excepted but the test fail when using the test_client with peewee.OperationalError: Connection already open.
Maybe I'm doing something wrong.

Traceback (most recent call last):
  File "test.py", line 22, in test_client
    self.app.get("/")
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/werkzeug/test.py", line 778, in get
    return self.open(*args, **kw)
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/flask/testing.py", line 127, in open
    follow_redirects=follow_redirects)
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/werkzeug/test.py", line 751, in open
    response = self.run_wsgi_app(environ, buffered=buffered)
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/werkzeug/test.py", line 668, in run_wsgi_app
    rv = run_wsgi_app(self.application, environ, buffered=buffered)
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/werkzeug/test.py", line 871, in run_wsgi_app
    app_rv = app(environ, start_response)
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/flask/app.py", line 1994, in __call__
    return self.wsgi_app(environ, start_response)
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/flask/app.py", line 1985, in wsgi_app
    response = self.handle_exception(e)
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/flask/app.py", line 1540, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/flask/_compat.py", line 33, in reraise
    raise value
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/flask/app.py", line 1982, in wsgi_app
    response = self.full_dispatch_request()
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/flask/app.py", line 1614, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/flask/app.py", line 1517, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/flask/_compat.py", line 33, in reraise
    raise value
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/flask/app.py", line 1610, in full_dispatch_request
    rv = self.preprocess_request()
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/flask/app.py", line 1831, in preprocess_request
    rv = func()
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/playhouse/flask_utils.py", line 171, in connect_db
    self.database.connect()
  File "/home/gkr/work/web/peewee-flask/nv/lib/python3.4/site-packages/peewee.py", line 3652, in connect
    raise OperationalError('Connection already open')
peewee.OperationalError: Connection already open

The error seems pretty clear to me. Are you opening a database connection (even implicitly, to create tables, for instance) anywhere in your tests? If so, be sure to close it. The FlaskDB helper binds handlers to the request setup/teardown cycle in which it connects/closes, respectively. If there's already a connection open in the given thread in which the request is run, then you'll see the above error. It's not a bug, it's a sign to you that you've left a connection dangling somewhere.

I do not leave open connection. FlaskDB do when used with the Flask test_client.
The only time I open the database is for creating the table and I close it 2 line after opening it.

That's the whole point of the issue, I had to choose between FlaskDB and testing my application.

Sorry, reopening to look into this more.

I see the issue. The problem is that you're initializing the database once for every test-case. Because there are two test-cases, the database gets "init_app()" called twice. Inside db.init_app(), handlers are bound to the app's before_request() and request_teardown() hooks. Inside the before_request() hook, the conn is opened.

The problem can be resolved by only calling app.init_db() once. Your app is essentially a singleton object so it maintains its state from run to run.

Not a bug in peewee, but in the way you're setting up your tests. Hope that makes sense.

The explanation make sense yes.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ezk84 picture ezk84  路  4Comments

razodactyl picture razodactyl  路  3Comments

dev-zero picture dev-zero  路  4Comments

alexpantyukhin picture alexpantyukhin  路  5Comments

MozzieHan picture MozzieHan  路  4Comments