Skip to content

Commit 4313838

Browse files
Add Python Tests
1 parent 4227a5d commit 4313838

File tree

22 files changed

+919
-77
lines changed

22 files changed

+919
-77
lines changed

.github/workflows/python-tests.yml

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
name: Python Tests
22

33
on:
4+
workflow_dispatch:
45
push:
56
branches: [ main ]
67
pull_request:
78
branches: [ main ]
89

910
permissions:
1011
contents: read
12+
checks: write
13+
pull-requests: write
1114

1215
jobs:
1316
test:
@@ -17,14 +20,53 @@ jobs:
1720
python-version: [ '3.12', '3.13' ]
1821
steps:
1922
- uses: actions/checkout@v4
23+
2024
- name: Set up Python ${{ matrix.python-version }}
2125
uses: actions/setup-python@v5
2226
with:
2327
python-version: ${{ matrix.python-version }}
28+
2429
- name: Install dependencies
2530
run: |
2631
python -m pip install --upgrade pip
2732
pip install -r requirements.txt
28-
- name: Run tests
33+
34+
- name: Install pytest and pytest-cov
35+
run: |
36+
pip install pytest pytest-cov
37+
38+
# Run tests with continue-on-error so that coverage and PR comments are always published.
39+
# The final step will explicitly fail the job if any test failed, ensuring PRs cannot be merged with failing tests.
40+
- name: Run pytest with coverage and generate JUnit XML
41+
run: |
42+
PYTHONPATH=$(pwd) COVERAGE_FILE=tests/python/.coverage-${{ matrix.python-version }} pytest --cov=shared/python --cov-config=tests/python/.coveragerc --cov-report=html:tests/python/htmlcov-${{ matrix.python-version }} --junitxml=tests/python/junit-${{ matrix.python-version }}.xml tests/python/
43+
continue-on-error: true
44+
45+
- name: Upload coverage HTML report
46+
uses: actions/upload-artifact@v4
47+
with:
48+
name: coverage-html-${{ matrix.python-version }}
49+
path: tests/python/htmlcov-${{ matrix.python-version }}/
50+
51+
- name: Upload JUnit test results
52+
uses: actions/upload-artifact@v4
53+
with:
54+
name: junit-results-${{ matrix.python-version }}
55+
path: tests/python/junit-${{ matrix.python-version }}.xml
56+
57+
- name: Publish Unit Test Results to PR
58+
if: always()
59+
uses: EnricoMi/publish-unit-test-result-action@v2
60+
with:
61+
files: tests/python/junit-${{ matrix.python-version }}.xml
62+
comment_title: Python ${{ matrix.python-version }} Test Results
63+
64+
# Explicitly fail the job if any test failed (so PRs cannot be merged with failing tests).
65+
# This runs after all reporting steps, meaning coverage and PR comments are always published.
66+
- name: Fail if tests failed
67+
if: always()
2968
run: |
30-
python -m unittest discover shared/python-tests
69+
if grep -q 'failures="[1-9]' tests/python/junit-${{ matrix.python-version }}.xml; then
70+
echo "::error ::Unit tests failed. See above for details."
71+
exit 1
72+
fi

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,8 @@ labs-in-progress/
2525

2626
# Exclude sensitive or generated files
2727
.env
28+
29+
30+
# Coverage data and reports
31+
.coverage
32+
tests/python/htmlcov/

README.md

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Azure API Management Samples
22

