Running locally, Python 3.12, Streamlit 1.40.1
Hi, please forgive the big setup here, trying to map my problem exactly. I am writing a bunch of tests for my streamlit app, and so far it has worked well using standard pytest
and mocking out my Postgres queries with monkeypatch
. However, I’m now trying to recover data from an INSERT ... RETURNING ...;
query and having a lot of trouble getting the scoping on my mock correct.
Imagine I have an app setup as follows:
.
├── poetry.lock
├── pyproject.toml
└── streamlit
├── app.py
├── classes
│ ├── __init__.py
│ └── burg.py
└── tests
├── __init__.py
└── test_app.py
Where my main app is in app.py
, and I have a class doing the lifting in classes/burg.py
.
burg.py
import streamlit as st
from sqlalchemy.sql import text
class Burg:
pass
class Burger(Burg):
@staticmethod
def flip_burger() -> list[str]:
with st.session_state.conn.session as session:
new_antigens = session.execute(
text(
"INSERT INTO user_logs (update_time, antigens_id, users_id, "
"site_page, status_changed) VALUES ('2024-10-10 00:00:00', 1, 1, "
"'burgers', 'flipped') returning user_logs_id;"
)
)
session.commit()
new_ids = [str(new_id[0]) for new_id in new_antigens]
return new_ids
app.py
import streamlit as st
from classes.burg import Burger
st.session_state.conn = st.connection("postgres") # init psql connection
Burger.flip_burger()
test_app.py
import streamlit as st
import pandas as pd
from classes.burg import Burger
class Test_Burger:
def test_flip_burger(self, monkeypatch):
class session_state:
class conn:
class session:
def __enter__(self):
return self
def __exit__(self):
pass
@staticmethod
def execute(null):
return pd.DataFrame({"ids": [100]})
def mock_conn(*args, **kwargs):
return session_state()
monkeypatch.setattr(st, "session_state", mock_conn)
borger = Burger()
assert borger.flip_burger() == [100]
The gist is I am inserting into my logs table and this function returns the ids of the rows that have been inserted.
I would like to use the monkeypatched method above to mock st.session_state.conn.session
and .execute()
so I can returned a couple fake ids and test my function.
I’ve tried a few different iterations of the session_state
mock class (from How to monkeypatch/mock modules and environments - pytest documentation), but the closest I can get is:
FAILED tests/test_app.py::Test_Burger::test_flip_burger - AttributeError: 'function' object has no attribute 'conn'
I have a feeling I’m just not scoping or designing my session_state
replacement correctly. What would be the right way to mock this out with monkeypatch?