Skip to content

Conversation

@robcsegal
Copy link
Contributor

@robcsegal robcsegal commented Jan 12, 2026

Added e2e tests for commerce credit memos
Data can't be seeded because it comes from Nav, but operations have data already there. Not ideal, but it's something.
https://softwareone.atlassian.net/browse/MPT-14923

Closes MPT-14923

  • Add end-to-end tests for commerce credit memos in billing
  • Add async credit memo test module (tests/e2e/billing/credit_memo/test_async_credit_memo.py) with tests for: get by ID, 404 not-found, list (fetch_page), and filter + iterate using RQLQuery
  • Add sync credit memo test module (tests/e2e/billing/credit_memo/test_sync_credit_memo.py) with tests for: get by ID, 404 not-found, list (fetch_page), and filter + iterate using RQLQuery
  • Add fixture invalid_credit_memo_id in tests/e2e/billing/credit_memo/conftest.py returning "CRD-0000-0000-0000-0000"
  • Add fixtures credit_memos and credit_memo to fetch sample data for tests
  • Mark credit memo tests as flaky; tests rely on existing data present in the system (no seed data)

@robcsegal robcsegal requested a review from a team as a code owner January 12, 2026 15:03
@coderabbitai
Copy link

coderabbitai bot commented Jan 12, 2026

📝 Walkthrough

Walkthrough

Adds end-to-end test coverage for credit memo operations: a new invalid ID fixture and separate async and sync test modules that verify fetching by ID (including 404), listing, and filtering credit memos.

Changes

Cohort / File(s) Summary
Test configuration
tests/e2e/billing/credit_memo/conftest.py
Adds invalid_credit_memo_id pytest fixture returning "CRD-0000-0000-0000-0000" for not-found tests.
Async credit memo tests
tests/e2e/billing/credit_memo/test_async_credit_memo.py
New async e2e tests: get by ID, assert 404 for invalid ID, fetch page (pagination), filter with RQLQuery and iterate results. Marked flaky.
Sync credit memo tests
tests/e2e/billing/credit_memo/test_sync_credit_memo.py
New sync e2e tests and fixtures (credit_memos, credit_memo): get by ID, assert 404 for invalid ID, list with limit, filter by id/status excluding vendor and assert single result. Marked flaky.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Jira Issue Key In Title ✅ Passed The PR title contains exactly one Jira issue key in the required MPT-XXXX format: MPT-14923.
Test Coverage Required ✅ Passed The PR includes only changes to test files within the tests/ folder (conftest.py, test_async_credit_memo.py, and test_sync_credit_memo.py). No non-test code files are modified.
Single Commit Required ✅ Passed The PR contains exactly one commit (644a970: 'Added e2e tests for commerce credit memos') which includes all changes to add end-to-end tests for commerce credit memos.

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


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

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (4)
tests/e2e/billing/credit_memo/test_async_credit_memo.py (2)

22-27: Consider skipping the test when no credit memos exist.

If credit_memo is None, the test proceeds with an empty string ID, which may cause an unexpected error rather than a meaningful test failure. Consider using pytest.skip to make the test behavior clearer when no data exists.

💡 Suggested improvement
 async def test_get_credit_memo_by_id(async_mpt_ops, credit_memo):
-    credit_memo_id = credit_memo.id if credit_memo else ""
+    if credit_memo is None:
+        pytest.skip("No credit memos available in the system")
+    credit_memo_id = credit_memo.id
 
     result = await async_mpt_ops.billing.credit_memos.get(credit_memo_id)
 
     assert result is not None

43-55: Same skip pattern could be applied here for consistency.

The filter test has the same None-handling pattern. Consider applying the pytest.skip approach here as well for consistency.

💡 Suggested improvement
 async def test_filter_credit_memos(async_mpt_ops, credit_memo):
-    credit_memo_id = credit_memo.id if credit_memo else ""
-    credit_memo_status = credit_memo.status if credit_memo else ""
+    if credit_memo is None:
+        pytest.skip("No credit memos available in the system")
+    credit_memo_id = credit_memo.id
+    credit_memo_status = credit_memo.status
     select_fields = ["-vendor"]
tests/e2e/billing/credit_memo/test_sync_credit_memo.py (2)

22-27: Same skip pattern suggestion applies here.

For consistency with async tests, consider using pytest.skip when credit_memo is None.

💡 Suggested improvement
 def test_get_credit_memo_by_id(mpt_ops, credit_memo):
