Two-Bit Alchemist Two-Bit Alchemist - 4 years ago 278
Python Question

Run Selenium Tests on Flask App with Logged In User

I am building a Flask-backed web app where all the interesting pages are behind a login. I would like to run automated tests against it using the Selenium WebDriver. I cannot seem to figure out how to log in a user and associate it with Selenium. Everything I try results in Selenium being presented with the "Please log in" page.

Unacceptable Solution 1: Scripted Selenium Log In



Many of the resources I have seen (1, 2, 3, among many others) suggest manually logging in with a scripted test, which is to say navigating Selenium to the log in page, filling out forms, and clicking buttons. This is a terrible solution for many reasons including but not limited to:


  • Requires hardcoding credentials in plaintext somewhere (my app uses social media log in so there are no test or made-up credentials available)

  • Introduces a dependency; login routine must now be run in a test or fixture and no other tests can be run in isolation of it

  • Slow; must be run before every test as a browser action



Unacceptable Solution 2: Require Manual Log In Before Selenium Tests Run



Something else I could do is open the browser I'm targeting myself before running the Selenium tests and log in. This keeps the credentials out of Selenium's hands. Problems:


  • PITA; Many times I will forget to do this, causing me to have to rerun tests. Because it's such a hassle I may be motivated to run the test suite less.

  • Not scalable; if I ever tried testing multiple browsers or on a different environment this is right out the window as an option

  • Slow; still requires Selenium to click through login page and hit 'Authorize app' on a third-party site.



Failed Attempted Solution 1: Session Fakery



Using something like this:

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


where client is an instance of
app.test_client()
. (This is in a pytest fixture; I'm using Flask_login). This allows me to log in during regular unit tests, but I have not been able to figure out how I could get Selenium to use this same session.

Failed Attempted Solution 2: login_user



Similar to the above I can try calling
Flask_login.login_user(test_user)
in a fixture, but I have not successfully been able to associate Selenium with this user. Since the session already failed, the only thing I could think would be to set a cookie for this logged in user on Selenium
driver.set_cookie
, but I have no idea how to get a proper one out of the test client or Flask login to do so.

Failed Solution #3: LOGIN_DISABLED



According to the Flask-Login docs you can set
LOGIN_DISABLED
in your app config to bypass the
login_required
decorator. I did this but I'm still seeing a login page.


I dug into this a bit more and the issue is not that LOGIN_DISABLED isn't working but that a lot of views depend on the behavior of Flask_login's
current_user.is_anonymous
. If I were going to go this route I'd also need a solution to make sure that
current_user
is set to the test user, so that actions in the app are correctly grouped with the user that's "logged in".

How do I authenticate once without using Selenium and then get Selenium to use that authenticated user for the rest of its session?

Answer Source

How to get cookies after login. One can simulate login process, find you form take action attribute from it and names of fields for username and password. Look what cookie is used for storing session key, suppose it is 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'])

Try to do it in a webdriver session initialisation. Or you may run it and feed this cookie to Selenium, for example as a command line parameter (just use your correct parameters):

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

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download