| name | test-qa |
| description | Create test cases, run QA/QC checks, and ensure code quality.
Use when asked to write tests, review code quality, or perform QA.
Supports: unit tests, integration tests, coverage analysis, linting, type checking.
|
Test & QA Agent
Overview
This skill handles test creation, test execution, and quality assurance for the MemRAG project.
Test Structure
Backend Tests (pytest)
- Location:
backend/tests/
- Framework: pytest + pytest-asyncio + pytest-mock
- Config:
backend/pyproject.toml
- Fixtures:
backend/tests/conftest.py (uses app.dependency_overrides)
- Pattern: Unit tests with mocked external services (Qdrant, mem0, DynamoDB, Gemini)
Frontend Tests
- Location:
frontend/src/__tests__/ (if exists)
- Framework: (check package.json for test runner)
Commands
Run All Backend Tests
cd /home/minhdd/pet_proj/proj2/backend && uv run pytest tests/ -v
Run with Coverage
cd /home/minhdd/pet_proj/proj2/backend && uv run pytest tests/ -v --cov=app --cov-report=term-missing --cov-report=html
Run Specific Test File
cd /home/minhdd/pet_proj/proj2/backend && uv run pytest tests/test_wiki_service.py -v
Run Specific Test Function
cd /home/minhdd/pet_proj/proj2/backend && uv run pytest tests/test_wiki_service.py::test_slugify_basic -v
Run Tests Matching Pattern
cd /home/minhdd/pet_proj/proj2/backend && uv run pytest tests/ -k "wiki" -v
Linting & Formatting
cd /home/minhdd/pet_proj/proj2/backend && uv run ruff format . && uv run ruff check .
cd /home/minhdd/pet_proj/proj2/frontend && npm run lint
Test Writing Conventions
Backend Test Patterns
-
Use fixtures from conftest.py:
app — FastAPI app with dependency overrides
client — AsyncClient for HTTP tests
mock_qdrant_client — Mocked Qdrant
mock_mem0_client — Mocked mem0
mock_dynamo_session_service — Mocked DynamoDB
mock_runner — Mocked ADK runner
wiki_dir, repo, settings, service — For wiki tests
-
Mock external services via dependency_overrides:
@pytest.fixture
def mock_qdrant_client(app):
client = MagicMock()
client.search.return_value = []
app.dependency_overrides[get_qdrant_client] = lambda: client
return client
- Async tests:
@pytest.mark.asyncio
async def test_something(service):
result = await service.some_method()
assert result is not None
- Patch LLM calls:
from unittest.mock import patch as _patch
from unittest.mock import AsyncMock
with _patch("app.services.wiki_service.get_genai_client") as mock_client:
mock_client.return_value.aio.models.generate_content.side_effect = RuntimeError("LLM down")
result = await service._extract_topics(text="some text", source_name="paper.pdf")
- Test structure:
- Arrange: Setup mocks and fixtures
- Act: Call the method under test
- Assert: Verify expected behavior
- Use descriptive test names:
test_<method>_<scenario>_<expected_behavior>
Test Categories
-
Unit Tests (test_*_service.py, test_*_repo.py)
- Test individual components in isolation
- Mock all external dependencies
- Focus on business logic
-
Integration Tests (test_*.py for API endpoints)
- Test HTTP endpoints via
client
- Verify request/response flow
- Use dependency overrides for external services
-
Edge Cases
- Empty inputs
- Invalid inputs
- Error handling
- Disabled features (e.g.,
wiki_enabled=False)
QA Checklist
When reviewing code or creating tests, ensure:
Code Quality
Test Coverage
Integration
Documentation
Creating New Tests
When asked to create tests:
-
Identify what to test:
- New features/functions
- Bug fixes (add regression tests)
- Untested code paths
-
Choose test type:
- Unit test: Single function/class
- Integration test: API endpoint or workflow
- Edge case test: Error handling, invalid inputs
-
Write the test:
- Use existing fixtures from
conftest.py
- Mock external services appropriately
- Follow naming conventions
- Add clear assertions with descriptive messages
-
Verify:
- Run the test:
uv run pytest tests/test_file.py::test_name -v
- Check coverage impact
- Ensure no regressions
Debugging Failed Tests
When tests fail:
- Read the error message carefully
- Check if it's a mock issue:
- Missing fixture
- Incorrect mock return value
- Async vs sync mock mismatch
- Check if it's a logic issue:
- Wrong assertion
- Changed behavior
- Run with verbose output:
uv run pytest tests/test_file.py::test_name -v -s
- Use pytest debugger:
import pytest; pytest.set_trace()
Common Patterns
Testing Async Methods
@pytest.mark.asyncio
async def test_async_method(service):
result = await service.async_method()
assert result == expected
Testing Error Handling
@pytest.mark.asyncio
async def test_method_handles_error(service):
with patch.object(service, "dependency", side_effect=RuntimeError("fail")):
await service.method()
Testing HTTP Endpoints
@pytest.mark.asyncio
async def test_endpoint(client):
response = await client.post("/api/v1/chat", json={"message": "hello"})
assert response.status_code == 200
assert "response" in response.json()
Testing Wiki Service
@pytest.mark.asyncio
async def test_wiki_synthesis(service, repo):
topics = [{"slug": "test-topic", "category": "topics", "title": "Test"}]
synthesized = "---\ntitle: Test\nsources: [doc-1]\n---\n# Test"
with (
patch.object(service, "_extract_topics", new=AsyncMock(return_value=topics)),
patch.object(service, "_synthesize_page", new=AsyncMock(return_value=synthesized)),
):
await service.update_wiki_from_document(
user_id=USER,
document_id="doc-1",
filename="test.pdf",
full_text="content",
)
page = repo.read_page(user_id=USER, rel_path="pages/topics/test-topic.md")
assert page is not None
Running Full QA Suite
Before marking a task complete:
cd /home/minhdd/pet_proj/proj2/backend && uv run ruff format . && uv run ruff check .
cd /home/minhdd/pet_proj/proj2/backend && uv run pytest tests/ -v --cov=app --cov-report=term-missing
cd /home/minhdd/pet_proj/proj2/frontend && npm run lint
Report results:
- Number of tests passed/failed
- Coverage percentage
- Any linting issues
- Recommendations for improvements