Запустите Selenium Tests в приложении Flask с зарегистрированным пользователем

Я создаю веб-приложение на основе Flask, где все интересные страницы находятся за логином. Я хотел бы запустить автоматические тесты против него с помощью Selenium WebDriver. Я не могу понять, как войти в систему пользователя и связать его с Selenium. Все, что я пробую, приводит к тому, что Selenium представлен на странице "Пожалуйста, войдите".

Недопустимое решение 1: Сценарий входа в систему Selenium

Многие из ресурсов, которые я видел ( 1, 2, 3, среди многих других), предлагают вручную войти в систему с помощью скриптового теста, то есть навигации Selenium к странице входа в систему, заполнения форм и нажатия кнопок. Это ужасное решение по многим причинам, включая, но не ограничиваясь:

  • Требуется жесткое кодирование учетных данных в виде открытого текста (мое приложение использует вход в социальные сети, поэтому нет доступных тестовых или готовых учетных данных)
  • Вводит зависимость; подпрограмма входа в систему должна теперь выполняться в тесте или в приборе, и никакие другие тесты не могут выполняться отдельно от нее
  • Медленный; должен быть запущен перед каждым тестом как действие браузера

Неприемлемое решение 2. Требуется ручной вход перед запуском тестов Selenium

Что-то еще, что я мог сделать, это открыть браузер, на который я нацеливался, прежде чем запускать тесты Selenium, и войти в систему. Это держит учетные данные в руках Selenium. Проблемы:

  • PITA; Много раз я забуду это сделать, и мне придется заново запускать тесты. Из-за таких хлопот у меня может возникнуть желание меньше запускать набор тестов.
  • Не масштабируется; если я когда-либо пытался протестировать несколько браузеров или в другой среде, это прямо в окне, как вариант
  • Медленный; по-прежнему требуется, чтобы Selenium щелкнул страницу входа и нажал "Авторизовать приложение" на стороннем сайте.

Неудачная попытка решения 1: Подделка сессии

Используя что-то вроде этого:

with client.session_transaction() as session:
    session['user_id'] = test_user.id
    session['_fresh'] = True

где клиент является экземпляром app.test_client(), (Это в приспособлении pytest; я использую Flask_login). Это позволяет мне входить в систему во время регулярных юнит-тестов, но я не смог выяснить, как заставить Selenium использовать этот же сеанс.

Неудачная попытка решения 2: login_user

Как и выше, я могу попробовать позвонить Flask_login.login_user(test_user) в приспособлении, но мне не удалось связать Selenium с этим пользователем. Поскольку сессия уже не удалась, единственное, что я мог подумать, это установить cookie для этого авторизованного пользователя в Selenium. driver.set_cookie, но я понятия не имею, как получить для этого подходящий тестовый клиент или Flask.

Неудачное решение № 3: LOGIN_DISABLED

В соответствии с документами Flask-Login вы можете установить LOGIN_DISABLED в конфигурации вашего приложения, чтобы обойти login_required декоратор. Я сделал это, но я все еще вижу страницу входа.

Я углубился в это немного больше, и проблема не в том, что LOGIN_DISABLED не работает, а в том, что многие представления зависят от поведения Flask_login. current_user.is_anonymous, Если бы я собирался пойти по этому пути, мне также нужно решение, чтобы убедиться, что current_user устанавливается для тестового пользователя, чтобы действия в приложении были правильно сгруппированы с пользователем, вошедшим в систему.

Как выполнить аутентификацию один раз без использования Selenium, а затем заставить Selenium использовать этого аутентифицированного пользователя до конца сеанса?

4 ответа

Решение

Как получить куки после входа в систему. Можно смоделировать процесс входа в систему, найти форму action атрибут из него и имена полей для имени пользователя и пароля. Посмотрите, что cookie используется для хранения ключа сеанса, предположим, что это sid,

get_cookie.py:

import requests
r = requests.post(action, 
                  data={'login': 'your_username', 'password': 'You_p@ssw0rd'}, 
                  allow_redirects=False)
# now r.cookies contains all returned cookies,
# print cookie you need:
print(r.cookie['sid'])

Попробуйте сделать это при инициализации сеанса вебдрайвера. Или вы можете запустить его и передать этот файл cookie в Selenium, например, в качестве параметра командной строки (просто используйте правильные параметры):

selenium .... --session=$(./get_cookie.py)

Cam, пожалуйста, прочитайте следующую ссылку?

Войти используя селен

При этом вход в систему осуществляется с использованием селена, а файл cookie сохраняется в файле для последующего использования. И после этого вы можете использовать запросы с сохраненным куки для доступа к другим страницам.

Вы можете создать AuthenticatedUser и сделать его current_user до испытаний.

В моем случае я использую безопасность флеш-памяти с ролями, поэтому я также создаю и внедряю определенную роль и ловушки вызовов, чтобы она интегрировалась с принципалом фляги и переопределяла пользовательский поиск, который происходит в безопасности фляги.

Поскольку вы, по-видимому, не используете эти дополнительные библиотеки, я постараюсь перенастроить их на ваш случай. Когда вы хотите отключить вход в систему, вы бы назвали то, что я назвал force_authenticated(app) до того, как ваш первый запрос происходит. (Это будет ошибка, если вызвано после того, как запросы уже произошли.)

# This is a non-anonymous, authenticated user
class AuthenticatedUser(flask_login.UserMixin):
    def get_id(self):
        return 'TestUser'

def force_authenticated(app):
    @app.before_request
    def set_identity():
        user = AuthenticatedUser()
        flask_login.login_user(user)

Вот полный, действительно минимальный, подтвержденный работающий пример:

from flask import Flask
import flask_login

class AuthenticatedUser(flask_login.UserMixin):
    def get_id(self):
        return 'TestUser'

def force_authenticated(app):
    @app.before_request
    def set_identity():
        user = AuthenticatedUser()
        flask_login.login_user(user)

app = Flask(__name__)
app.secret_key = 'blahblah'

lm = flask_login.LoginManager(app)
lm.init_app(app)

force_authenticated(app)

@app.route('/')
@flask_login.login_required
def hello_world():
    return 'Hello, World!'

app.run()

У нас есть форма, такая же, как вы используете колбу. Мы создали файл конфигурации по умолчанию в проекте GIT. Затем я перенес это в свою коробку и создал свой собственный файл конфигурации из этого значения по умолчанию и поместил свои учетные данные в этот файл. Кажется, у нас это хорошо работает. Я запускаю все свои тесты из Eclipse, используя pydev. Я недавно начал использовать HTMLTestRunner чтобы получить лучшую картину результатов. Я надеюсь, что это помогает вам.

Другие вопросы по тегам