Reputation: 547
So I've tried writing some tests for my Flask application for a couple of days but I can't get it to run. The tests pass but it gets stuck on PASSED.
I've cloned cookiecutter-flask (cookiecutter-flask) and it runs webtest together with pytest (I think). My conftest.py looks the same as it does in the repo (conftest.py)
These are my current tests:
def test_app(testapp):
app = create_app(TestConfig)
res = testapp.get('/')
res.status_code == 200
This pass and it continues.
def test_create_admin_user(db, testapp):
password = bcrypt.generate_password_hash('test')
User.create(
uid='00000000000000000000',
email='[email protected]',
password=password,
active=1
)
user = User.query.filter_by(email='[email protected]').first()
assert user.email == '[email protected]'
This is where I'm lost and the test gets stuck on PASSED and doesn't do anything. When I force interrupt the process I get this:
Traceback (most recent call last):
File "manage.py", line 68, in <module>
manager.run()
File "/home/johan/Development/venv_python/local/lib/python2.7/site-packages/flask_script/__init__.py", line 412, in run
result = self.handle(sys.argv[0], sys.argv[1:])
File "/home/johan/Development/venv_python/local/lib/python2.7/site-packages/flask_script/__init__.py", line 383, in handle
res = handle(*args, **config)
File "/home/johan/Development/venv_python/local/lib/python2.7/site-packages/flask_script/commands.py", line 216, in __call__
return self.run(*args, **kwargs)
File "/home/johan/Development/venv_python/local/lib/python2.7/site-packages/flask/ctx.py", line 386, in __exit__
self.auto_pop(exc_value)
File "/home/johan/Development/venv_python/local/lib/python2.7/site-packages/flask/ctx.py", line 374, in auto_pop
self.pop(exc)
File "/home/johan/Development/venv_python/local/lib/python2.7/site-packages/flask/ctx.py", line 357, in pop
% (rv, self)
AssertionError: Popped wrong request context. (<RequestContext 'http://localhost/' [GET] of backend.app> instead of <RequestContext 'http://localhost/' [GET] of backend.app>)
I've found the following thread in flask about testing (granted, this is Flask-Testing but I thought that it has some relevance, maybe it doesn't: issue) and changed my test-config so it contains PRESERVE_CONTEXT_ON_EXCEPTION = False but it still just hangs.
Anybody have any ideas I can try? I'm not super familiar with testing per se so it probably is something that I'm doing wrong.
Upvotes: 5
Views: 2094
Reputation: 3226
The db
fixture provided by flask-cookiecutter
is prone to locking up, and this is probably what's hanging your tests (this was the case for me when I first started writing tests for a flask-cookiecutter
based app).
Here's a better db
fixture (to replace the one in your tests/conftest.py
file):
@pytest.yield_fixture(scope='function')
def db(app):
_db.app = app
with app.app_context():
_db.session.remove()
_db.drop_all()
_db.create_all()
yield _db
_db.session.remove()
_db.drop_all()
## This dispose() call is needed to avoid the DB locking
## between tests.
## Thanks to:
## http://stackoverflow.com/a/18293157/2066849
_db.get_engine(_db.app).dispose()
Could also be an issue with the app context, but that isn't prone to completely hang the tests as much as the DB session is.
You should also consider changing this fixture (and most of the other fixtures) to scope='session'
, so the DB doesn't have to be re-created for each individual test (and so the app doesn't have to be re-instantiated, although that's trivial overhead compared to the DB). But then you have to do some cleanup manually, after individual tests that modify DB records.
Upvotes: 2
Reputation: 723
You need to use the right app context
def test_create_admin_user(db, testapp):
with app.app_context():
password = bcrypt.generate_password_hash('test')
User.create(
uid='00000000000000000000',
email='[email protected]',
password=password,
active=1
)
user = User.query.filter_by(email='[email protected]').first()
assert user.email == '[email protected]'
See https://github.com/Leo-G/Flask-Scaffold/blob/master/scaffold/app/tests.py for a full example
Upvotes: 0