Skip to content

feat: increase backend test coverage to 87%#3631

Merged
arkid15r merged 8 commits intoOWASP:mainfrom
HarshitVerma109:test-coverage-improvement
Jan 29, 2026
Merged

feat: increase backend test coverage to 87%#3631
arkid15r merged 8 commits intoOWASP:mainfrom
HarshitVerma109:test-coverage-improvement

Conversation

@HarshitVerma109
Copy link
Contributor

@HarshitVerma109 HarshitVerma109 commented Jan 28, 2026

Proposed change

Resolves #3607

This PR increases the backend test coverage from 83% to 87% by adding comprehensive unit tests for previously untested or low-coverage files.

Checklist

  • Required: I followed the contributing workflow
  • Required: I verified that my code works as intended and resolves the issue as described
  • Required: I ran make check-test locally: all warnings addressed, tests passed
  • I used AI for code, documentation, tests, or communication related to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 28, 2026

Summary by CodeRabbit

  • Tests

    • Added comprehensive test coverage for AI agent nodes, middleware null-character blocking, GitHub integration features, OWASP admin functionality, API permissions and health metrics views, board candidate synchronization, and Slack event handling.
  • Chores

    • Updated custom dictionary for spell-checking.

✏️ Tip: You can customize this high-level summary in your review settings.

Walkthrough

Adds many new unit tests across backend apps (AI agent, common middleware, GitHub, OWASP, Slack) and a single dictionary entry; tests cover AgentNodes flows, null-character middleware, GitHub command/model logic, OWASP admin/views/commands, Slack handlers/commands, and PDF/URL endpoints.

Changes

Cohort / File(s) Summary
AI Agent tests
backend/tests/apps/ai/agent/nodes_test.py
New unit tests for AgentNodes: init, retrieve/generate/evaluate flows, metadata extraction, retriever usage, chunk filtering, routing, and OpenAI error handling.
Common middleware tests
backend/tests/apps/common/middlewares/__init__.py, backend/tests/apps/common/middlewares/block_null_characters_test.py
Adds package init and tests verifying BlockNullCharactersMiddleware rejects null chars in path, query params, POST data, and body.
GitHub tests
backend/tests/apps/github/management/commands/github_update_pull_requests_test.py, backend/tests/apps/github/models/comment_test.py
Tests for PR→issue linking command behavior and Comment model import/update and string formatting.
OWASP admin & mixins tests
backend/tests/apps/owasp/admin/mixins_test.py
Tests for BaseOwaspAdminMixin, GenericEntityAdminMixin, and StandardOwaspAdminMixin list/search/display helpers and config merging.
OWASP API views/tests
backend/tests/apps/owasp/api/internal/views/permissions_test.py, backend/tests/apps/owasp/api/internal/views/project_health_metrics_test.py, backend/tests/apps/owasp/api/internal/views/urls_test.py
Adds permission checks across environments, PDF generation success/error paths, and URL routing resolution tests for project health metrics.
OWASP management command tests
backend/tests/apps/owasp/management/commands/owasp_sync_board_candidates_test.py
Tests candidate filename/frontmatter parsing, sync success and API error handling, and year-based command delegation (fixture introduction and signature updates).
Slack tests
backend/tests/apps/slack/events/app_mention_test.py, backend/tests/apps/slack/management/commands/owasp_match_channels_test.py
Tests AppMention event handling (blocks/text, disabled convo) and owasp_match_channels command (dry-run, creation path, OWASP prefix stripping).
Spell dictionary
cspell/custom-dict.txt
Adds boardofdirectors entry to custom dictionary.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • kasya
🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 1.35% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main objective of the PR: increasing backend test coverage from 83% to 87% by adding comprehensive unit tests.
Description check ✅ Passed The description is directly related to the changeset, clearly stating that it resolves issue #3607 by increasing backend test coverage through adding comprehensive unit tests for previously untested files.
Linked Issues check ✅ Passed The PR successfully addresses all requirements from issue #3607: it adds comprehensive unit tests for all 10 identified low-coverage backend files with proper mocking of external dependencies (OpenAI, GitHub API, Slack API, Django ORM), achieving the stated goal of raising coverage from 83% to 87%.
Out of Scope Changes check ✅ Passed All changes are in scope: new test files for identified low-coverage modules, one package initializer, and one custom dictionary entry for spell-checking. No unrelated modifications were introduced outside the test coverage improvement objectives.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

