test: Add unit tests for backend-api#211
Open
Shreyas-Microsoft wants to merge 16 commits intodevfrom
Open
Conversation
Generate a text-format summary with only the TOTAL line from coverage.xml. Use pytest-coverage-path instead of pytest-xml-coverage-path so the Coverage Report dropdown shows only TOTAL row without per-file listing. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Fix test_returns_false_for_none to call is_valid_uuid directly - Fix inaccurate comment about non-existent env file path - Make test_get_service_status_not_initialized deterministic with mock - Exclude test files from processor coverage (tool.coverage.run.omit) - Regenerate uv.lock with pytest-asyncio Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment on lines
+3
to
+25
| import importlib | ||
| from types import SimpleNamespace | ||
| from unittest.mock import MagicMock, patch | ||
|
|
||
| import pytest | ||
| from pydantic import BaseModel, ValidationError | ||
| from semantic_kernel.exceptions.service_exceptions import ServiceInitializationError | ||
|
|
||
| # The source module imports SKBaseModel from libs.base.SKBase, but that module | ||
| # is empty in the repository. Inject a minimal stand-in before importing | ||
| # kernel_agent so tests can exercise the file without touching source. | ||
| import libs.base.SKBase as _skbase_mod # noqa: E402 | ||
|
|
||
| if not hasattr(_skbase_mod, "SKBaseModel"): | ||
|
|
||
| class _SKBaseModelStub(BaseModel): | ||
| model_config = {"arbitrary_types_allowed": True} | ||
|
|
||
| _skbase_mod.SKBaseModel = _SKBaseModelStub # type: ignore[attr-defined] | ||
|
|
||
| importlib.import_module("libs.base.kernel_agent") # noqa: E402 | ||
|
|
||
|
|
Comment on lines
+136
to
+142
| def test_local_environment_recommendations(self): | ||
| cred = MagicMock() | ||
| cred.__class__.__name__ = "AzureCliCredential" | ||
| with patch.object(credential_util, "get_azure_credential", return_value=cred): | ||
| info = credential_util.validate_azure_authentication() | ||
| assert info["environment"] == "local_development" | ||
| assert info["status"] == "configured" |
Comment on lines
+27
to
+29
| def _run(coro): | ||
| return asyncio.get_event_loop().run_until_complete(coro) if False else asyncio.run(coro) | ||
|
|
Comment on lines
+84
to
+94
| python -c " | ||
| import xml.etree.ElementTree as ET | ||
| tree = ET.parse('src/backend-api/reports/coverage.xml') | ||
| root = tree.getroot() | ||
| stmts = int(root.attrib.get('lines-valid', 0)) | ||
| miss = stmts - int(root.attrib.get('lines-covered', 0)) | ||
| cover = int(float(root.attrib.get('line-rate', 0)) * 100) | ||
| with open('src/backend-api/reports/coverage-summary.txt', 'w') as f: | ||
| f.write('Name Stmts Miss Cover\n') | ||
| f.write(f'TOTAL {stmts} {miss} {cover}%\n') | ||
| " |
Comment on lines
+156
to
+166
| python -c " | ||
| import xml.etree.ElementTree as ET | ||
| tree = ET.parse('src/processor/reports/coverage.xml') | ||
| root = tree.getroot() | ||
| stmts = int(root.attrib.get('lines-valid', 0)) | ||
| miss = stmts - int(root.attrib.get('lines-covered', 0)) | ||
| cover = int(float(root.attrib.get('line-rate', 0)) * 100) | ||
| with open('src/processor/reports/coverage-summary.txt', 'w') as f: | ||
| f.write('Name Stmts Miss Cover\n') | ||
| f.write(f'TOTAL {stmts} {miss} {cover}%\n') | ||
| " |
Use pytest-xml-coverage-path with coverage-path-prefix so the action correctly resolves XML paths (relative to subdir) against PR diff paths. Combined with report-only-changed-files: true, when no source files are in the diff this shows: badge + Coverage Report dropdown with TOTAL row + 'No files were changed' note + test summary table. Matches the format used in Multi-Agent-Custom-Automation-Engine PR #961. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment on lines
+3
to
+25
| import importlib | ||
| from types import SimpleNamespace | ||
| from unittest.mock import MagicMock, patch | ||
|
|
||
| import pytest | ||
| from pydantic import BaseModel, ValidationError | ||
| from semantic_kernel.exceptions.service_exceptions import ServiceInitializationError | ||
|
|
||
| # The source module imports SKBaseModel from libs.base.SKBase, but that module | ||
| # is empty in the repository. Inject a minimal stand-in before importing | ||
| # kernel_agent so tests can exercise the file without touching source. | ||
| import libs.base.SKBase as _skbase_mod # noqa: E402 | ||
|
|
||
| if not hasattr(_skbase_mod, "SKBaseModel"): | ||
|
|
||
| class _SKBaseModelStub(BaseModel): | ||
| model_config = {"arbitrary_types_allowed": True} | ||
|
|
||
| _skbase_mod.SKBaseModel = _SKBaseModelStub # type: ignore[attr-defined] | ||
|
|
||
| importlib.import_module("libs.base.kernel_agent") # noqa: E402 | ||
|
|
||
|
|
Comment on lines
+119
to
+122
| uses: actions/checkout@v5 | ||
|
|
||
| - name: Set up Python | ||
| uses: actions/setup-python@v6 |
Comment on lines
+87
to
+93
| prefix = "src/backend-api/src/app/" | ||
| tree = ET.parse(path) | ||
| root = tree.getroot() | ||
| for cls in root.iter("class"): | ||
| fname = cls.attrib.get("filename", "") | ||
| if fname and not fname.startswith(prefix): | ||
| cls.attrib["filename"] = prefix + fname |
Comment on lines
+161
to
+167
| prefix = "src/processor/src/" | ||
| tree = ET.parse(path) | ||
| root = tree.getroot() | ||
| for cls in root.iter("class"): | ||
| fname = cls.attrib.get("filename", "") | ||
| if fname and not fname.startswith(prefix): | ||
| cls.attrib["filename"] = prefix + fname |
Processor: 75% -> 87.44% (+199 tests across 5 files) - queue_service.py: 35% -> 86% - groupchat_orchestrator.py: 25% -> ~70%+ (helpers fully covered) - mcp_mermaid.py: 52% -> 99% - application_base.py: 0% -> 100% - main.py: 0% -> 94% Backend-api: 82.27% -> 93.28% (+125 tests across 7 files) - SKLogicBase.py: 0% -> 93% - blob/helper.py: 68% -> 99% - blob/async_helper.py: 72% -> 97% - blob/config.py: 70% -> 100% - shared_config.py: 67% -> 100% - services/interfaces.py: 74% -> 100% - file_repository.py / process_repository.py: 67% -> 100% CI: add --cov-fail-under=82 to both backend and processor jobs in .github/workflows/test.yml so the pipeline fails when coverage drops below 82%. Backend pyproject.toml: add [tool.coverage.run] omit list for parity with processor so local pytest runs (which use pytest.ini's --cov=src) do not inflate coverage with test-file lines. No production code modified, no coverage exclusions added beyond the test directory, all 1077 prior + new tests pass on both services. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Purpose
This pull request adds comprehensive unit tests for several core backend components, focusing on application initialization, dependency injection, Azure App Configuration integration, FastAPI extensions, kernel agent logic, and model entities. These tests ensure correct instantiation, lifecycle management, and integration of services and models, greatly improving the reliability and maintainability of the codebase.
Application Initialization and Dependency Injection:
Applicationclass to verify correct FastAPI setup, context assignment, core service registration, and router inclusion.AppContextand related dependency injection features, covering service lifetimes (singleton, scoped, async), scope management, async resource cleanup, and shutdown behavior.Azure App Configuration Integration:
AppConfigurationHelperto ensure correct credential handling, endpoint validation, environment variable population from configuration, and delegation to the underlying Azure client.FastAPI Extensions:
TypedFastAPI, verifying context assignment, FastAPI compatibility, and utility functions for attaching application context.Kernel Agent Logic:
kernel_agent, including initialization, plugin and function management, service registration, error handling, and service type enumeration.Model Entities:
Process,File,AgentStatus,ProcessStatus, andProcessStartQueueMessage, ensuring correct default values, field assignments, and serialization logic.Does this introduce a breaking change?
Golden Path Validation
Deployment Validation
What to Check
Verify that the following are valid
Other Information