Skip to content

feat: fixed fixtures in backend/e2e - #237

Merged
HardMax71 merged 3 commits into
mainfrom
fix/test-fixtures
Feb 27, 2026
Merged

HardMax71 merged 3 commits into
mainfrom
fix/test-fixtures

Conversation

@HardMax71

@HardMax71 HardMax71 commented Feb 27, 2026

Copy link
Copy Markdown
Owner

Summary by cubic

Refactored e2e tests to replace fixtures with async helpers for creating executions, sagas, and notifications, making setup deterministic and faster. Added a simple exec_request fixture and tightened readiness waits to reduce flakiness.

  • Refactors

    • Replaced created_execution*, execution_with_saga, and execution_with_notification with create_execution, create_execution_with_saga, and create_execution_with_notification helpers that return parsed models.
    • Introduced exec_request fixture for a default Python print script; tests pass it to helpers.
    • Tests import and use helpers directly; helpers encapsulate POD_CREATED and notification waits, and create_execution_with_notification supports a timeout.
  • Bug Fixes

    • Prevented hangs by adding a timeout to notification readiness.
    • Strengthened SSE access tests by asserting 403 error payload details.

Written for commit f0f63d0. Summary will update on new commits.

Summary by CodeRabbit

  • Tests
    • Refactored end-to-end tests to use explicit async helpers for creating executions, saga states, and notifications instead of prior implicit fixtures.
    • Tests now integrate with Redis for real-time event waits and dynamically create executions during runs.
    • Updated test flows and assertions for saga status, notifications, server-sent events, and access-control checks to improve reliability and clarity.

Copilot AI review requested due to automatic review settings February 27, 2026 07:31
@coderabbitai

coderabbitai Bot commented Feb 27, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5d23248 and f0f63d0.

📒 Files selected for processing (5)
  • backend/tests/e2e/conftest.py
  • backend/tests/e2e/test_execution_routes.py
  • backend/tests/e2e/test_notifications_routes.py
  • backend/tests/e2e/test_saga_routes.py
  • backend/tests/e2e/test_sse_routes.py

📝 Walkthrough

Walkthrough

Replaces pytest-asyncio fixtures in E2E tests with imperative async helper functions in backend/tests/e2e/conftest.py (create_execution, create_execution_with_saga, create_execution_with_notification); tests updated to call these helpers and to use Redis + API calls for event synchronization and saga/notification retrieval.

Changes

Cohort / File(s) Summary
Test helpers / Conftest
backend/tests/e2e/conftest.py
Removed pytest-asyncio fixtures and added async helper functions create_execution, create_execution_with_saga, create_execution_with_notification, a shared _DEFAULT_REQUEST, and renamed fixture simple_execution_requestexec_request. Helpers accept AsyncClient and redis.Redis, POST to /api/v1/execute, wait for POD_CREATED/notification via Redis, and return typed responses.
Saga tests
backend/tests/e2e/test_saga_routes.py
Replaced execution_with_saga fixture with await create_execution_with_saga(test_user, redis_client, exec_request); tests now accept redis_client: redis.Redis and exec_request: ExecutionRequest; removed direct SagaDocument/wait_for_pod_created usage and reference saga via saga.saga_id.
Notification tests
backend/tests/e2e/test_notifications_routes.py
Replaced execution_with_notification fixture with calls to await create_execution_with_notification(test_user, redis_client, exec_request, timeout=...); tests accept redis_client: redis.Redis and exec_request: ExecutionRequest; assertions updated to use the returned notification instance.
SSE tests
backend/tests/e2e/test_sse_routes.py
Removed reliance on created_execution fixture; tests now call create_execution(test_user, exec_request) at runtime and use returned execution_id for SSE endpoints; added explicit 403 detail assertions for cross-user access.
Execution tests minor rename
backend/tests/e2e/test_execution_routes.py
Renamed test parameter simple_execution_requestexec_request and updated its usage in the test.
Imports / Cleanup across E2E tests
backend/tests/e2e/...
Updated imports to reference new helpers (create_execution*, wait_for_result), added redis.asyncio typing where used, and removed imports/fixtures related to the removed pytest fixtures and wait_for_pod_created.

Sequence Diagram(s)

