Skip to content

Commit e7d5df8

Browse files
nik-localstackGitHub Copilot
andcommitted
feat(tests): add integration tests for plugins and proxy behavior
Co-authored-by: GitHub Copilot <copilot@github.com>
1 parent c3afe1c commit e7d5df8

10 files changed

Lines changed: 624 additions & 48 deletions

File tree

.actrc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
--container-architecture linux/arm64
2+
-P ubuntu-24.04=catthehacker/ubuntu:act-latest

.github/workflows/tests.yml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
name: Run Tests
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches:
7+
- master
8+
9+
jobs:
10+
tests:
11+
runs-on: ubuntu-24.04
12+
13+
services:
14+
postgres:
15+
image: postgres:16
16+
env:
17+
POSTGRES_USER: postgres
18+
POSTGRES_PASSWORD: postgres
19+
POSTGRES_DB: postgres
20+
ports:
21+
- 5432:5432
22+
options: >-
23+
--health-cmd "pg_isready -U postgres"
24+
--health-interval 10s
25+
--health-timeout 5s
26+
--health-retries 5
27+
28+
env:
29+
E2E_PG_HOST: 127.0.0.1
30+
E2E_PG_PORT: 5432
31+
E2E_PG_USER: postgres
32+
E2E_PG_PASSWORD: postgres
33+
E2E_PG_DB: postgres
34+
35+
steps:
36+
- uses: actions/checkout@v4
37+
38+
- name: Set up Python
39+
uses: actions/setup-python@v5
40+
with:
41+
python-version: "3.13"
42+
43+
- name: Install dependencies
44+
run: |
45+
sudo apt-get update
46+
sudo apt-get install -y postgresql-client
47+
python -m pip install --upgrade pip
48+
pip install -r requirements.txt
49+
pip install pytest pytest-timeout
50+
51+
- name: Run tests
52+
run: |
53+
python -m pytest -vv
54+

Makefile

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,73 @@
11
VENV_DIR ?= .venv
22
VENV_RUN = . $(VENV_DIR)/bin/activate
33
PIP_CMD ?= pip
4+
PYTHON_CMD ?= python
5+
TEST_DEPS ?= pytest pytest-timeout
6+
LINT_DEPS ?= ruff
7+
8+
PG_TEST_CONTAINER ?= pg-proxy-local-tests
9+
PG_TEST_IMAGE ?= postgres:16
10+
PG_TEST_PORT ?= 55432
11+
PG_TEST_USER ?= postgres
12+
PG_TEST_PASSWORD ?= postgres
13+
PG_TEST_DB ?= postgres
14+
ACT_CMD ?= act
15+
ACT_WORKFLOW ?= .github/workflows/tests.yml
16+
ACT_JOB ?= tests
17+
ACT_PULL ?= false
18+
ACT_CONTAINER_ARCH ?= linux/arm64
419

520
usage: ## Show this help
621
@fgrep -h "##" $(MAKEFILE_LIST) | fgrep -v fgrep | sed -e 's/\\$$//' | sed -e 's/##//'
722

823
install: ## Install dependencies in local virtualenv folder
9-
(test `which virtualenv` || $(PIP_CMD) install --user virtualenv) && \
24+
(test `which virtualenv` || $(PIP_CMD) install virtualenv) && \
1025
(test -e $(VENV_DIR) || virtualenv $(VENV_OPTS) $(VENV_DIR)) && \
1126
($(VENV_RUN) && $(PIP_CMD) install --upgrade pip) && \
1227
(test ! -e requirements.txt || ($(VENV_RUN); $(PIP_CMD) install -r requirements.txt))
1328

