This document summarizes the complete testing infrastructure rebuild for the Gofannon project.
✅ Full test coverage infrastructure for frontend and backend ✅ 95% minimum coverage requirement enforced via CI/CD ✅ Automated PR checks run unit tests on every pull request ✅ Nightly integration tests run comprehensive tests daily ✅ Comprehensive documentation for writing and maintaining tests ✅ Example tests demonstrating best practices ✅ Test data factories for generating consistent test fixtures
| Type | Location | Run When | Purpose |
|---|---|---|---|
| Unit Tests (Frontend) | packages/webui/src/**/*.test.jsx | Every PR | Test React components in isolation |
| Unit Tests (Backend) | packages/api/user-service/tests/unit/ | Every PR | Test Python functions/classes in isolation |
| Integration Tests | packages/api/user-service/tests/integration/ | Nightly | Test with real services (DB, S3, etc.) |
| E2E Tests | webapp/tests/e2e/ | Nightly | Test complete user workflows |
Files Created:
vitest.config.ts - Vitest configurationsrc/test/setup.ts - Test environment setupsrc/components/ActionCard.test.jsx - Example component testsrc/test/utils.test.js - Example utility testDependencies Added:
vitest - Test runner@testing-library/react - React component testing utilities@testing-library/user-event - User interaction simulation@testing-library/jest-dom - DOM matchers@vitest/ui - Interactive test UI@vitest/coverage-v8 - Coverage reportingjsdom - DOM environment for NodeCommands:
pnpm test # Run tests pnpm test:ui # Interactive UI pnpm test:coverage # With coverage report
Files Created:
pytest.ini - pytest configuration.coveragerc - Coverage settingstests/conftest.py - Shared fixturestests/factories/ - Test data factoriesagent_factory.pyuser_factory.pychat_factory.pytests/unit/test_user_service.py - Example service teststests/unit/test_user_model.py - Example model teststests/integration/test_health_endpoint.py - Example integration testDependencies Added:
pytest>=8.0.0 - Test frameworkpytest-asyncio>=0.23.0 - Async test supportpytest-cov>=4.1.0 - Coverage pluginpytest-mock>=3.12.0 - Mocking utilitiesfactory-boy>=3.3.0 - Test data factoriesfaker>=22.0.0 - Fake data generationCommands:
python -m pytest tests/unit # Unit tests python -m pytest tests/integration # Integration tests python -m pytest --cov=. --cov-report=html # With coverage
Files Created:
pr-unit-tests.yml - Runs on every PR
nightly-integration-tests.yml - Runs daily at 2 AM UTC
Secrets Required:
OPENAI_API_KEY - For AI model testingGEMINI_API_KEY - For alternative AI modelAWS_ACCESS_KEY_ID - For S3 integration testsAWS_SECRET_ACCESS_KEY - For S3 integration testsAWS_REGION - AWS region (optional, defaults to us-east-1)Updated package.json:
{ "test": "pnpm run test:unit && pnpm run test:integration", "test:unit": "pnpm run test:unit:frontend && pnpm run test:unit:backend", "test:unit:frontend": "pnpm --filter webui test", "test:unit:backend": "cd packages/api/user-service && python -m pytest tests/unit -v", "test:integration": "pnpm run test:integration:backend && pnpm run test:e2e", "test:integration:backend": "cd packages/api/user-service && python -m pytest tests/integration -v", "test:e2e": "playwright test", "test:coverage": "pnpm run test:coverage:frontend && pnpm run test:coverage:backend", "test:coverage:frontend": "pnpm --filter webui test:coverage", "test:coverage:backend": "cd packages/api/user-service && python -m pytest tests/unit --cov=. --cov-report=html --cov-report=term-missing" }
Created in docs/testing/:
README.md - Testing overview and quick startunit-testing.md - Comprehensive unit testing guidecontributing.md - PR requirements and guidelinesSUMMARY.md - This documentTopics Covered:
class TestUserService: @pytest.fixture def mock_db(self): db = Mock() db.get = Mock(return_value={"id": "test-123"}) return db def test_get_user_existing(self, user_service, mock_db): user = user_service.get_user("test-123") mock_db.get.assert_called_once_with("users", "test-123") assert user.id == "test-123"
describe('ActionCard', () => { it('calls onClick when clicked', async () => { const onClick = vi.fn(); render(<ActionCard {...props} onClick={onClick} />); await userEvent.click(screen.getByRole('button')); expect(onClick).toHaveBeenCalled(); }); });
webapp/ ├── packages/ │ ├── webui/ # Frontend │ │ ├── src/ │ │ │ ├── components/*.test.jsx # Component tests │ │ │ └── test/ │ │ │ ├── setup.ts # Test setup │ │ │ └── *.test.js # Utility tests │ │ └── vitest.config.ts # Vitest config │ │ │ └── api/user-service/ # Backend │ ├── tests/ │ │ ├── conftest.py # Pytest fixtures │ │ ├── unit/ # Unit tests │ │ ├── integration/ # Integration tests │ │ └── factories/ # Test data factories │ ├── pytest.ini # Pytest config │ └── .coveragerc # Coverage config │ └── package.json # NPM scripts .github/workflows/ ├── pr-unit-tests.yml # PR checks └── nightly-integration-tests.yml # Nightly tests docs/testing/ ├── README.md # Overview ├── unit-testing.md # Unit test guide ├── contributing.md # PR requirements └── SUMMARY.md # This file
When writing new code:
pnpm test:unit before committingWhen reviewing PRs:
Required for every PR:
See contributing.md for detailed guidelines.
Backend:
# Create test file touch tests/unit/test_new_feature.py # Write tests following examples # Run to verify python -m pytest tests/unit/test_new_feature.py -v
Frontend:
# Create test file next to component touch src/components/NewComponent.test.jsx # Write tests following examples # Run to verify pnpm test NewComponent.test.jsx
Frontend: Edit vitest.config.ts
coverage: { thresholds: { lines: 95, // Adjust here functions: 95, branches: 95, statements: 95, } }
Backend: Edit pytest.ini
addopts = --cov-fail-under=95 # Adjust here
OPENAI_API_KEYAWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYAWS_REGION (optional)Install dependencies:
cd webapp pnpm install cd packages/api/user-service pip install -r requirements.txt
Run tests:
cd webapp pnpm test:unit
Check coverage:
pnpm test:coverage
Read the guides:
README.mdunit-testing.mdcontributing.md before your first PRWrite your first test:
docs/testing/Testing infrastructure implemented: January 2025 Documentation version: 1.0