sequenceDiagram
  participant Test as Test (helper)
  participant Client as AsyncClient (API)
  participant Redis as Redis
  participant SagaAPI as Saga service / API

  Test->>Client: POST /api/v1/execute (create_execution)
  Client-->>Test: ExecutionResponse (execution_id)
  Test->>Redis: subscribe/wait for POD_CREATED or notification (by execution_id)
  Redis-->>Test: event (POD_CREATED / notification)
  Test->>SagaAPI: GET /api/v1/sagas/{execution_id} (create_execution_with_saga)
  SagaAPI-->>Test: SagaStatusResponse
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Poem

🐰 I hopped through tests with a tiny jig,
Helpers in paw, no fixtures to rig,
Redis bells chimed, sagas woke bright,
Executions spawned into the night,
CI hums softly — hop, hop, delight! 🎉

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: fixed fixtures in backend/e2e' accurately describes the main change: refactoring pytest-asyncio fixtures into explicit async helper functions in the backend e2e tests.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/test-fixtures

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates backend end-to-end tests to stop relying on async fixture chaining for “created execution / execution with saga / execution with notification”, replacing them with explicit async helper functions to make test setup more deterministic and easier to control.

Changes:

  • Replace created_execution, execution_with_saga, and execution_with_notification fixtures with create_execution* async helper functions in tests/e2e/conftest.py.
  • Update SSE, saga, and notification E2E tests to call the new helpers directly and pass required clients/Redis.
  • Simplify and remove now-unused imports/types in the updated tests.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
backend/tests/e2e/test_sse_routes.py Switch execution stream tests to create executions via create_execution() instead of created_execution fixture.
backend/tests/e2e/test_saga_routes.py Replace execution_with_saga fixture usage with create_execution_with_saga() helper across saga route tests.
backend/tests/e2e/test_notifications_routes.py Replace execution_with_notification fixture usage with create_execution_with_notification() helper and clean up imports.
backend/tests/e2e/conftest.py Remove async fixtures and introduce create_execution* helper functions for explicit, reusable test setup.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread backend/tests/e2e/conftest.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
backend/tests/e2e/test_notifications_routes.py (1)

360-397: ⚠️ Potential issue | 🟡 Minor

Strengthen 404 isolation checks with response body assertions.

Lines 374 and 396 assert only status code. Please also validate the error payload to verify the API contract for unauthorized resource access.

Based on learnings: "Applies to backend/tests/**/*.py : Backend tests must test API responses precisely including status code and response body contents; use pytest.mark.parametrize over duplicate test bodies; mock at service boundaries using unittest.mock.AsyncMock".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/tests/e2e/test_notifications_routes.py` around lines 360 - 397,
Update the two tests (test_cannot_mark_other_users_notification_read and
test_cannot_delete_other_users_notification) to also assert the JSON error
payload from the 404 responses so the API contract for unauthorized resource
access is validated (e.g., assert response.json() matches the expected error
shape/message). Refactor the duplicate logic by parameterizing the HTTP method
and endpoint assertion (use pytest.mark.parametrize over method/route pairs) and
reuse create_execution_with_notification, test_user and another_user fixtures;
ensure the owner-success path still asserts the 204 for the PUT case.
backend/tests/e2e/test_saga_routes.py (1)

47-58: ⚠️ Potential issue | 🟡 Minor

Validate 403 payloads in access-control tests.

Line 58 and Line 246 assert only status code. Add response body checks to enforce the exact error contract for forbidden access.

Based on learnings: "Applies to backend/tests/**/*.py : Backend tests must test API responses precisely including status code and response body contents; use pytest.mark.parametrize over duplicate test bodies; mock at service boundaries using unittest.mock.AsyncMock".

Also applies to: 232-247

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/tests/e2e/test_saga_routes.py` around lines 47 - 58, The test
test_get_saga_access_denied currently only asserts response.status_code == 403;
update it to also assert the exact JSON error body contract (e.g.,
response.json() == {"detail": "Forbidden", "code": "forbidden"} or whatever your
API uses) so the forbidden response payload is verified after calling
create_execution_with_saga and another_user.get; apply the same change to the
other access-control test that currently only checks status (the duplicate test
around lines 232-247) and consolidate duplicate assertions using
pytest.mark.parametrize to avoid copy/paste.
🧹 Nitpick comments (2)
backend/tests/e2e/conftest.py (2)

