Skip to content

test: pin chat listing to a constant number of SQL statements - #46

Merged
lesnik512 merged 1 commit into
mainfrom
test/query-count-chat-listing
Oct 4, 2026
Merged

lesnik512 merged 1 commit into
mainfrom
test/query-count-chat-listing

Conversation

@lesnik512

Copy link
Copy Markdown
Member

Closes #22

What changed

  • tests/api/helpers.py: count_statements(session), a context manager that listens to SQLAlchemy's before_cursor_execute on the connection behind the db_session fixture's session and collects every statement sent while the block runs. Route handlers already run on that connection (the fixture overrides Database.database_engine with it), so a request's statements land there.
  • tests/api/test_chat_listing_api.py: test_listing_runs_the_same_number_of_statements_for_one_chat_as_for_many lists chats via GET /api/chats/ for alice (1 direct chat) and carol (5 direct chats), each chat with a last message, and asserts both requests send the same number of statements.
  • tests/api/test_statement_counter.py: checks that a statement on a second connection from a fresh engine is not counted, while one on the test connection is.

No changes in app/, and db_session itself is untouched.

Why

No test counted queries, so a regression of the last-message lookup to one query per chat (N+1) would have kept every test green as long as the data was right. Comparing the 1-chat count with the 5-chat count, rather than pinning an absolute number, keeps the test about scaling and leaves the listing query free to change shape.

The listener is registered on the connection object, not the engine class, so other connections (other engines, other tests) are never counted. The counter hooks in through a helper that takes the session, not through a change to db_session, to stay clear of the parallel fixture-teardown work in #19/#23.

How the regression check was done

I temporarily edited ChatsRepository.list_for_user to drop orm.selectinload(tables.ChatsTable.last_message) and load each chat's last message with one session.get(tables.MessagesTable, chat.last_message_id) per chat (set via orm.attributes.set_committed_value). Then I ran just test tests/api/test_chat_listing_api.py:

E       assert 8 == 4
1 failed, 9 passed

5 chats sent 8 statements (SAVEPOINT, listing SELECT, 5 per-chat message SELECTs, ROLLBACK TO SAVEPOINT) and 1 chat sent 4. I reverted the edit (git checkout app/). On the unmodified code both requests send 4 (SAVEPOINT, listing SELECT, one batched selectin SELECT, ROLLBACK TO SAVEPOINT) and the test passes.

Test results

  • just test: 112 passed, coverage 100.00%
  • just lint: ruff format/check and ty check all pass

@lesnik512
lesnik512 merged commit 1bf68ae into main Oct 4, 2026
4 checks passed
@lesnik512
lesnik512 deleted the test/query-count-chat-listing branch October 4, 2026 10:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

No query-count instrumentation

1 participant