# Testing

**Version**: 2.4.9
**Last Updated**: April 5, 2026

This project uses **pytest** (backend) and **Vitest** (frontend) for comprehensive test coverage. On Windows, batch runners are provided for convenience and generate both:
- JUnit XML (`.xml`)
- Styled HTML report (`.html`)

Before running the quality gate or local tests, install contributor tooling:

```bash
pip install -r requirements-dev.txt
python scripts/install_local_hooks.py
```

Runtime dependencies stay in `requirements.txt`; optional AI/vector dependencies stay in `requirements-vector.txt`. See `docs/DEPENDENCY_POLICY.md` for the canonical dependency policy.

Reports are written to:
- `tests/__reports__/`

Open the index:
- `tests/__reports__/index.html`

## Test Coverage

### Backend (Python)
- Core functionality (index, search, routes)
- Metadata extraction (ExifTool, FFprobe, geninfo)
- Database operations (schema, migrations)
- Security (CSRF, auth, path validation)
- Feature tests (collections, batch ZIP, viewer)
- Regression tests

### Frontend (JavaScript)
- Vue.js components
- API client
- UI utilities
- Event handling
- Drag & drop

---

## Quick Commands

### All Tests (Cross-Platform)
```bash
# From repo root
python -m pytest -q

# With verbose output
python -m pytest -v

# With coverage
pytest tests/ --cov=mjr_am_backend --cov-report=html
```

### Single Test File
```bash
python -m pytest tests/core/test_routes.py -v
```

### Single Test Folder
```bash
python -m pytest tests/metadata/ -v
```

### Single Test Function
```bash
python -m pytest tests/core/test_routes.py::test_routes -v
```

### Frontend Tests
```bash
# Run JavaScript tests
npm run test:js

# Watch mode
npm run test:js:watch
```

### Canonical Quality Gate
```bash
# Full repo gate
python scripts/run_quality_gate.py

# Fast Python-only gate (useful before pushing)
python scripts/run_quality_gate.py --python-only --skip-tests

# Tox wrapper for the fast Python-only gate
tox -e quality
```

The canonical gate runs encoding/BOM checks, `ruff`, `mypy`, `bandit`, `pip-audit`, xenon/radon complexity checks, backend tests, frontend tests, and `npm audit`. The `pip-audit` step audits `requirements.txt` directly so the local package itself does not need to be published on PyPI for the gate to pass. CI uses the same script for the Python quality job so local and CI behavior stay aligned.

The Python coverage gate currently enforces a minimum combined backend/shared coverage threshold of `60%`, which gives the CI pipeline a regression floor without making legacy cleanup block unrelated work.

During the migration to stricter quality thresholds, `ruff` is enforced with autofix on commit for changed Python files, while `mypy` and the changed-file complexity gate run on pre-push. The changed-file complexity threshold is aligned locally with the CI limit of `25`, and repository-wide hygiene, security, and complexity checks continue to run across the repo.

## Local Hooks

This repository ships local Git hooks via `pre-commit`:

```bash
python scripts/install_local_hooks.py
```

Installed behavior:
- `pre-commit`: BOM/encoding hygiene, `ruff --fix`, `eslint --fix`, `prettier --write`
- `pre-push`: mandatory `mypy` plus `scripts/run_changed_quality_gate.py`

The changed-file quality gate is also runnable manually:

```bash
python scripts/run_changed_quality_gate.py
```

For frontend tests in the Node Vitest environment, prefer the shared helpers in `ui/tests/helpers/vitestEnvironment.mjs`. Team rule: use partial Vue mocks by default, based on the real `vue` module, instead of full replacement mocks.

## Batch runners (Windows)

From the repo root:

- Full suite: `run_tests.bat` (delegates to `tests/run_tests_all.bat`)

Category runners:

- `tests/config/run_tests_config.bat`
- `tests/core/run_tests_core.bat`
- `tests/database/run_tests_database.bat`
- `tests/features/run_tests_features.bat`
- `tests/metadata/run_tests_metadata.bat`
- `tests/rating_tags/run_tests_rating_tags.bat`
- `tests/regressions/run_tests_regressions.bat`

All batch runners support `/nopause` for non-interactive runs:

```bat
run_tests.bat /nopause
```

## Test artifacts (DB/WAL/SHM)

Some tests create SQLite files. Pytest temp files are stored under:
- `tests/__pytest_tmp__/`

This includes `*.db`, `*.db-wal`, `*.db-shm`, and other runtime artifacts.

## Parser samples (metadata extraction)

`tests/metadata/test_parser_folder_scan.py` scans **every file** under:
- `tests/parser/` (recursive)

If you don't want to commit large samples, you can point the test to an external folder:

```powershell
$env:MJR_TEST_PARSER_DIR = "C:\path\to\parser"
python -m pytest tests/metadata/test_parser_folder_scan.py -q
```
