Skip to content

Commit 0bb9e71

Browse files
authored
Merge pull request #32 from Jsweb-Tech/tests/pytest
Tests: Add comprehensive pytest testing infrastructure for jsweb framework
2 parents 6c45301 + 58393d7 commit 0bb9e71

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+4772
-1798
lines changed

.coveragerc

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
[run]
2+
source = jsweb
3+
branch = True
4+
omit =
5+
*/tests/*
6+
*/test_*.py
7+
*/__pycache__/*
8+
*/venv/*
9+
*/.venv/*
10+
setup.py
11+
12+
[report]
13+
precision = 2
14+
show_missing = True
15+
skip_covered = False
16+
exclude_lines =
17+
pragma: no cover
18+
def __repr__
19+
raise AssertionError
20+
raise NotImplementedError
21+
if __name__ == .__main__.:
22+
if TYPE_CHECKING:
23+
if typing.TYPE_CHECKING:
24+
@abstractmethod
25+
@abc.abstractmethod
26+
pass
27+
...
28+
except ImportError:
29+
except KeyboardInterrupt:
30+
31+
[html]
32+
directory = htmlcov
33+
34+
[xml]
35+
output = coverage.xml

.github/workflows/tests.yml

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
name: Tests
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
- develop
8+
pull_request:
9+
branches:
10+
- main
11+
- develop
12+
13+
jobs:
14+
test:
15+
runs-on: ubuntu-latest
16+
strategy:
17+
matrix:
18+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
19+
fail-fast: false
20+
21+
steps:
22+
- name: Checkout code
23+
uses: actions/checkout@v4
24+
25+
- name: Set up Python ${{ matrix.python-version }}
26+
uses: actions/setup-python@v5
27+
with:
28+
python-version: ${{ matrix.python-version }}
29+
cache: "pip"
30+
31+
- name: Install dependencies
32+
run: |
33+
python -m pip install --upgrade pip setuptools wheel
34+
pip install -e ".[dev]"
35+
36+
- name: Run pytest with coverage
37+
run: |
38+
pytest Tests/ -v --cov=jsweb --cov-report=xml --cov-report=html --cov-report=term-missing
39+
40+
- name: Upload coverage to Codecov
41+
uses: codecov/codecov-action@v4
42+
with:
43+
files: ./coverage.xml
44+
flags: unittests
45+
name: codecov-umbrella
46+
fail_ci_if_error: false
47+
verbose: true
48+
49+
- name: Archive coverage reports
50+
if: always()
51+
uses: actions/upload-artifact@v4
52+
with:
53+
name: coverage-report-py${{ matrix.python-version }}
54+
path: htmlcov/
55+
56+
lint:
57+
runs-on: ubuntu-latest
58+
steps:
59+
- name: Checkout code
60+
uses: actions/checkout@v4
61+
62+
- name: Set up Python
63+
uses: actions/setup-python@v5
64+
with:
65+
python-version: "3.11"
66+
cache: "pip"
67+
68+
- name: Install dependencies
69+
run: |
70+
python -m pip install --upgrade pip
71+
pip install -e ".[dev]"
72+
73+
- name: Run black (code formatting check)
74+
run: black --check jsweb Tests
75+
76+
- name: Run Ruff (lint & import check)
77+
run: ruff check jsweb Tests
78+
79+
- name: Run mypy (type checking)
80+
run: mypy jsweb --ignore-missing-imports --no-error-summary 2>/dev/null || true
81+
82+
security:
83+
runs-on: ubuntu-latest
84+
steps:
85+
- name: Checkout code
86+
uses: actions/checkout@v4
87+
88+
- name: Set up Python
89+
uses: actions/setup-python@v5
90+
with:
91+
python-version: "3.11"
92+
cache: "pip"
93+
94+
- name: Install dependencies
95+
run: |
96+
python -m pip install --upgrade pip
97+
pip install -e ".[dev]"
98+
99+
- name: Run bandit (security scan)
100+
run: bandit -r jsweb -f json -o bandit-report.json || true
101+
102+
- name: Run safety (dependency check)
103+
run: safety check --json || true

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ This project is licensed under the **MIT License** - see [LICENSE](LICENSE) file
363363
---
364364

365365
<p align="center">
366-
Made with ❤️ by the JsWeb team<br>
366+
Made and Maintained by the JsWeb team<br>
367367
<a href="https://discord.gg/cqg5wgEVhP" target="_blank">Join our Discord community</a> •
368368
<a href="https://github.com/sponsors/Jones-peter" target="_blank">Sponsor us</a>
369369
</p>

Tests/TESTS_GUIDE.md

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
# Pytest Setup and CI/CD Integration
2+
3+
## Local Testing
4+
5+
### Installation
6+
7+
Install development dependencies including pytest:
8+
9+
```bash
10+
pip install -e ".[dev]"
11+
```
12+
13+
### Running Tests
14+
15+
Run all tests:
16+
17+
```bash
18+
pytest
19+
```
20+
21+
Run tests with coverage report:
22+
23+
```bash
24+
pytest --cov=jsweb --cov-report=html
25+
```
26+
27+
Run specific test file:
28+
29+
```bash
30+
pytest Tests/test_routing.py -v
31+
```
32+
33+
Run tests with specific marker:
34+
35+
```bash
36+
pytest -m unit
37+
pytest -m integration
38+
pytest -m slow
39+
```
40+
41+
Run tests matching a pattern:
42+
43+
```bash
44+
pytest -k "test_form" -v
45+
```
46+
47+
### Available Test Markers
48+
49+
- `@pytest.mark.unit` - Unit tests
50+
- `@pytest.mark.integration` - Integration tests
51+
- `@pytest.mark.slow` - Slow running tests
52+
- `@pytest.mark.asyncio` - Async tests
53+
- `@pytest.mark.forms` - Form validation tests
54+
- `@pytest.mark.routing` - Routing tests
55+
- `@pytest.mark.database` - Database tests
56+
- `@pytest.mark.security` - Security tests
57+
58+
### Coverage Reports
59+
60+
After running tests with `--cov`, view the HTML coverage report:
61+
62+
```bash
63+
# On Windows
64+
start htmlcov/index.html
65+
66+
# On Linux/Mac
67+
open htmlcov/index.html
68+
```
69+
70+
## CI/CD Integration
71+
72+
### GitHub Actions Workflow
73+
74+
The project includes a GitHub Actions workflow (`.github/workflows/tests.yml`) that:
75+
76+
1. **Tests Job** - Runs tests on multiple Python versions (3.8-3.12)
77+
- Installs dependencies
78+
- Runs pytest with coverage
79+
- Uploads coverage to Codecov
80+
- Archives coverage reports as artifacts
81+
82+
2. **Lint Job** - Checks code quality
83+
- Black (code formatting)
84+
- isort (import sorting)
85+
- Flake8 (linting)
86+
- MyPy (type checking)
87+
88+
3. **Security Job** - Scans for security issues
89+
- Bandit (security analysis)
90+
- Safety (dependency vulnerabilities)
91+
92+
### Workflow Triggers
93+
94+
The workflow runs automatically on:
95+
96+
- Push to `main` and `develop` branches
97+
- Pull requests to `main` and `develop` branches
98+
99+
### Codecov Integration
100+
101+
Coverage reports are automatically uploaded to Codecov. Add a `CODECOV_TOKEN` secret in your GitHub repository settings for authenticated uploads (optional).
102+
103+
## Configuration Files
104+
105+
### pytest.ini
106+
107+
Main pytest configuration file with:
108+
- Test discovery patterns
109+
- Output options
110+
- Test markers
111+
- Asyncio mode settings
112+
113+
### pyproject.toml
114+
115+
Contains additional pytest and coverage configuration:
116+
- `[tool.pytest.ini_options]` - Pytest settings
117+
- `[tool.coverage.run]` - Coverage collection settings
118+
- `[tool.coverage.report]` - Coverage report options
119+
120+
### .coveragerc
121+
122+
Detailed coverage configuration:
123+
- Source paths
124+
- Files to omit
125+
- Excluded lines
126+
- Report formats
127+
128+
## Pre-commit Hooks
129+
130+
To run tests and linting before commits, set up pre-commit:
131+
132+
```bash
133+
pre-commit install
134+
pre-commit run --all-files
135+
```
136+
137+
The `.pre-commit-config.yaml` should include pytest and other linting tools.
138+
139+
## Tips for Writing Tests
140+
141+
### Basic Test Structure
142+
143+
```python
144+
import pytest
145+
from jsweb import App
146+
147+
@pytest.mark.unit
148+
def test_app_creation():
149+
"""Test that an app can be created."""
150+
app = App(__name__)
151+
assert app is not None
152+
```
153+
154+
### Using Fixtures
155+
156+
```python
157+
@pytest.mark.unit
158+
def test_with_app(app):
159+
"""Test using the app fixture."""
160+
assert app is not None
161+
162+
@pytest.mark.unit
163+
def test_with_config(config):
164+
"""Test using the config fixture."""
165+
assert config.TESTING is True
166+
```
167+
168+
### Async Tests
169+
170+
```python
171+
@pytest.mark.asyncio
172+
async def test_async_operation():
173+
"""Test async code."""
174+
result = await some_async_function()
175+
assert result is not None
176+
```
177+
178+
### Parametrized Tests
179+
180+
```python
181+
@pytest.mark.parametrize("input,expected", [
182+
("test", "test"),
183+
("TEST", "test"),
184+
("Test", "test"),
185+
])
186+
def test_string_lowercase(input, expected):
187+
"""Test string lowercasing with multiple inputs."""
188+
assert input.lower() == expected
189+
```
190+
191+
## Troubleshooting
192+
193+
### ImportError: No module named 'jsweb'
194+
195+
Install the package in development mode:
196+
197+
```bash
198+
pip install -e .
199+
```
200+
201+
### Coverage not showing results
202+
203+
Make sure to use:
204+
205+
```bash
206+
pytest --cov=jsweb
207+
```
208+
209+
### Tests not being discovered
210+
211+
Check that test files follow the pattern: `test_*.py` and test functions start with `test_`
212+
213+
### Async test issues
214+
215+
Ensure pytest-asyncio is installed:
216+
217+
```bash
218+
pip install pytest-asyncio
219+
```

0 commit comments

Comments
 (0)