22347bd549
Adds tests/integration/: an optional real-Gitea suite, skipped by default, enabled only by GITEA_INTEGRATION=1. - docker-compose.yml pins gitea/gitea:1.22.6 (disposable container, port 3003) - gitea-integration helper: up (wait-ready) / token (test-only admin, token to stdout only) / down (removes container + volume) - conftest.py: session fixtures; unique disposable seed repo (inttest-<hex>) created via API and deleted on teardown - test_gitea_live.py (6 tests, via shared api_request/api_get_all client): issue pagination multi-page walk + overall limit, PR listing, targeted label add/remove leaves other labels intact, bad-token 401 fails closed without echoing the credential, real 404 payload surfaces as safe redacted error - README + developer-testing-guidelines section 8 updated (planned -> real) Default pytest tests/ -q: 355 passed, 6 skipped (unit suite unchanged, no network). Live verification: 6 passed against the pinned container. No production credentials; token never logged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
61 lines
2.4 KiB
Markdown
61 lines
2.4 KiB
Markdown
# Opt-in Gitea Integration Tests (#66)
|
|
|
|
Real-Gitea integration tests for the shared API client
|
|
(`gitea_auth.api_request` / `api_get_all`). **Skipped by default** — the unit
|
|
suite (`pytest tests/ -q`) stays fast, mocked, and network-free.
|
|
|
|
## What they prove
|
|
|
|
Against a real, disposable Gitea instance:
|
|
|
|
- issue listing + pagination (multi-page walk, overall `limit`)
|
|
- PR listing through the same paginated client
|
|
- targeted label add/remove (one label removed, others untouched)
|
|
- permission denial fails closed (bad token → clear `401` error, token never echoed)
|
|
- real Gitea error payloads surface as safe, redacted `RuntimeError`s
|
|
|
|
## Environment variables
|
|
|
|
| Variable | Meaning |
|
|
|---|---|
|
|
| `GITEA_INTEGRATION=1` | opt-in switch — the suite is skipped without it |
|
|
| `GITEA_INTEGRATION_URL` | base URL (default `http://localhost:3003`) |
|
|
| `GITEA_INTEGRATION_TOKEN` | API token for the **local test** instance |
|
|
|
|
Never point these at a production Gitea and never use production tokens. The
|
|
token is used only in the `Authorization` header; tests assert it does not
|
|
appear in any error output.
|
|
|
|
## Quick start (Docker)
|
|
|
|
```bash
|
|
tests/integration/gitea-integration up
|
|
export GITEA_INTEGRATION_TOKEN="$(tests/integration/gitea-integration token)"
|
|
GITEA_INTEGRATION=1 ./venv/bin/python -m pytest tests/integration/ -q
|
|
tests/integration/gitea-integration down
|
|
```
|
|
|
|
- Image is **pinned** (`gitea/gitea:1.22.6` in `docker-compose.yml`); bump the
|
|
pin deliberately, never `:latest`.
|
|
- `up` waits until `/api/v1/version` answers (60s timeout).
|
|
- `token` idempotently creates a TEST-ONLY admin (`inttest-admin`) inside the
|
|
container and prints a fresh API token to stdout — nothing is written to disk.
|
|
- `down` removes the container **and its volume** (full teardown).
|
|
|
|
An existing local Gitea works too: set `GITEA_INTEGRATION_URL` and a token for
|
|
any account allowed to create/delete its own repos.
|
|
|
|
## Seed data and cleanup
|
|
|
|
- Each session creates one uniquely-named repo (`inttest-<8 hex>`), seeds
|
|
issues/labels/one PR inside it, and deletes the repo on teardown
|
|
(best-effort; a leaked repo is disposable and obvious).
|
|
- Nothing outside the seed repo is touched; the suite never mutates
|
|
pre-existing repos, users, or instance settings.
|
|
|
|
## Relationship to the unit suite
|
|
|
|
Unit tests remain the default and must stay mocked. Add an integration test
|
|
only for behavior that genuinely depends on a real server (pagination
|
|
metadata, permission semantics, live error payloads).
|