157-171: create_execution takes redis_client but never uses it.

This parameter currently adds coupling without behavior. Consider removing it from create_execution and keeping Redis only in helpers that actually wait on Redis events.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/tests/e2e/conftest.py` around lines 157 - 171, The create_execution
helper currently accepts an unused redis_client parameter; remove the unused
parameter from the function signature (create_execution) and from every
test/caller that passes it, leaving the function to accept only client, request,
script, lang, lang_version and return ExecutionResponse; keep Redis usage
confined to helpers that explicitly wait for Redis events (do not reintroduce
redis_client into create_execution), and update any type hints or imports
referencing redis_client accordingly (e.g., callers that relied on redis_client
should instead call the Redis-wait helper where needed).

166-167: Use Google-style docstrings for the new helper functions.

The added helper docstrings don’t include Args/Returns (and Raises where relevant), which is required by the repo guidelines.

As per coding guidelines: "Use Google-style docstrings with Args/Returns/Raises sections for all functions and classes".

Also applies to: 183-187, 212-217

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/tests/e2e/conftest.py` around lines 166 - 167, Update the new helper
function docstrings in backend/tests/e2e/conftest.py (the helper that "POST
/execute and return response (does NOT wait for completion)" and the two other
helpers referenced at the other ranges) to use Google-style format: add an Args
section documenting parameters, a Returns section describing the return value,
and a Raises section where appropriate; ensure each section is concise and
matches the function signature and behavior so tests and linters accept the
docstrings.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@backend/tests/e2e/test_sse_routes.py`:
- Around line 167-181: Update the test_execution_stream_other_users_execution
test to assert the error response body in addition to status code: after calling
sse_client_another.get(f"/api/v1/events/executions/{execution.execution_id}"),
parse the response body (e.g., response.json()) and assert it matches the
expected error payload shape/content (status/message/code or whatever API error
schema your handlers return). Reference the test function name
test_execution_stream_other_users_execution and the sse_client_another.get call
to locate where to add assertions and ensure the error fields are explicitly
checked rather than only response.status_code.

---

Outside diff comments:
In `@backend/tests/e2e/test_notifications_routes.py`:
- Around line 360-397: Update the two tests
(test_cannot_mark_other_users_notification_read and
test_cannot_delete_other_users_notification) to also assert the JSON error
payload from the 404 responses so the API contract for unauthorized resource
access is validated (e.g., assert response.json() matches the expected error
shape/message). Refactor the duplicate logic by parameterizing the HTTP method
and endpoint assertion (use pytest.mark.parametrize over method/route pairs) and
reuse create_execution_with_notification, test_user and another_user fixtures;
ensure the owner-success path still asserts the 204 for the PUT case.

In `@backend/tests/e2e/test_saga_routes.py`:
- Around line 47-58: The test test_get_saga_access_denied currently only asserts
response.status_code == 403; update it to also assert the exact JSON error body
contract (e.g., response.json() == {"detail": "Forbidden", "code": "forbidden"}
or whatever your API uses) so the forbidden response payload is verified after
calling create_execution_with_saga and another_user.get; apply the same change
to the other access-control test that currently only checks status (the
duplicate test around lines 232-247) and consolidate duplicate assertions using
pytest.mark.parametrize to avoid copy/paste.

---

Nitpick comments:
In `@backend/tests/e2e/conftest.py`:
- Around line 157-171: The create_execution helper currently accepts an unused
redis_client parameter; remove the unused parameter from the function signature
(create_execution) and from every test/caller that passes it, leaving the
function to accept only client, request, script, lang, lang_version and return
ExecutionResponse; keep Redis usage confined to helpers that explicitly wait for
Redis events (do not reintroduce redis_client into create_execution), and update
any type hints or imports referencing redis_client accordingly (e.g., callers
that relied on redis_client should instead call the Redis-wait helper where
needed).
- Around line 166-167: Update the new helper function docstrings in
backend/tests/e2e/conftest.py (the helper that "POST /execute and return
response (does NOT wait for completion)" and the two other helpers referenced at
the other ranges) to use Google-style format: add an Args section documenting
parameters, a Returns section describing the return value, and a Raises section
where appropriate; ensure each section is concise and matches the function
signature and behavior so tests and linters accept the docstrings.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cb3f2e3 and 16d5852.

📒 Files selected for processing (4)
  • backend/tests/e2e/conftest.py
  • backend/tests/e2e/test_notifications_routes.py
  • backend/tests/e2e/test_saga_routes.py
  • backend/tests/e2e/test_sse_routes.py

Comment thread backend/tests/e2e/test_sse_routes.py

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 4 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="backend/tests/e2e/conftest.py">

<violation number="1" location="backend/tests/e2e/conftest.py:159">
P3: `create_execution` has an unused `redis_client` parameter, which adds dead API surface and unnecessary coupling in test helpers.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread backend/tests/e2e/conftest.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
backend/tests/e2e/conftest.py (1)

164-204: Upgrade helper docstrings to Google style sections.

The new helper docstrings are clear, but they don’t include explicit Args/Returns/Raises sections.

As per coding guidelines, "Use Google-style docstrings with Args/Returns/Raises sections for all functions and classes".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/tests/e2e/conftest.py` around lines 164 - 204, Update the
triple-quoted docstrings for create_execution_with_saga,
create_execution_with_notification (and the helper create_execution if
applicable) to Google-style format: add an "Args:" section listing parameters
(client: AsyncClient, redis_client: redis.Redis, request: ExecutionRequest, and
optional timeout: float) with types and brief descriptions, a "Returns:" section
describing the returned tuple types (e.g., tuple[ExecutionResponse,
SagaStatusResponse] or tuple[ExecutionResponse, NotificationResponse]), and a
"Raises:" section enumerating possible exceptions (e.g., AssertionError when
saga/notification not found, timeout-related errors). Keep the existing brief
summary lines, then append these Args/Returns/Raises sections in each function
docstring.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@backend/tests/e2e/conftest.py`:
- Around line 209-216: The test currently returns result.notifications[0] which
can be a stale item; update the helper to select the notification that
corresponds to the newly created execution instead of the first item. After
fetching NotificationListResponse.model_validate(resp.json()), filter
result.notifications for the one that matches the created execution (e.g.,
compare notification.execution_id or notification.resource_id/subject_id to
execution.id), and if that field is not available, fall back to choosing the
most-recent notification by sorting result.notifications by created_at (or
equivalent timestamp) and returning the latest; keep the helper functions
create_execution, wait_for_notification and variables
execution/result.notifications unchanged otherwise.
- Around line 162-163: The three test helpers create_execution,
create_execution_with_saga, and create_execution_with_notification currently use
the shared mutable _DEFAULT_REQUEST as a default argument; change each signature
to accept request: ExecutionRequest | None = None and at the start of each
function add request = request or _DEFAULT_REQUEST so a fresh reference is used
per call, avoiding state leakage from mutating the shared _DEFAULT_REQUEST.

---

Nitpick comments:
In `@backend/tests/e2e/conftest.py`:
- Around line 164-204: Update the triple-quoted docstrings for
create_execution_with_saga, create_execution_with_notification (and the helper
create_execution if applicable) to Google-style format: add an "Args:" section
listing parameters (client: AsyncClient, redis_client: redis.Redis, request:
ExecutionRequest, and optional timeout: float) with types and brief
descriptions, a "Returns:" section describing the returned tuple types (e.g.,
tuple[ExecutionResponse, SagaStatusResponse] or tuple[ExecutionResponse,
NotificationResponse]), and a "Raises:" section enumerating possible exceptions
(e.g., AssertionError when saga/notification not found, timeout-related errors).
Keep the existing brief summary lines, then append these Args/Returns/Raises
sections in each function docstring.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 16d5852 and 5d23248.

📒 Files selected for processing (2)
  • backend/tests/e2e/conftest.py
  • backend/tests/e2e/test_sse_routes.py

Comment thread backend/tests/e2e/conftest.py Outdated
Comment thread backend/tests/e2e/conftest.py
@sonarqubecloud

Copy link
Copy Markdown

@HardMax71
HardMax71 merged commit d9f86f9 into main Feb 27, 2026
16 checks passed
@HardMax71
HardMax71 deleted the fix/test-fixtures branch February 27, 2026 08:41
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.

2 participants