【问题标题】:struggling to test flask-dance / flask-security / flask-sqlalchemy / pytest努力测试烧瓶舞蹈/烧瓶安全/烧瓶-sqlalchemy/pytest
【发布时间】:2019-01-04 21:20:45
【问题描述】:

我的应用程序需要登录到 google 以便以后使用 google api。我有烧瓶舞蹈、烧瓶安全、烧瓶 sqlalchemy 工作到可以在我的开发系统中登录和注销的地步。

我一直在努力使用 pytest 测试登录。我正在尝试通过调用 flask_security.login_user 来强制登录,但 test_login 失败,好像没有人登录一样。我怀疑这是由于上下文设置的问题,但我尝试了很多不同的东西,但没有找到灵丹妙药。

不幸的是,虽然我在软件开发(尤其是 python)方面有很多经验,但我没有解决这个问题所需的 pytest / flask-dance / flask-security 背景。

在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

在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

在 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

【问题讨论】:

    标签: python flask flask-sqlalchemy pytest flask-security


    【解决方案1】:

    当您调用login_user() 时,它会修改flask.session 对象。但是,在使用测试客户端时,you can only modify flask.session inside of a session transaction。如果你这样做,它应该可以工作:

    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
    

    如果您从 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
    

    很遗憾,the author of Flask-Login refuses to publish an update of the package to PyPI,所以你不能使用 PyPI 上的 Flask-Login 版本,你必须从 GitHub 安装。 (我不知道他为什么拒绝发布更新。)

    【讨论】:

    • 将假定此答案是正确的并标记为正确。但由于github.com/singingwolfboy/flask-dance/issues/182,我已经放弃使用烧瓶舞。 BTW,你的意思是烧瓶登录的作者拒绝发布更新吗?
    • 啊,但我看到这个答案并不真正取决于烧瓶舞,是吗?不幸的是,我也放弃了对代码进行单元测试的尝试。 :p
    • @LouK 是的,我的意思是烧瓶登录!我已将我的答案编辑为更正确,谢谢。
    猜你喜欢
    • 1970-01-01
    • 2021-09-07
    • 2018-10-18
    • 2012-12-29
    • 2014-07-20
    • 2020-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多