3+
[![Python Tests](https://github.com/Azure-Samples/Apim-Samples/actions/workflows/python-tests.yml/badge.svg?branch=main)](https://github.com/Azure-Samples/Apim-Samples/actions/workflows/python-tests.yml)
4+
35
This repository provides a playground to safely experiment with and learn Azure API Management (APIM) policies in various architectures.
46

57
## Objectives
@@ -87,11 +89,53 @@ The repo uses the bicep linter and has rules defined in `bicepconfig.json`. See
8789

8890
We welcome contributions! Please consider forking the repo and creating issues and pull requests to share your samples. Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details. Thank you!
8991

90-
### Testing
9192

92-
Python modules and files in the `shared` folder are supported with tests in the `python-tests` folder. They can be invoked manually via `pytest -v` but are also run upon push to GitHub origin. The `pytest.ini` file in the root sets up the test structure.
93+
### Testing & Code Coverage
94+
95+
Python modules in `shared/python` are covered by comprehensive unit tests located in `tests/python`. All tests use [pytest](https://docs.pytest.org/) and leverage modern pytest features, including custom markers for unit and HTTP tests.
96+
97+
#### Running Tests Locally
98+
99+
- **PowerShell (Windows):**
100+
- Run all tests with coverage: `./tests/python/run_tests.ps1`
101+
- **Shell (Linux/macOS):**
102+
- Run all tests with coverage: `./tests/python/run_tests.sh`
103+
104+
Both scripts:
105+
- Run all tests in `tests/python` using pytest
106+
- Generate a code coverage report (HTML output in `tests/python/htmlcov`)
107+
- Store the raw coverage data in `tests/python/.coverage`
108+
109+
You can also run tests manually and see details in the console:
110+
```sh
111+
pytest -v --cov=shared/python --cov-report=html:tests/python/htmlcov --cov-report=term tests/python
112+
```
113+
114+
#### Viewing Coverage Reports
115+
116+
After running tests, open `tests/python/htmlcov/index.html` in your browser to view detailed coverage information.
117+
118+
#### Pytest Markers
119+
120+
- `@pytest.mark.unit` — marks a unit test
121+
- `@pytest.mark.http` — marks a test involving HTTP/mocking
122+
123+
Markers are registered in `pytest.ini` to avoid warnings.
124+
125+
#### Continuous Integration (CI)
126+
127+
On every push or pull request, GitHub Actions will:
128+
- Install dependencies
129+
- Run all Python tests in `tests/python` with coverage
130+
- Store the `.coverage` file in `tests/python`
131+
- Upload the HTML coverage report as a workflow artifact for download
132+
133+
#### Additional Notes
134+
135+
- The `.gitignore` is configured to exclude coverage output and artifacts.
136+
- All test and coverage features work both locally and in CI.
93137

94-
Additional information can be found [here](# https://docs.pytest.org/en/8.2.x/).
138+
For more details on pytest usage, see the [pytest documentation](https://docs.pytest.org/en/8.2.x/).
95139

96140
---
97141

infrastructure/afd-apim/clean-up.ipynb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919
"from apimtypes import INFRASTRUCTURE\n",
2020
"\n",
2121
"deployment = INFRASTRUCTURE.AFD_APIM_PE\n",
22-
"index = 1\n",
22+
"indexes = [1]\n",
2323
"\n",
24-
"utils.cleanup_resources(deployment, utils.get_infra_rg_name(deployment, index))"
24+
"utils.cleanup_infra_deployments(deployment, indexes)"
2525
]
2626
}
2727
],

infrastructure/apim-aca/clean-up.ipynb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919
"from apimtypes import INFRASTRUCTURE\n",
2020
"\n",
2121
"deployment = INFRASTRUCTURE.APIM_ACA\n",
22-
"index = 1\n",
22+
"indexes = [1]\n",
2323
"\n",
24-
"utils.cleanup_resources(deployment, utils.get_infra_rg_name(deployment, index))"
24+
"utils.cleanup_infra_deployments(deployment, indexes)"
2525
]
2626
}
2727
],

infrastructure/simple-apim/clean-up.ipynb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919
"from apimtypes import INFRASTRUCTURE\n",
2020
"\n",
2121
"deployment = INFRASTRUCTURE.SIMPLE_APIM\n",
22-
"index = 1\n",
22+
"indexes = [1]\n",
2323
"\n",
24-
"utils.cleanup_resources(deployment, utils.get_infra_rg_name(deployment, index))"
24+
"utils.cleanup_infra_deployments(deployment, indexes)"
2525
]
2626
}
2727
],
@@ -41,7 +41,7 @@
4141
"name": "python",
4242
"nbconvert_exporter": "python",
4343
"pygments_lexer": "ipython3",
44-
"version": "3.12.9"
44+
"version": "3.12.10"
4545
}
4646
},
4747
"nbformat": 4,

pytest.ini

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

requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22

33
requests
44
setuptools
5-
pytest
5+
pytest
6+
pytest-cov

shared/python-tests/__init__.py

Lines changed: 0 additions & 1 deletion
This file was deleted.

shared/python-tests/test_apimtypes.py

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

0 commit comments

Comments
 (0)