PyTest с Flask -Security - проблема входа в систему для тестирования - PullRequest
0 голосов
/ 11 апреля 2020

У меня есть работающее приложение flask, и я добавляю тестирование с использованием библиотеки pytest .

99% функциональности приложения требуют, чтобы пользователи входили в систему, и я использую flask -security для управления этим.

Приложение работает хорошо, однако я изо всех сил пытаюсь добавить тестирование - в частности, чтобы войти в систему тестового пользователя, а затем тестировать представления, украшенные декоратором login_required, из базового пакета flask -login. Я прочитал много уроков и вопросов, связанных со стековым потоком, но не смог «исправить» это ...

Я понимаю, как работать в контексте приложения, но считаю, что conftest.py настроен правильно для этого.

Код ниже. Кто-нибудь может подсказать, что я могу делать не так? Заранее большое спасибо.

application.py

def create_app(config_class=DevConfig):
    app = Flask(__name__)
    app.config.from_object(config_class)

    db.init_app(app)
    ##  add extensions

    from user.models import User, Role
    from user.forms import ExtendedRegisterForm, ExtendedConfirmRegisterForm
    user_datastore = SQLAlchemyUserDatastore(db, User, Role)
    security.init_app(app, user_datastore, register_form=ExtendedRegisterForm,
        confirm_register_form=ExtendedConfirmRegisterForm)

    ## register blueprints

    return app

tests / conftest.py

import pytest
import os

from application import create_app, security
from application import db as _db

from config import TestConfig
from user.models import User, Role
from .utils import valid_user, create_roles_users


@pytest.fixture(scope='module')
def test_client():
    app = create_app(config_class=TestConfig)

    testing_client = app.test_client()

    # application context
    ctx = app.app_context()
    ctx.push()

    yield testing_client

    ctx.pop()


@pytest.fixture(scope='module')
def init_db():
    _db.create_all()

    create_roles_users(security, _db)

    yield _db

    _db.drop_all()

tests / utils.py

valid_user = {
    "first_name": "Test", 
    "last_name": "User",
    "email": "test_user@test.com", 
    "password": "test_pwd"
    }

def login(client, username=valid_user['email'], password=valid_user['password']):
    return client.post('/user/login', data=dict(
        email=username,
        password=password
    ), follow_redirects=True)


def logout(client):
    return client.get('/user/logout', follow_redirects=True)


def create_roles_users(security, db):
    # create roles
    roles = ['submitter', 'approver', 'admin', 'db-admin', 'leave-tracker']
    for role in roles:
        security.datastore.find_or_create_role(name=role)

    # create and activate users
    users = []
    users.append(valid_user)
    created_users = []

    for user_args in users:
        created_user = security.datastore.create_user(**user_args)
        security.datastore.activate_user(created_user)

        created_users.append(created_user)

    # assign submitter role to users
    for user in created_users:
        for role in roles:
            r = security.datastore.find_or_create_role(role)
            security.datastore.add_role_to_user(user, r)

    db.session.commit()

тестовое представление после входа в систему

from tests.utils import login, logout, valid_user


def test_homepage_not_loggedin(test_client):
    """
    GIVEN no authenticated user
    WHEN the '/' page is requested (GET)
    THEN check the user is forwarded to log in
    """
    rv = test_client.get('/')
    assert rv.status_code == 302

    rv = test_client.get('/', follow_redirects=True)
    assert b'Please log in' in rv.data


def test_homepage_loggedin(test_client, init_db):
    """
    GIVEN logged in user
    WHEN the '/timesheets' page is requested (GET)
    THEN check the user is not requested to log in
    """

    with test_client:

        rv = login(test_client)
        assert rv.status_code == 200

        rv = test_client.get('/timesheets', follow_redirects=True)
        assert b'Please log in' not in rv.data

После запуска pytest я получаю 'pass' в первом тесте (not_loggedin) и 'fail' во втором тесте (loggedin) - возвращенный текст показывает что пользователь все еще перенаправлен на страницу / user / login.

В конфигурации я переключил LOGIN_DISABLED = False на LOGIN_DISABLED = True, и он обходит ошибку, однако это приводит к AttributeError: 'AnonymousUser' object has no attribute 'id' , поскольку пользователь не авторизован и, следовательно, анонимен.

1 Ответ

0 голосов
/ 21 апреля 2020

Подсказка от jwag привела к ответу, для любого, кто найдет этот вопрос. Установив для WTF_CSRF_ENABLED значение False в конфигурации, это позволяет успешный вход в систему. Слава JWAG.

...