coderabbitai[bot]
coderabbitai bot previously approved these changes Jan 28, 2026
coderabbitai[bot]
coderabbitai bot previously approved these changes Jan 28, 2026
Copy link
Collaborator

@arkid15r arkid15r left a comment

Choose a reason for hiding this comment

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

Please don't forget to check your code locally before requesting review from maintainers.

Copy link
Contributor

@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: 2

🤖 Fix all issues with AI agents
In `@backend/tests/apps/ai/agent/nodes_test.py`:
- Around line 8-11: The test fixture mock_openai patches openai.OpenAI globally;
change it to patch the import location used by the module under test by patching
"apps.ai.agent.nodes.openai.OpenAI" instead (keep the existing
mocker.patch("os.getenv", return_value="fake-key") and return the patched
object), so the mock applies only to the OpenAI class used in tests for
functions/classes in apps.ai.agent.nodes.

In `@backend/tests/apps/slack/management/commands/owasp_match_channels_test.py`:
- Around line 87-90: The test currently patches EntityChannel.objects as
mock_ec_qs but doesn't explicitly set the return value for the
filter(...).exists() chain, relying on Mock truthiness; update the mock to
explicitly set mock_ec_qs.filter.return_value.exists.return_value = True (or
False as appropriate for the "exists" path you want to cover) so the command's
dry-run branch is exercised; keep the existing mock_get_or_create setup
(mock_get_or_create.return_value = (None, True)) and ensure you set the exists()
value before invoking the command in the test.

coderabbitai[bot]
coderabbitai bot previously approved these changes Jan 29, 2026
Copy link
Contributor

@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 `@backend/tests/apps/owasp/api/internal/views/project_health_metrics_test.py`:
- Around line 120-152: The test name
test_generate_project_health_metrics_pdf_no_metrics is misleading because the
mock for ProjectHealthMetrics.get_latest_health_metrics returns a truthy mock
(so metrics exist) and the Http404 is triggered by generate_latest_metrics_pdf
returning None; rename the test to
test_generate_project_health_metrics_pdf_generation_fails or change the mock to
return None from ProjectHealthMetrics.get_latest_health_metrics.first() to truly
test the "no metrics" path; locate references to
generate_project_health_metrics_pdf,
ProjectHealthMetrics.get_latest_health_metrics, and generate_latest_metrics_pdf
in the test to apply the rename or adjust the mocked return value accordingly.
🧹 Nitpick comments (5)
backend/tests/apps/github/models/comment_test.py (1)

71-76: Remove redundant initial body assignment.

The body parameter on line 72 is immediately overwritten on line 74, making the initial assignment unnecessary.

♻️ Suggested simplification
     def test_str_representation(self):
-        comment = Comment(body="A very long comment body that should be truncated", author=None)
-        long_body = "A" * 60
-        comment.body = long_body
+        comment = Comment(body="A" * 60, author=None)
         assert str(comment).startswith("None - AAAAA")
         assert len(str(comment)) <= 60  # approx
backend/tests/apps/common/middlewares/block_null_characters_test.py (2)

39-47: Consider verifying response message for consistency.

These tests only assert the status code, whereas test_null_in_path_blocks and test_null_in_body_blocks also verify the full JSON response body. For consistency and to catch regressions in error messages, consider adding the same message assertion here.

♻️ Suggested enhancement for consistency
     def test_null_in_query_params_blocks(self, middleware, factory):
         request = factory.get("/clean/path", {"q": "bad\x00value"})
         response = middleware(request)
         assert response.status_code == HTTPStatus.BAD_REQUEST
