Skip to content

test: add ratcheting API call-count tests for hot commands (#802) - #804

Draft
padak wants to merge 1 commit into
mainfrom
claude/issue-802-api-call-count-tests
Draft

padak wants to merge 1 commit into
mainfrom
claude/issue-802-api-call-count-tests

Conversation

@padak

@padak padak commented Sep 27, 2026

Copy link
Copy Markdown
Member

What / why

Adds ratcheting API call-count tests for the hot read commands so an N+1 regression (a per-item lookup sneaking into a list loop) or a duplicate call fails CI instead of reaching users as a slow command and rate-limit pressure.

  • tests/helpers.py: mock_api_routes (route table keyed by (METHOD, path), host/query-agnostic, reusable + optional so zero-call commands do not trip pytest-httpx teardown; unmatched requests get a non-retryable 418 so they fail fast without backoff sleeps), recorded_api_calls, and assert_api_calls (exact count + sequence, optional query string, ordered=False sorted-multiset mode for thread-pool fan-out).
  • tests/test_api_call_counts.py: every command runs end-to-end (CliRunner -> command -> service -> real HTTP client -> pytest-httpx). Expected call lists are committed literals; the module docstring states that raising one is a deliberate, reviewed change and that improvements should lower it.
  • CONTRIBUTING.md: checklist item asking new/changed hot-path commands to add or update a call-count case.

Commands covered and pinned counts

Command Calls Size check
project list 0 --
project status --project X 1 (GET /v2/storage/tokens/verify) --
project status (2 projects) 2 (one verify per project) --
config list 3 (components?include=configuration, dev-branches, branch/{default}/search/component-configurations) 1 vs 10 configs: constant
config detail 1 1 vs 10 rows: constant
job list --project X 1 (/search/jobs?limit=50&offset=0&sortBy=startTime&sortOrder=desc, query pinned) 1 vs 10 jobs: constant
job list (2 projects) 2 (one search per project, unordered) --
job detail (flow job) 1 --
storage tables 1 1 vs 10 tables: constant
storage table-detail 1 --
flow list 2 (keboola.flow/configs + legacy keboola.orchestrator/configs count probe) 1 vs 10 flows: constant
flow detail 1 1 vs 10 tasks: constant

All commands were practical end-to-end; no service-layer fallback was needed.

Follow-ups found

No N+1 or duplicate calls in the covered paths. One minor observation, not fixed here:

  • config list spends a GET /v2/storage/dev-branches per project on every run just to find the default branch id for the folder-metadata search (when no branch is active). Constant per project, not per item; could be cached or skipped if the folder lookup were made optional. Low priority.

How tested

  • uv run pytest tests/test_api_call_counts.py -- 18 passed
  • make check -- lint, format, ty, full suite: 6920 passed, 15 skipped

Fixes #802

Pin the exact (METHOD, path) HTTP calls of the hot read commands
(project list/status, config list/detail, job list single + fan-out,
job detail, storage tables/table-detail, flow list/detail) end-to-end
through CliRunner against pytest-httpx, with 1-vs-10-item cases proving
list call counts do not grow per item. Shared recording/assert helpers
live in tests/helpers.py; CONTRIBUTING.md asks hot-path command changes
to add or update a case.

This branch has not been deployed

No deployments
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.

test: ratcheting API call-count tests for hot commands (catch N+1 regressions)

1 participant