-    credit_memo_id = credit_memo.id if credit_memo else ""
+    if credit_memo is None:
+        pytest.skip("No credit memos available in the system")
+    credit_memo_id = credit_memo.id
 
     result = mpt_ops.billing.credit_memos.get(credit_memo_id)
 
     assert result is not None

43-55: Same skip pattern could be applied here for consistency.

💡 Suggested improvement
 def test_filter_credit_memos(mpt_ops, credit_memo):
-    credit_memo_id = credit_memo.id if credit_memo else ""
-    credit_memo_status = credit_memo.status if credit_memo else ""
+    if credit_memo is None:
+        pytest.skip("No credit memos available in the system")
+    credit_memo_id = credit_memo.id
+    credit_memo_status = credit_memo.status
     select_fields = ["-vendor"]
📜 Review details

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9879263 and be0c9fc.

📒 Files selected for processing (3)
  • tests/e2e/billing/credit_memo/conftest.py
  • tests/e2e/billing/credit_memo/test_async_credit_memo.py
  • tests/e2e/billing/credit_memo/test_sync_credit_memo.py
🧰 Additional context used
📓 Path-based instructions (2)
**/*

⚙️ CodeRabbit configuration file

**/*: For each subsequent commit in this PR, explicitly verify if previous review comments have been resolved

Files:

  • tests/e2e/billing/credit_memo/test_async_credit_memo.py
  • tests/e2e/billing/credit_memo/conftest.py
  • tests/e2e/billing/credit_memo/test_sync_credit_memo.py
**/*.py

⚙️ CodeRabbit configuration file

**/*.py: Follow the linting rules defined in pyproject.toml under [tool.ruff] and [tool.flake8] sections.
For formatting, use Ruff instead of Black. Do not suggest Black formatting changes.

Files:

  • tests/e2e/billing/credit_memo/test_async_credit_memo.py
  • tests/e2e/billing/credit_memo/conftest.py
  • tests/e2e/billing/credit_memo/test_sync_credit_memo.py
🧠 Learnings (4)
📓 Common learnings
Learnt from: albertsola
Repo: softwareone-platform/mpt-api-python-client PR: 183
File: tests/e2e/catalog/price_lists/conftest.py:29-30
Timestamp: 2026-01-08T08:34:13.551Z
Learning: In the mpt-api-python-client E2E tests, the team intentionally reuses existing API resources (via e2e_config) for read-only operations and safe mutations (e.g., updating the "notes" field) to improve test execution speed. Only destructive/dangerous tests use isolated fixtures (created_price_list or async_created_price_list) that are created and cleaned up per test.
Learnt from: robcsegal
Repo: softwareone-platform/mpt-api-python-client PR: 186
File: tests/e2e/billing/ledger/charge/test_sync_ledger_charge.py:33-39
Timestamp: 2026-01-08T23:38:26.691Z
Learning: In the mpt-api-python-client e2e tests, hardcoded values like "INV12345" for invoice external IDs are intentional and guaranteed to exist because they come from import files used to seed the test data.
📚 Learning: 2026-01-08T08:34:05.465Z
Learnt from: albertsola
Repo: softwareone-platform/mpt-api-python-client PR: 183
File: tests/e2e/catalog/price_lists/conftest.py:29-30
Timestamp: 2026-01-08T08:34:05.465Z
Learning: In end-to-end tests (e.g., tests/e2e/...), reuse existing API resources for read-only operations and safe mutations to speed up test execution. Reserve isolated fixtures (e.g., created_price_list) for destructive tests that require per-test creation and cleanup. Ensure tests document when a fixture creates/destroys data and clearly indicate which operations are destructive, so tests stay fast and properly isolated.

Applied to files:

  • tests/e2e/billing/credit_memo/test_async_credit_memo.py
  • tests/e2e/billing/credit_memo/conftest.py
  • tests/e2e/billing/credit_memo/test_sync_credit_memo.py
📚 Learning: 2025-12-12T15:02:20.732Z
Learnt from: robcsegal
Repo: softwareone-platform/mpt-api-python-client PR: 160
File: tests/e2e/commerce/agreement/attachment/test_async_agreement_attachment.py:55-58
Timestamp: 2025-12-12T15:02:20.732Z
Learning: In pytest with pytest-asyncio, if a test function uses async fixtures but contains no await, declare the test function as def (synchronous) instead of async def. Pytest-asyncio will resolve the async fixtures automatically; this avoids linter complaints about unnecessary async functions. This pattern applies to any test file under the tests/ directory that uses such fixtures.

Applied to files:

  • tests/e2e/billing/credit_memo/test_async_credit_memo.py
  • tests/e2e/billing/credit_memo/conftest.py
  • tests/e2e/billing/credit_memo/test_sync_credit_memo.py
📚 Learning: 2026-01-08T23:38:19.565Z
Learnt from: robcsegal
Repo: softwareone-platform/mpt-api-python-client PR: 186
File: tests/e2e/billing/ledger/charge/test_sync_ledger_charge.py:33-39
Timestamp: 2026-01-08T23:38:19.565Z
Learning: In Python e2e tests under tests/e2e, hardcoded external IDs (e.g., INV12345) are intentional because they come from seeded test data. Ensure the test data seeds consistently include these IDs; if seeds change, update tests accordingly. Prefer using a named constant for such IDs (e.g., INV_EXTERNAL_ID) and document the dependency on seed data to avoid brittle tests.

Applied to files:

  • tests/e2e/billing/credit_memo/test_async_credit_memo.py
  • tests/e2e/billing/credit_memo/conftest.py
  • tests/e2e/billing/credit_memo/test_sync_credit_memo.py
🧬 Code graph analysis (1)
tests/e2e/billing/credit_memo/test_sync_credit_memo.py (5)
mpt_api_client/exceptions.py (1)
  • MPTAPIError (20-42)
mpt_api_client/rql/query_builder.py (1)
  • RQLQuery (115-524)
tests/e2e/conftest.py (1)
  • mpt_ops (31-32)
mpt_api_client/models/model.py (1)
  • id (119-121)
tests/e2e/billing/credit_memo/conftest.py (1)
  • invalid_credit_memo_id (5-6)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (9)
tests/e2e/billing/credit_memo/conftest.py (1)

1-6: LGTM!

Clean and straightforward fixture for negative test cases. The ID format follows the expected credit memo pattern and provides a consistent invalid ID for 404 scenarios across both async and sync tests.

tests/e2e/billing/credit_memo/test_async_credit_memo.py (4)

1-6: LGTM!

Appropriate imports and the flaky marker is suitable for e2e tests that depend on external systems and pre-existing data.


9-19: LGTM!

The credit_memo fixture correctly uses def instead of async def since it contains no await expressions, and pytest-asyncio handles the async fixture resolution automatically. Based on learnings, this follows the team's established pattern.


30-32: LGTM!

Clean negative test case that properly validates the 404 response for a non-existent credit memo.


35-40: LGTM!

Straightforward list test. The flaky marker appropriately accounts for the dependency on pre-existing data.

tests/e2e/billing/credit_memo/test_sync_credit_memo.py (4)

1-6: LGTM!

Appropriate imports and flaky marker consistent with the async test module.


9-19: LGTM!

Fixtures appropriately reuse existing API resources for read-only operations, following the team's pattern for e2e test efficiency. Based on learnings, this approach is intentional.


30-32: LGTM!

Properly validates the 404 response for a non-existent credit memo ID.


35-40: LGTM!

The list test is appropriately marked flaky and follows the team's pattern for e2e tests.

@robcsegal robcsegal force-pushed the MPT-14923-add-e-2-e-tests-for-billing-credit-memos branch from be0c9fc to 644a970 Compare January 12, 2026 15:46
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @tests/e2e/billing/credit_memo/test_sync_credit_memo.py:
- Around line 37-42: test_list_credit_memos currently asserts there are results
but doesn't handle an empty system; update the test to mirror other tests by
importing pytest if needed and adding a check after calling
mpt_ops.billing.credit_memos.fetch_page(limit=limit): if len(result) == 0 then
call pytest.skip("no credit memos available") so the test is skipped in
environments with no data (alternatively change the assertion to assert
len(result) >= 0 if empty results are acceptable).
🧹 Nitpick comments (1)
tests/e2e/billing/credit_memo/test_sync_credit_memo.py (1)

22-29: Consider strengthening the assertion.

The test verifies the result is not None, but could also verify that the returned credit memo's ID matches the requested ID for more thorough validation.

💡 Suggested improvement
     result = mpt_ops.billing.credit_memos.get(credit_memo_id)

-    assert result is not None
+    assert result is not None
+    assert result.id == credit_memo_id
📜 Review details

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between be0c9fc and 644a970.

📒 Files selected for processing (3)
  • tests/e2e/billing/credit_memo/conftest.py
  • tests/e2e/billing/credit_memo/test_async_credit_memo.py
  • tests/e2e/billing/credit_memo/test_sync_credit_memo.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/e2e/billing/credit_memo/test_async_credit_memo.py