1429
publish: ## Publish the library to the central PyPi repository
1530
($(VENV_RUN); pip install twine; python ./setup.py sdist && twine upload dist/*)
1631

17-
.PHONY: usage install clean publish test lint
32+
install-test: install ## Install test dependencies in local virtualenv
33+
($(VENV_RUN); $(PIP_CMD) install $(TEST_DEPS))
34+
35+
install-lint: install ## Install lint dependencies in local virtualenv
36+
($(VENV_RUN); $(PIP_CMD) install $(LINT_DEPS))
37+
38+
lint: install-lint ## Format code with ruff
39+
$(VENV_DIR)/bin/ruff format postgresql_proxy tests plugins
40+
41+
test: ## Start local PostgreSQL container and run all tests
42+
@set -euo pipefail; \
43+
cleanup() { docker rm -f $(PG_TEST_CONTAINER) >/dev/null 2>&1 || true; }; \
44+
trap cleanup EXIT INT TERM; \
45+
docker rm -f $(PG_TEST_CONTAINER) >/dev/null 2>&1 || true; \
46+
docker run --name $(PG_TEST_CONTAINER) \
47+
-e POSTGRES_USER=$(PG_TEST_USER) \
48+
-e POSTGRES_PASSWORD=$(PG_TEST_PASSWORD) \
49+
-e POSTGRES_DB=$(PG_TEST_DB) \
50+
-p $(PG_TEST_PORT):5432 \
51+
-d $(PG_TEST_IMAGE) >/dev/null; \
52+
for i in $$(seq 1 45); do \
53+
if docker exec $(PG_TEST_CONTAINER) pg_isready -U $(PG_TEST_USER) >/dev/null 2>&1; then \
54+
echo "PostgreSQL ready on 127.0.0.1:$(PG_TEST_PORT)"; \
55+
break; \
56+
fi; \
57+
sleep 1; \
58+
done; \
59+
if ! docker exec $(PG_TEST_CONTAINER) pg_isready -U $(PG_TEST_USER) >/dev/null 2>&1; then \
60+
echo "PostgreSQL did not become ready in time"; \
61+
exit 1; \
62+
fi; \
63+
E2E_PG_HOST=127.0.0.1 \
64+
E2E_PG_PORT=$(PG_TEST_PORT) \
65+
E2E_PG_USER=$(PG_TEST_USER) \
66+
E2E_PG_PASSWORD=$(PG_TEST_PASSWORD) \
67+
E2E_PG_DB=$(PG_TEST_DB) \
68+
$(VENV_DIR)/bin/$(PYTHON_CMD) -m pytest -vv
69+
70+
test-act: ## Run the CI test workflow locally with act
71+
$(ACT_CMD) -W $(ACT_WORKFLOW) -j $(ACT_JOB) --pull=$(ACT_PULL) --container-architecture $(ACT_CONTAINER_ARCH)
72+
73+
.PHONY: usage install install-test install-lint clean publish test test-act lint

README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,38 @@ If you want to test it, do this. Otherwise scroll down for instructions on how t
7878
- add stop() method to proxy; refactor logging
7979
- v0.0.2
8080
- fix socket file descriptors under Linux
81+
82+
83+
84+
## Testing
85+
86+
CI runs tests on Python `3.13`, so use Python `3.13` locally for parity.
87+
88+
Run the full local test suite (starts a disposable PostgreSQL container automatically):
89+
90+
```bash
91+
make test
92+
```
93+
94+
Run the GitHub Actions test workflow locally with [`act`](https://github.com/nektos/act):
95+
96+
On macOS, install `act` with Homebrew:
97+
98+
```bash
99+
brew install act
100+
```
101+
102+
```bash
103+
make test-act
104+
```
105+
106+
Useful overrides for local runs:
107+
108+
```bash
109+
# Refresh images explicitly when needed
110+
make test-act ACT_PULL=true
111+
112+
# Match GitHub runner architecture on Apple Silicon (slower)
113+
make test-act ACT_CONTAINER_ARCH=linux/amd64
114+
```
115+

plugins/tableau_hll/test.py

Lines changed: 0 additions & 34 deletions
This file was deleted.

tests/README.md

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Testing Guide
2+
3+
All tests in this repo require a real PostgreSQL server and are organized at the top level:
4+
5+
- `test_proxy.py`: proxy behavior tests (connection, SSL, hang regressions)
6+
- `test_plugins.py`: plugin integration tests (HLL rewrite behavior)
7+
8+
## Prerequisites
9+
10+
- Python `3.13` (same version as CI)
11+
- Docker (for local disposable PostgreSQL)
12+
- `psql` (`postgresql-client`)
13+
- `openssl` (SSL tests generate a temporary self-signed cert/key at runtime)
14+
- `act` (optional, for local GitHub Actions runs)
15+
16+
Install Python deps in the project virtualenv:
17+
18+
```bash
19+
make install-test
20+
```
21+
22+
## Which command should I use?
23+
24+
- Fastest full local run with disposable Postgres: `make test`
25+
- Run only proxy tests (using your own Postgres): `python -m pytest tests/test_proxy.py -vv`
26+
- Run only plugin tests: `python -m pytest tests/test_plugins.py -vv`
27+
- Run exact CI workflow locally: `make test-act`
28+
29+
## 1) Full local suite (recommended)
30+
31+
`make test` starts a temporary PostgreSQL container, waits for readiness, sets DB env vars, then runs:
32+
33+
```bash
34+
python -m pytest -vv
35+
```
36+
37+
Use it when you want one command that matches normal contributor workflow.
38+
39+
```bash
40+
make test
41+
```
42+
43+
## 2) DB-backed proxy tests against an existing PostgreSQL
44+
45+
If you already have PostgreSQL running, set connection env vars and run only proxy tests:
46+
47+
```bash
48+
export E2E_PG_HOST=127.0.0.1
49+
export E2E_PG_PORT=5432
50+
export E2E_PG_USER=postgres
51+
export E2E_PG_PASSWORD=postgres
52+
export E2E_PG_DB=postgres
53+
python -m pytest tests/test_proxy.py -vv
54+
```
55+
56+
If PostgreSQL is not reachable, tests fail fast at startup.
57+
58+
## 3) Plugin integration tests
59+
60+
```bash
61+
python -m pytest tests/test_plugins.py -vv
62+
```
63+
64+
Requires PostgreSQL to be running with the `E2E_PG_*` env vars set (see section 2).
65+
66+
## 4) Run the GitHub workflow locally (`act`)
67+
68+
```bash
69+
make test-act
70+
```
71+
72+
Useful overrides:
73+
74+
```bash
75+
# Refresh workflow images
76+
make test-act ACT_PULL=true
77+
78+
# Match GitHub x86_64 runner architecture (slower on Apple Silicon)
79+
make test-act ACT_CONTAINER_ARCH=linux/amd64
80+
```

tests/conftest.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import os
2+
3+
import psycopg2
4+
import pytest
5+
6+
7+
@pytest.fixture(scope="session")
8+
def postgres_settings():
9+
"""PostgreSQL connection settings from environment or defaults."""
10+
return {
11+
"host": os.environ.get("E2E_PG_HOST", "127.0.0.1"),
12+
"port": int(os.environ.get("E2E_PG_PORT", "5432")),
13+
"user": os.environ.get("E2E_PG_USER", "postgres"),
14+
"password": os.environ.get("E2E_PG_PASSWORD", "postgres"),
15+
"dbname": os.environ.get("E2E_PG_DB", "postgres"),
16+
}
17+
18+
19+
@pytest.fixture(scope="session", autouse=True)
20+
def ensure_postgres_available(postgres_settings):
21+
"""Ensure PostgreSQL backend is available before running any tests."""
22+
try:
23+
with psycopg2.connect(
24+
connect_timeout=3, sslmode="disable", **postgres_settings
25+
) as conn:
26+
with conn.cursor() as cur:
27+
cur.execute("SELECT 1")
28+
assert cur.fetchone() == (1,)
29+
except Exception as err: # pragma: no cover - environment dependent
30+
pytest.fail(
31+
f"PostgreSQL backend is required for tests but is not reachable: {err}"
32+
)
33+

tests/test_plugin.py

Lines changed: 0 additions & 12 deletions
This file was deleted.

0 commit comments

Comments
 (0)