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?