Skip to content

Commit 1d4ba08

Browse files
ChrisPC-39Sebastiancrivetimihai
authored
Asnyc testing (#604)
* Add new Makefile targets Signed-off-by: Sebastian <[email protected]> * Add new config for make targets Signed-off-by: Sebastian <[email protected]> * Add new async testing files Signed-off-by: Sebastian <[email protected]> * Async safety unit test Signed-off-by: Sebastian <[email protected]> * Add github workflow Signed-off-by: Sebastian <[email protected]> * Update documentation Signed-off-by: Sebastian <[email protected]> * Fix yamlint issues Signed-off-by: Sebastian <[email protected]> * Add asyncpg module in workflow Signed-off-by: Sebastian <[email protected]> * Remove installation dependency in workflow Signed-off-by: Sebastian <[email protected]> * Update MANIFEST.in Signed-off-by: Sebastian <[email protected]> * Install dependency for async Signed-off-by: Sebastian <[email protected]> * Fix async testing Signed-off-by: Sebastian <[email protected]> * Remove reports Signed-off-by: Sebastian <[email protected]> * Pylint mcpgateway/bootstrap_db.py Signed-off-by: Sebastian <[email protected]> * Add dev dependencies Signed-off-by: Sebastian <[email protected]> * Relint Signed-off-by: Mihai Criveti <[email protected]> * Rebase, lint and fix pylint issues Signed-off-by: Mihai Criveti <[email protected]> * Rebase, lint and fix pylint issues Signed-off-by: Mihai Criveti <[email protected]> * Cleanup manifest.in Signed-off-by: Mihai Criveti <[email protected]> * Cleanup manifest.in Signed-off-by: Mihai Criveti <[email protected]> * Cleanup manifest.in Signed-off-by: Mihai Criveti <[email protected]> * Cleanup manifest.in Signed-off-by: Mihai Criveti <[email protected]> --------- Signed-off-by: Sebastian <[email protected]> Signed-off-by: Mihai Criveti <[email protected]> Co-authored-by: Sebastian <[email protected]> Co-authored-by: Mihai Criveti <[email protected]>
1 parent 6a43a86 commit 1d4ba08

23 files changed

+1118
-83
lines changed
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# ===============================================================
2+
# 🔄 Async Safety & Performance Testing
3+
# ===============================================================
4+
#
5+
# - runs the async safety and performance tests across multiple Python versions
6+
# - includes linting, debugging, profiling, benchmarking, and validation
7+
# - uploads the test artifacts as build artifacts
8+
# - performs a performance regression check
9+
# ---------------------------------------------------------------
10+
11+
name: Tests & Coverage
12+
13+
on:
14+
push:
15+
branches: ["main"]
16+
pull_request:
17+
branches: ["main"]
18+
# schedule:
19+
# - cron: '42 3 * * 1' # Monday 03:42 UTC
20+
21+
permissions:
22+
contents: write # needed *only* if the badge-commit step is enabled
23+
checks: write
24+
actions: read
25+
26+
jobs:
27+
async-testing:
28+
name: 🔄 Async Safety & Performance Testing
29+
runs-on: ubuntu-latest
30+
needs: [test]
31+
32+
strategy:
33+
fail-fast: false
34+
matrix:
35+
python: ["3.11", "3.12"]
36+
37+
steps:
38+
- name: ⬇️ Checkout source
39+
uses: actions/checkout@v4
40+
with:
41+
fetch-depth: 1
42+
43+
- name: 🐍 Setup Python ${{ matrix.python }}
44+
uses: actions/setup-python@v5
45+
with:
46+
python-version: ${{ matrix.python }}
47+
cache: pip
48+
49+
- name: 📦 Install dependencies
50+
run: |
51+
python -m pip install --upgrade pip
52+
pip install -e .[dev]
53+
pip install flake8-async flake8-bugbear pytest-asyncio snakeviz aiomonitor
54+
55+
- name: 🔍 Run async linting
56+
run: |
57+
make async-lint
58+
59+
- name: 🐛 Run async debug tests
60+
run: |
61+
make async-debug
62+
63+
- name: 📊 Generate performance profiles
64+
run: |
65+
make profile
66+
67+
- name: ⚡ Run async benchmarks
68+
run: |
69+
make async-benchmark
70+
71+
- name: ✅ Validate async patterns
72+
run: |
73+
make async-validate
74+
75+
- name: 📎 Upload async test artifacts
76+
uses: actions/upload-artifact@v4
77+
with:
78+
name: async-test-results
79+
path: |
80+
async_testing/reports/
81+
async_testing/profiles/
82+
retention-days: 30
83+
84+
- name: 📈 Performance regression check
85+
run: |
86+
python async_testing/check_regression.py \
87+
--current async_testing/profiles/latest.prof \
88+
--baseline async_testing/profiles/baseline.prof \
89+
--threshold 20 # 20% regression threshold

.github/workflows/pytest.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ jobs:
6565
python3 -m pip install --upgrade pip
6666
# install the project itself in *editable* mode so tests import the same codebase
6767
# and pull in every dev / test extra declared in pyproject.toml
68-
pip install -e .[dev]
68+
pip install -e .[dev,asyncpg]
6969
# belt-and-braces - keep the core test tool-chain pinned here too
7070
pip install pytest pytest-cov pytest-asyncio coverage[toml]
7171

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
CLAUDE.local.md
2+
.aider*
3+
.scannerwork
14
llms-full.txt
25
aider*
36
.aider*

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ pytest -m "not slow"
228228
# To test everything:
229229

230230
make autoflake isort black pre-commit
231-
make interrogate doctest test smoketest lint-web flake8 bandit pylint
231+
make doctest test htmlcov smoketest lint-web flake8 bandit interrogate pylint verify
232232

233233
# Rules
234234
- When using git commit always add a -s to sign commits

MANIFEST.in

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ include *.yml
2727
include *.json
2828
include *.sh
2929
include *.txt
30+
recursive-include async_testing *.py
31+
recursive-include async_testing *.yaml
3032

3133
# 3️⃣ Tooling/lint configuration dot-files (explicit so they're not lost)
3234
include .env.make
@@ -73,7 +75,8 @@ prune *.egg-info
7375
prune charts
7476
prune k8s
7577
prune .devcontainer
76-
78+
exclude CLAUDE.*
79+
exclude llms-full.txt
7780

7881
# Exclude deployment, mcp-servers and agent_runtimes
7982
prune deployment

Makefile

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3705,6 +3705,97 @@ pip-audit: ## 🔒 Audit Python dependencies for CVEs
37053705
python3 -m pip install --quiet --upgrade pip-audit && \
37063706
pip-audit --strict || true"
37073707

3708+
3709+
3710+
## --------------------------------------------------------------------------- ##
3711+
## Async Code Testing and Performance Profiling
3712+
## --------------------------------------------------------------------------- ##
3713+
.PHONY: async-test async-lint profile async-monitor async-debug profile-serve
3714+
3715+
ASYNC_TEST_DIR := async_testing
3716+
PROFILE_DIR := $(ASYNC_TEST_DIR)/profiles
3717+
REPORTS_DIR := $(ASYNC_TEST_DIR)/reports
3718+
VENV_PYTHON := $(VENV_DIR)/bin/python
3719+
3720+
async-test: async-lint async-debug
3721+
@echo "🔄 Running comprehensive async safety tests..."
3722+
@mkdir -p $(REPORTS_DIR)
3723+
@PYTHONASYNCIODEBUG=1 $(VENV_PYTHON) -m pytest \
3724+
tests/ \
3725+
--asyncio-mode=auto \
3726+
--tb=short \
3727+
--junitxml=$(REPORTS_DIR)/async-test-results.xml \
3728+
-v
3729+
3730+
async-lint:
3731+
@echo "🔍 Running async-aware linting..."
3732+
@$(VENV_DIR)/bin/ruff check mcpgateway/ tests/ \
3733+
--select=F,E,B,ASYNC \
3734+
--output-format=github
3735+
@$(VENV_DIR)/bin/flake8 mcpgateway/ tests/ \
3736+
--extend-select=B,ASYNC \
3737+
--max-line-length=100
3738+
@$(VENV_DIR)/bin/mypy mcpgateway/ \
3739+
--warn-unused-coroutine \
3740+
--strict
3741+
3742+
profile:
3743+
@echo "📊 Generating async performance profiles..."
3744+
@mkdir -p $(PROFILE_DIR)
3745+
@$(VENV_PYTHON) $(ASYNC_TEST_DIR)/profiler.py \
3746+
--scenarios websocket,database,mcp_calls \
3747+
--output $(PROFILE_DIR) \
3748+
--duration 60
3749+
@echo "🌐 Starting SnakeViz server..."
3750+
@$(VENV_DIR)/bin/snakeviz $(PROFILE_DIR)/combined_profile.prof \
3751+
--server --port 8080
3752+
3753+
profile-serve:
3754+
@echo "🌐 Starting SnakeViz profile server..."
3755+
@$(VENV_DIR)/bin/snakeviz $(PROFILE_DIR) \
3756+
--server --port 8080 --hostname 0.0.0.0
3757+
3758+
async-monitor:
3759+
@echo "👁️ Starting aiomonitor for live async debugging..."
3760+
@$(VENV_PYTHON) $(ASYNC_TEST_DIR)/monitor_runner.py \
3761+
--webui_port 50101 \
3762+
--console_port 50102 \
3763+
--host localhost \
3764+
--console-enabled
3765+
3766+
async-debug:
3767+
@echo "🐛 Running async tests with debug mode..."
3768+
@PYTHONASYNCIODEBUG=1 $(VENV_PYTHON) -X dev \
3769+
-m pytest tests/ \
3770+
--asyncio-mode=auto \
3771+
--capture=no \
3772+
-v
3773+
3774+
async-benchmark:
3775+
@echo "⚡ Running async performance benchmarks..."
3776+
@$(VENV_PYTHON) $(ASYNC_TEST_DIR)/benchmarks.py \
3777+
--output $(REPORTS_DIR)/benchmark-results.json \
3778+
--iterations 1000
3779+
3780+
profile-compare:
3781+
@echo "📈 Comparing performance profiles..."
3782+
@$(VENV_PYTHON) $(ASYNC_TEST_DIR)/profile_compare.py \
3783+
--baseline $(PROFILE_DIR)/combined_profile.prof \
3784+
--current $(PROFILE_DIR)/mcp_calls_profile.prof \
3785+
--output $(REPORTS_DIR)/profile-comparison.json
3786+
3787+
async-validate:
3788+
@echo "✅ Validating async code patterns..."
3789+
@$(VENV_PYTHON) $(ASYNC_TEST_DIR)/async_validator.py \
3790+
--source mcpgateway/ \
3791+
--report $(REPORTS_DIR)/async-validation.json
3792+
3793+
async-clean:
3794+
@echo "🧹 Cleaning async testing artifacts..."
3795+
@rm -rf $(PROFILE_DIR)/* $(REPORTS_DIR)/*
3796+
@pkill -f "aiomonitor" || true
3797+
@pkill -f "snakeviz" || true
3798+
37083799
## --------------------------------------------------------------------------- ##
37093800
## Gitleaks (Go binary - separate installation)
37103801
## --------------------------------------------------------------------------- ##

0 commit comments

Comments
 (0)