+        assert json.loads(response.content) == {
+            "message": "Request contains null characters in URL or parameters "
+            "which are not allowed.",
+            "errors": {},
+        }
 
     def test_null_in_post_data_blocks(self, middleware, factory):
         request = factory.post("/clean/path", {"data": "bad\x00value"})
         response = middleware(request)
         assert response.status_code == HTTPStatus.BAD_REQUEST
+        assert json.loads(response.content) == {
+            "message": "Request contains null characters in URL or parameters "
+            "which are not allowed.",
+            "errors": {},
+        }

62-69: Consider adding response body assertion for unicode null test as well.

For consistency with test_null_in_body_blocks, this test should also verify the JSON response message.

♻️ Suggested enhancement
     def test_unicode_null_in_body_blocks(self, middleware, factory):
         request = factory.post(
             "/clean/path",
             data=b'{"key": "bad\\u0000value"}',
             content_type="application/json",
         )
         response = middleware(request)
         assert response.status_code == HTTPStatus.BAD_REQUEST
+        assert json.loads(response.content) == {
+            "message": "Request contains null characters in body which are not allowed.",
+            "errors": {},
+        }
backend/tests/apps/owasp/management/commands/owasp_sync_board_candidates_test.py (1)

69-71: Remove redundant mock.

This patch is immediately overridden by the patch at lines 94-97 with a side_effect, making this initial patch completely unused.

♻️ Proposed fix
     def test_sync_year_candidates_success(self, command, mocker):
-        mocker.patch(
-            "apps.owasp.management.commands.owasp_sync_board_candidates.get_repository_file_content"
-        )
-
         mock_board = Mock()
         mock_board.id = 100
backend/tests/apps/owasp/admin/mixins_test.py (1)

45-52: Make HTML assertions less brittle.

Hard-coding single-quote markup can make tests fail if attribute quoting/order changes. Prefer checking URL substrings (or parsing HTML) to keep tests stable.

♻️ Suggested tweak
-        assert "href='https://owasp.org/test-project'" in url
-        assert "target='_blank'" in url
+        assert "https://owasp.org/test-project" in url
+        assert "target" in url and "_blank" in url
@@
-        assert "href='https://github.com/owasp/repo-1'" in urls
-        assert "href='https://github.com/owasp/repo-2'" in urls
+        assert "https://github.com/owasp/repo-1" in urls
+        assert "https://github.com/owasp/repo-2" in urls
@@
-        assert "href='https://github.com/owasp/main-repo'" in urls
+        assert "https://github.com/owasp/main-repo" in urls

Also applies to: 61-77, 79-92

coderabbitai[bot]
coderabbitai bot previously approved these changes Jan 29, 2026
@arkid15r arkid15r enabled auto-merge January 29, 2026 22:01
@sonarqubecloud
Copy link

Copy link
Collaborator

@arkid15r arkid15r left a comment

Choose a reason for hiding this comment

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

LGTM

@arkid15r
Copy link
Collaborator

Thanks for improving BE test coverage!

@codecov
Copy link

codecov bot commented Jan 29, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 87.72%. Comparing base (98418cc) to head (747cd45).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #3631      +/-   ##
==========================================
+ Coverage   85.56%   87.72%   +2.15%     
==========================================
  Files         463      463              
  Lines       14306    14306              
  Branches     1903     1903              
==========================================
+ Hits        12241    12550     +309     
+ Misses       1686     1344     -342     
- Partials      379      412      +33     
Flag Coverage Δ
backend 87.48% <ø> (+2.93%) ⬆️
frontend 88.38% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.
see 11 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 98418cc...747cd45. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@arkid15r arkid15r added this pull request to the merge queue Jan 29, 2026
Merged via the queue into OWASP:main with commit 7fcdd46 Jan 29, 2026
35 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improve Test Coverage for Low-Coverage Backend Files

2 participants

Comments