Testing
Testing Guide¶
Complete guide to testing in TrikuSec.
Test Structure¶
All tests use pytest (not Django's unittest):
src/api/tests.py- Unit tests for API endpointssrc/api/tests_integration.py- Integration testssrc/api/tests_middleware.py- Middleware testssrc/api/tests_policy_security.py- Policy security testssrc/frontend/tests_e2e.py- End-to-end tests (Playwright)src/conftest.py- Shared pytest fixturessrc/frontend/conftest.py- E2E test fixtures
Running Tests¶
All Tests¶
Unit Tests Only¶
docker compose -f docker-compose.dev.yml --profile test run --rm test pytest -m "not integration and not e2e" -v
Note: E2E tests are automatically skipped if Playwright is not available. The -m "not e2e" marker explicitly excludes them for clarity.
Integration Tests Only¶
E2E Tests Only¶
E2E tests require Playwright and must be run in the test-e2e service:
See E2E Testing Documentation for detailed information.
Specific Test File¶
Specific Test¶
docker compose -f docker-compose.dev.yml --profile test run --rm test pytest api/tests.py::TestUploadReport::test_upload_report_valid_license_new_device -v
With Coverage¶
docker compose -f docker-compose.dev.yml --profile test run --rm test pytest --cov=api --cov=frontend --cov-report=html --cov-report=term-missing
Test Types¶
Unit Tests¶
Test individual components in isolation:
- API endpoints
- Models
- Forms
- Utilities
Integration Tests¶
Test end-to-end workflows:
- Lynis report upload
- License validation
- Policy compliance
Middleware Tests¶
Test custom middleware:
- Rate limiting
- Security headers
- Error handling
E2E Tests¶
Test complete user workflows in a real browser:
- Frontend interactions
- Form submissions
- Sidebar state management
- User flows
See E2E Testing Documentation for details.
Test Fixtures¶
Fixtures are defined in src/conftest.py:
license_key- Sample license keydevice- Sample devicelynis_report- Mock Lynis report data
Writing Tests¶
Example Unit Test¶
import pytest
from api.views import upload_report
def test_upload_report_valid_license(client, license_key):
response = client.post('/api/lynis/upload/', {
'licensekey': license_key.licensekey,
'hostid': 'test-host',
'data': 'base64-encoded-data'
})
assert response.status_code == 200
Example Integration Test¶
@pytest.mark.integration
def test_lynis_workflow(client, license_key):
# Upload report
response = client.post('/api/lynis/upload/', {...})
assert response.status_code == 200
# Check device created
device = Device.objects.get(hostid='test-host')
assert device is not None
Test Database¶
The test container automatically: - Runs migrations before tests - Uses a separate test database - Cleans up after tests
Continuous Integration¶
Tests run automatically on:
- Push to main or develop branches
- Pull requests
CI runs three separate test jobs: 1. Unit Tests - Fast unit tests (excludes integration and E2E tests) 2. Integration Tests - End-to-end API workflows with Lynis client 3. E2E Tests - Browser-based frontend tests with Playwright
See .github/workflows/test.yml for CI configuration.
Best Practices¶
- Isolation - Each test should be independent
- Fixtures - Use fixtures for common test data
- Naming - Use descriptive test names
- Coverage - Aim for high test coverage
- Speed - Keep tests fast
Next Steps¶
- Development Setup - Development environment
- Contributing - Contribution guidelines