简体   繁体   English

努力测试flask-dance / flask-security / flask-sqlalchemy / pytest

[英]struggling to test flask-dance / flask-security / flask-sqlalchemy / pytest

My application requires login to google for later use of google apis. 我的应用程序要求登录到Google,以便以后使用Google API。 I have flask-dance, flask-security, flask-sqlalchemy working to the point where I can do the log in and log out in my development system. 我有flask-dance,flask-security,flask-sqlalchemy工作到可以在开发系统中登录和注销的程度。

What I've been struggling with is testing of the login using pytest. 我一直在努力的是使用pytest对登录进行测试。 I am trying force the login with the call to flask_security.login_user, but test_login fails as if nobody is logged in. I suspect this is a problem because of context setting, but I have tried a lot of different things and haven't found the magic elixir. 我正在尝试通过调用flask_security.login_user强制登录,但test_login失败,好像没有人登录。我怀疑由于上下文设置而导致此问题,但是我尝试了很多不同的方法,但没有找到魔术长生不老药。

Unfortunately, while I have a lot of experience in software development in general and python in particular, I don't have the pytest / flask-dance / flask-security background needed to solve this. 不幸的是,尽管我在软件开发方面尤其是在python方面有很多经验,但我没有解决该问题所需的pytest / flask-dance / flask-security背景。

in settings.py 在settings.py中

class Testing():
    # default database
    SQLALCHEMY_DATABASE_URI = 'sqlite:///:memory:'

    TESTING = True
    WTF_CSRF_ENABLED = False

    # need to set SERVER_NAME to something, else get a RuntimeError about not able to create URL adapter
    SERVER_NAME = 'dev.localhost'

    # need a default secret key - in production replace by config file
    SECRET_KEY = "<test secret key>"

    # fake  credentials
    GOOGLE_OAUTH_CLIENT_ID = 'fake-client-id'
    GOOGLE_OAUTH_CLIENT_SECRET = 'fake-client-secret'

    # need to allow logins in flask-security. see https://github.com/mattupstate/flask-security/issues/259
    LOGIN_DISABLED = False

in conftest.py 在conftest.py中

import pytest

from racesupportcontracts import create_app
from racesupportcontracts.dbmodel import db
from racesupportcontracts.settings import Testing

@pytest.fixture
def app():
    app = create_app(Testing)
    yield app

@pytest.fixture
def dbapp(app):
    db.drop_all()
    db.create_all()
    yield app

in test_basic.py 在test_basic.py中

def login_test_user(email):
    from racesupportcontracts.dbmodel import db, User
    from flask_security import login_user
    user = User.query.filter_by(email=email).one()
    login_user(user)
    db.session.commit()

def test_login(dbapp):
    app = dbapp
    from racesupportcontracts.dbmodel import db, init_db
    from racesupportcontracts import user_datastore
    from flask import url_for
    # init_db should create at least superadmin, admin roles
    init_db(defineowner=False)
    useremail = 'testuser@example.com'
    with app.test_client() as client:
        create_user(useremail, 'superadmin')
        login_test_user(useremail)
        resp = client.get('/', follow_redirects=True)
        assert resp.status_code == 200
        assert url_for('admin.logout') in resp.data

When you call login_user() , that modifies the flask.session object. 当您调用login_user() ,将修改flask.session对象。 However, when using the test client, you can only modify flask.session inside of a session transaction . 但是,使用测试客户端时, 只能在会话事务内部修改flask.session It should work if you do this: 如果这样做,它应该可以工作:

with app.test_client() as client:
    with client.session_transaction() as sess:
        sess["user_id"] = 1  # if you want user 1 to be logged in for this test

    resp = client.get('/', follow_redirects=True)
    # make whatever assertions you want

If you install the latest version of Flask-Login from GitHub, you can also use the FlaskLoginClient class to make this more readable: 如果您从GitHub安装了最新版本的Flask-Login ,则还可以使用FlaskLoginClient类使其更具可读性:

# in conftest.py
from flask_login import FlaskLoginClient

@pytest.fixture
def app():
    app = create_app(Testing)
    app.test_client_class = FlaskLoginClient
    yield app


# in test_basic.py
def test_login(app):
    user = User.query.filter_by(email='testuser@example.com').one()
    with app.test_client(user=user) as client:
        resp = client.get('/', follow_redirects=True)
        # make whatever assertions you want

Unfortunately, the author of Flask-Login refuses to publish an update of the package to PyPI , so you can't use the version of Flask-Login that is on PyPI, you have to install from GitHub. 不幸的是, Flask-Login的作者拒绝将软件包的更新发布到PyPI ,因此您不能使用PyPI上的Flask-Login版本, 必须从GitHub安装。 (I have no idea why he refuses to publish an update.) (我不知道他为什么拒绝发布更新。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM