question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Sessions are empty when testing

See original GitHub issue

This doc expresses that we can access session without any extra context manager.

However the following code does not return any session key (session is empty):

from flask import Flask


import pytest
from flask import session


myapp = Flask('testing')
myapp.secret_key = 'secret'
myapp.debug = True

@myapp.route('/')
def home():
    return session['message']


@pytest.fixture
def app():
    return myapp


def test_home(client):
    session['message'] = 'something'
    response = client.get('/')
    assert response.data == 'something'

Any hint on what we’re missing here?

Thanks 😃

Issue Analytics

  • State:open
  • Created 6 years ago
  • Reactions:8
  • Comments:7 (1 by maintainers)

github_iconTop GitHub Comments

7reactions
russmaccommented, Jan 20, 2019

Was also having this issue until I moved my yield client outside of the with client.session_transaction() as session: enumeration. You can debug by printing the session object, Which shows the secure cookie contents.

Wont work:

def client():
    with app.test_client() as client:
        with client.session_transaction() as session:
            session['Authorization'] = 'redacted'
            print(session) # will be empty SecureCookieSession
            yield client

Works:

def client():
    with app.test_client() as client:
        with client.session_transaction() as session:
            session['Authorization'] = 'redacted'
        print(session) # will be populated SecureCookieSession
        yield client
3reactions
northernSagecommented, Mar 31, 2021

Thanks @vinyll for taking the time to open the issue and all others for providing examples and a working solution. I feel like the issue could use a bit more info on why the described problem is happening.

While pytest-flask pushes a test request context for you at the beginning of the test session as stated in the docs

During test execution a request context will be automatically pushed for you, so context-bound methods can be conveniently called (e.g. url_for, session).

pytest-flask does not prevent flask from creating and pushing new request context objects onto the request context stack upon request handling. What this means and its consequences can be seen with help of the code snippet bellow:

def _context_info(scope, session):
    """shows current session and request context
       objects ids for debugging purposes"""
    print(scope, id(session._get_current_object()),
        " - session[message]: ",
        session.get("message", "not-found"),
        " - _request_ctx_stack top: ", 
        id(_request_ctx_stack.top))

def test_client_session(client, live_server):
    # adds a simple view that writes to session object
    @live_server.app.route('/home')
    def home():
        session["message"] = "BACON"
        _context_info("session id inside view: ", session)
        return "session updated"

    session["message"] = "EGGS"

    # checks context state before and after request
    _context_info("session id before request: ", session)
    response = client.get(url_for("home"))
    _context_info("session id after request: ", session)

    # pops top request object off stack
    print("poping top request context from stack...")
    _request_ctx_stack.pop()

    # check what is on top of stack
    _context_info("session id after popping request: ", session)

    assert False

Output:

...
----------------------------- Captured stdout call -----------------------------
session id before request:         139747393971024  - session[message]:   EGGS  - _request_ctx_stack top:  139747394620304
session id inside view:            139747393972272  - session[message]:  BACON  - _request_ctx_stack top:  139747394052432
session id after request:          139747393972272  - session[message]:  BACON  - _request_ctx_stack top:  139747394052432
popping top request context from stack...
session id after popping request:  139747393971024  - session[message]:   EGGS  - _request_ctx_stack top:  139747394620304

From this we can see that flask is pushing a new request context into the stack, shadowing the session object of the test request context pushed by pytest-flask and this seems to be the reason for the problem. The solution provided by @russmac is the official flask way of getting around this problem. A secondary possible solution would be using a view function (similar to my example above) to write to the session object and then access it using session["yourkey"] within your test since the session object will still be reachable:

def test_session(client, live_server):
    
    # temporary view just to alter session
    @live_server.app.route('/setsession')
    def set_session():
        session["message"] = "EGGS"
        return session["message"]
    
    response = client.get(url_for("set_session"))

    assert response.status == "200 OK"
    assert session["message"] == "EGGS"
Read more comments on GitHub >

github_iconTop Results From Across the Web

How do check if a PHP session is empty? - Stack Overflow
If you want to check whether sessions are available, you probably want to use the session_id() function: session_id() returns the session id ...
Read more >
Sessions seem to always be empty and regenerated - Laracasts
Sessions seem to always be empty and regenerated. I've been playing with cookies on a laravel test app that I keep coming back...
Read more >
why in Unit testing current session is empty? - Mendix Forum
One way to test microflows that have dependancies such as the current user is to instead pass it as a parameter to a...
Read more >
How do check if a PHP session is empty | Edureka Community
Make sure you're calling session_start before reading from or writing to the session array. Hope it helps!! answered Nov 9, 2020 by ...
Read more >
Python: pytest accessing Flask session and request context ...
Sessions are empty when testing #69 raises this problem, and user russmac suggests a solution: @pytest.fixture(scope='module') ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Hashnode Post

No results found