Skip to content

Commit 0f4591e

Browse files
committed
Add E2E testing infrastructure using mkosi
Set up end-to-end testing that runs pystemd inside a real systemd environment using mkosi to build Fedora container images. - Add mkosi.conf for building test images with configurable Python versions - Add mkosi.build.chroot to install pystemd and dependencies via uv - Add GitHub Actions workflow to run E2E tests across Python 3.10-3.14 - Add e2e/test_e2e.py with initial test cases - Add E2E_TESTING.md with documentation - Update .gitignore for mkosi generated files The tests run inside a systemd-nspawn container, allowing us to test pystemd against real systemd APIs rather than mocked interfaces.
1 parent df633ab commit 0f4591e

12 files changed

Lines changed: 837 additions & 2 deletions

.github/workflows/e2e-tests.yml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
name: E2E Tests
2+
3+
on:
4+
push:
5+
branches: [ main, develop ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
jobs:
10+
e2e-tests:
11+
name: E2E Tests with mkosi (Python ${{ matrix.python-version }})
12+
runs-on: ubuntu-latest
13+
14+
strategy:
15+
matrix:
16+
python-version: ['3.11', '3.12', '3.13', '3.14', '3.14t']
17+
18+
env:
19+
PYTHON_VERSION: ${{ matrix.python-version }}
20+
UNIT_NAME: pystemd-e2e-py${{ matrix.python-version }}.service
21+
MACHINE_NAME: pystemd-test-py${{ matrix.python-version }}
22+
23+
steps:
24+
- name: Checkout code
25+
uses: actions/checkout@v4
26+
27+
- name: Install uv
28+
uses: astral-sh/setup-uv@v7
29+
30+
- name: Set up latest Python
31+
uses: actions/setup-python@v4
32+
33+
- name: setup-mkosi
34+
uses: systemd/mkosi@v26
35+
36+
- name: Install systemd-container
37+
run: |
38+
sudo apt-get update
39+
sudo apt-get install -y systemd-container
40+
41+
- name: Generate mkosi keys
42+
run: |
43+
sudo mkosi genkey
44+
45+
- name: Build mkosi test image
46+
run: |
47+
sudo mkosi -E "$PYTHON_VERSION" build
48+
49+
- name: run e2e pytest
50+
run: |
51+
python3 -m venv venv
52+
venv/bin/python -m ensurepip
53+
venv/bin/python -m pip install pytest
54+
55+
venv/bin/pytest e2e
56+

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,10 @@ pystemd/RELEASE
9898

9999
# not a fan of keeping uv lock files around
100100
uv.lock
101+
102+
# mkosi generated files
103+
pystemd-test/
104+
pystemd-test-*/
105+
.#pystemd-test*.lck
106+
mkosi.key
107+
mkosi.crt

E2E_TESTING.md

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
# pystemd E2E Testing Setup
2+
3+
## Overview
4+
5+
This setup provides comprehensive end-to-end testing for pystemd using mkosi. Tests run in a real systemd environment to ensure accurate testing of systemd integration.
6+
7+
## Quick Start
8+
9+
```bash
10+
# Install mkosi (one-time setup)
11+
sudo dnf install mkosi # Fedora/RHEL
12+
# or
13+
sudo apt install mkosi # Debian/Ubuntu
14+
15+
# Run all E2E tests
16+
make e2e-test
17+
18+
# Or manually
19+
sudo mkosi
20+
```
21+
22+
## What Was Created
23+
24+
### Configuration Files
25+
26+
1. **`mkosi.conf`** - Main mkosi configuration
27+
- Defines Fedora 41 test environment
28+
- Installs Python 3, systemd, and dependencies
29+
- Configures build and test setup
30+
31+
2. **`mkosi.build`** - Build script
32+
- Builds pystemd from source
33+
- Installs into test image
34+
- Installs test dependencies (pytest, psutil)
35+
36+
3. **`mkosi.postinst`** - Post-installation script
37+
- Sets up test environment
38+
- Configures systemd
39+
40+
### Test Suite
41+
42+
**`mkosi.files/e2e-tests/test_e2e.py`** - Comprehensive E2E tests covering:
43+
44+
#### pystemd.run Tests (10+ tests)
45+
- Simple command execution
46+
- Commands with args, env vars, custom cwd
47+
- User switching (requires root)
48+
- Wait modes (wait vs wait_for_activation)
49+
- Error handling (raise_on_fail)
50+
- Timeouts (runtime_max_sec)
51+
- Service types
52+
- Stop commands
53+
54+
#### Manager Tests
55+
- Version and architecture queries
56+
- Listing units and unit files
57+
- Getting units by name
58+
59+
#### Unit Tests
60+
- Property reading
61+
- Start/stop/restart operations
62+
- Process management
63+
64+
#### Transient Unit Tests
65+
- Creating via Manager API
66+
- Setting dependencies
67+
68+
#### D-Bus Tests
69+
- System bus connections
70+
- User bus connections
71+
72+
### Infrastructure
73+
74+
4. **`mkosi.files/e2e-tests/run-tests.sh`** - Test runner
75+
- Executes pytest in mkosi environment
76+
- Reports results
77+
78+
5. **`Makefile`** - Convenience targets
79+
- `make e2e-test` - Build and run tests
80+
- `make e2e-shell` - Enter test environment
81+
- `make e2e-clean` - Clean artifacts
82+
83+
6. **`.github/workflows/e2e-tests.yml`** - CI integration
84+
- Runs on push/PR
85+
- Uses Ubuntu runners
86+
- Uploads test results
87+
88+
7. **`mkosi.files/e2e-tests/README.md`** - Detailed documentation
89+
90+
## Usage Examples
91+
92+
### Run tests locally
93+
```bash
94+
make e2e-test
95+
```
96+
97+
### Debug a test failure
98+
```bash
99+
# Enter the test environment
100+
make e2e-shell
101+
102+
# Inside the environment
103+
cd /e2e-tests
104+
python3 -m pytest test_e2e.py::TestPystemdRun::test_simple_command -v
105+
```
106+
107+
### Run without rebuilding (faster iteration)
108+
```bash
109+
make e2e-test-quick
110+
```
111+
112+
### Add a new test
113+
114+
Edit `mkosi.files/e2e-tests/test_e2e.py`:
115+
116+
```python
117+
def test_my_feature(self):
118+
"""Test my new feature"""
119+
unit = pystemd.run([b'/bin/echo', b'hello'], wait=True)
120+
assert unit.Service.ExecMainStatus == 0
121+
```
122+
123+
Then run:
124+
```bash
125+
make e2e-test
126+
```
127+
128+
## Architecture
129+
130+
```
131+
┌─────────────────┐
132+
│ Host System │
133+
│ │
134+
│ make e2e-test │
135+
└────────┬────────┘
136+
137+
v
138+
┌─────────────────────────────────┐
139+
│ mkosi │
140+
│ │
141+
│ ┌──────────────────────────┐ │
142+
│ │ Fedora 41 Image │ │
143+
│ │ │ │
144+
│ │ - systemd running │ │
145+
│ │ - pystemd installed │ │
146+
│ │ - pytest + tests │ │
147+
│ │ │ │
148+
│ │ Run: /e2e-tests/ │ │
149+
│ │ run-tests.sh │ │
150+
│ └──────────────────────────┘ │
151+
│ │
152+
│ Isolated systemd environment │
153+
└─────────────────────────────────┘
154+
```
155+
156+
## Benefits
157+
158+
**Real systemd environment** - Not containerized, no quirks
159+
**Isolated testing** - Clean environment each run
160+
**Fast** - Directory format, no VM overhead
161+
**CI ready** - GitHub Actions integration included
162+
**Example-based** - Tests derived from real usage examples
163+
164+
## CI/CD Integration
165+
166+
The GitHub Actions workflow (`.github/workflows/e2e-tests.yml`) automatically:
167+
- Runs on every push to main/develop
168+
- Runs on all pull requests
169+
- Installs mkosi
170+
- Builds test image
171+
- Runs all E2E tests
172+
- Uploads test artifacts
173+
174+
## Troubleshooting
175+
176+
### mkosi not found
177+
```bash
178+
sudo dnf install mkosi # or apt install mkosi
179+
```
180+
181+
### Permission denied
182+
```bash
183+
# mkosi requires root
184+
sudo mkosi
185+
```
186+
187+
### Tests fail locally but pass in examples
188+
```bash
189+
# Check if you're running as root (many tests require it)
190+
sudo make e2e-test
191+
```
192+
193+
### Want to modify the test environment
194+
Edit `mkosi.conf` to add packages, change OS version, etc.
195+
196+
## Next Steps
197+
198+
- Add more test cases based on additional examples
199+
- Test more edge cases
200+
- Add performance benchmarks
201+
- Test on different systemd versions

0 commit comments

Comments
 (0)