How to: Install heavier extras so tests needing torch or faiss work:
ALPHA_FACTORY_FULL=1 python check_env.py --auto-install
```
The `run_tests` helper automatically executes `python check_env.py --auto-install`
before running `pytest`. When offline, set `WHEELHOUSE` or pass
`--wheelhouse
` so packages install from the local wheel cache. The
repository ships with a `wheels/` directory that can be used as this cache.
The full test suite relies on optional packages including `numpy`, `torch`,
`pandas`, `prometheus_client`, `gymnasium`, `playwright`, `httpx`, `uvicorn`,
`git`, `hypothesis` and `requests_mock`.

Tests that depend on optional heavy packages skip automatically when those
libraries are missing. Set environment variables like `SKIP_WEBKIT_TESTS=1`
or `PYTEST_NET_OFF=1` to bypass browser or network tests if the necessary
dependencies aren't installed.

#### Wheelhouse Setup

Tests install packages from PyPI unless a local wheelhouse is provided. Build
one from `requirements.lock` and point `WHEELHOUSE` to it before verifying the
environment and running the suite:

```bash
mkdir -p wheels
pip wheel -r requirements.lock -w wheels
export WHEELHOUSE=$(pwd)/wheels
python check_env.py --auto-install --wheelhouse "$WHEELHOUSE"
WHEELHOUSE="$WHEELHOUSE" pytest -q
```

If network access is unavailable and the variable is unset these commands fail
instead of falling back to PyPI.

#### Offline or Restricted Environments

Run `./scripts/build_offline_wheels.sh` to populate a wheelhouse on a
machine with internet access, then set `WHEELHOUSE=
` before executing
the tests so dependencies install from this local cache.
If `npx playwright install` fails to download WebKit, set `SKIP_WEBKIT_TESTS=1`
so browser checks skip gracefully.

#### Test Runtime

Running `pytest` may take several minutes on the first run while caches are
created. Execute the suite in verbose mode to see ongoing progress:

```bash
pytest -vv
```

After completion `pytest` prints a summary such as `### passed in 120.00s`.

The suite includes `tests/test_api_rate_limit.py` which spins up
`api_server.app` with `API_RATE_LIMIT=2` and verifies that exceeding the
limit returns HTTP `429`.