🧰 Additional context used
📓 Path-based instructions (2)
**/*

⚙️ CodeRabbit configuration file

**/*: For each subsequent commit in this PR, explicitly verify if previous review comments have been resolved

Files:

  • tests/e2e/billing/credit_memo/test_sync_credit_memo.py
  • tests/e2e/billing/credit_memo/conftest.py
**/*.py

⚙️ CodeRabbit configuration file

**/*.py: Follow the linting rules defined in pyproject.toml under [tool.ruff] and [tool.flake8] sections.
For formatting, use Ruff instead of Black. Do not suggest Black formatting changes.

Files:

  • tests/e2e/billing/credit_memo/test_sync_credit_memo.py
  • tests/e2e/billing/credit_memo/conftest.py
🧠 Learnings (3)
📚 Learning: 2026-01-08T08:34:05.465Z
Learnt from: albertsola
Repo: softwareone-platform/mpt-api-python-client PR: 183
File: tests/e2e/catalog/price_lists/conftest.py:29-30
Timestamp: 2026-01-08T08:34:05.465Z
Learning: In end-to-end tests (e.g., tests/e2e/...), reuse existing API resources for read-only operations and safe mutations to speed up test execution. Reserve isolated fixtures (e.g., created_price_list) for destructive tests that require per-test creation and cleanup. Ensure tests document when a fixture creates/destroys data and clearly indicate which operations are destructive, so tests stay fast and properly isolated.

Applied to files:

  • tests/e2e/billing/credit_memo/test_sync_credit_memo.py
  • tests/e2e/billing/credit_memo/conftest.py
📚 Learning: 2025-12-12T15:02:20.732Z
Learnt from: robcsegal
Repo: softwareone-platform/mpt-api-python-client PR: 160
File: tests/e2e/commerce/agreement/attachment/test_async_agreement_attachment.py:55-58
Timestamp: 2025-12-12T15:02:20.732Z
Learning: In pytest with pytest-asyncio, if a test function uses async fixtures but contains no await, declare the test function as def (synchronous) instead of async def. Pytest-asyncio will resolve the async fixtures automatically; this avoids linter complaints about unnecessary async functions. This pattern applies to any test file under the tests/ directory that uses such fixtures.

Applied to files:

  • tests/e2e/billing/credit_memo/test_sync_credit_memo.py
  • tests/e2e/billing/credit_memo/conftest.py
📚 Learning: 2026-01-08T23:38:19.565Z
Learnt from: robcsegal
Repo: softwareone-platform/mpt-api-python-client PR: 186
File: tests/e2e/billing/ledger/charge/test_sync_ledger_charge.py:33-39
Timestamp: 2026-01-08T23:38:19.565Z
Learning: In Python e2e tests under tests/e2e, hardcoded external IDs (e.g., INV12345) are intentional because they come from seeded test data. Ensure the test data seeds consistently include these IDs; if seeds change, update tests accordingly. Prefer using a named constant for such IDs (e.g., INV_EXTERNAL_ID) and document the dependency on seed data to avoid brittle tests.

Applied to files:

  • tests/e2e/billing/credit_memo/test_sync_credit_memo.py
  • tests/e2e/billing/credit_memo/conftest.py
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (4)
tests/e2e/billing/credit_memo/conftest.py (1)

1-6: LGTM!

Clean fixture providing a well-formed invalid ID for 404 testing. The CRD- prefix follows the expected credit memo ID format.

tests/e2e/billing/credit_memo/test_sync_credit_memo.py (3)

1-6: LGTM!

Imports are clean and the module-level flaky marker correctly aligns with project conventions for e2e tests as per pyproject.toml configuration.


9-19: LGTM - fixtures follow the read-only resource reuse pattern.

Based on learnings, reusing existing API resources for read-only operations is the correct approach here. The None handling in credit_memo properly supports skip logic in dependent tests.

Consider moving these fixtures to conftest.py if the async test module needs similar fixtures, to avoid duplication.


45-59: LGTM!

Well-structured filter test with appropriate skip logic. The chained filter calls with RQLQuery and field exclusion via select demonstrate comprehensive API coverage.

@sonarqubecloud
Copy link

@robcsegal robcsegal merged commit e65c348 into main Jan 12, 2026
4 checks passed
@robcsegal robcsegal deleted the MPT-14923-add-e-2-e-tests-for-billing-credit-memos branch January 12, 2026 16:30
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.

3 participants