4.0 KiB
Testing Guide for OpenTTD Python Client
This guide explains how the test suite is structured, the types of tests available, and how to execute them.
📂 Test Suite Structure
The tests are located in the tests/ directory:
| Test File | Target | Description |
|---|---|---|
test_admin.py |
OpenTTDAdminClient |
Tests admin client initialization, admin packet types, and basic protocol constants. |
test_protocol.py |
OpenTTDProtocol |
Tests binary serialization, custom parsers, and stream encryption/decryption (XChaCha20-Poly1305). |
test_logic.py |
OpenTTDClient |
Tests client connection lifecycle, company joining flow, authentication, and state management. |
test_coverage.py |
Coverage Helpers | Auxiliary unit tests targeting connection errors, fallback packet handlers, and missing passwords to ensure high test coverage. |
test_e2e.py |
Integration / E2E | Connects to a running local OpenTTD server (e.g., in Docker) to verify full socket interactions, stream cryptography, and keep-alive frames. |
🚀 How to Run Tests
Pytest automatically uses pytest.ini to configure the Python import path (pythonpath = lib). You do not need to manually configure PYTHONPATH.
Make sure your virtual environment is active before running commands:
source venv/bin/activate
1. Run Normal (Non-E2E) Tests
These are unit and logic tests that run instantly in memory without external dependencies:
pytest -m "not e2e"
2. Run E2E Tests Only
Requires a running local OpenTTD server configured with password "asd". If the server is offline, this test will fail:
pytest -m "e2e"
🐳 Starting the OpenTTD Server (Docker)
To run E2E tests locally, you can start the dedicated JGRPP OpenTTD server using the provided Docker Compose configuration in the docker/ directory.
1. Build and Start the Server
Run this command from the project root directory:
docker compose -f docker/docker-compose.yml up -d --build
Note: The first build will clone and compile the JGRPP source code, which may take a few minutes.
2. Monitor Server Logs
To watch the server logs (e.g., to see client connections and events):
docker compose -f docker/docker-compose.yml logs -f
3. Stop the Server
To stop the server container:
docker compose -f docker/docker-compose.yml down
3. Run All Tests
Runs both unit/logic tests and E2E tests:
pytest
4. Run with Coverage Report
To view statement coverage statistics:
pytest --cov=openttd --cov-report=term-missing
📊 Testing Mandate
We enforce the following testing mandates:
- Normal/Unit tests (
pytest -m "not e2e") must achieve 100% code coverage on the codebase independently. - E2E tests (
pytest -m "e2e") do NOT require 100% code coverage. Instead, they are only required to cover every public function of the client classes (OpenTTDClientandOpenTTDAdminClient) and protocol classes with multiple (varied) inputs/scenarios.
To run/verify tests:
- Normal Tests (Must achieve 100% coverage):
pytest -m "not e2e" --cov=openttd --cov-report=term-missing --cov-fail-under=100 - E2E Tests (No coverage mandate, must cover all public functions with multiple inputs):
pytest -m "e2e"
🔧 Pytest Configuration (pytest.ini)
The project uses a pytest.ini file at the root:
pythonpath = lib: Simplifies invocation by resolving imports from the locallib/directory.markers: Registers the custome2emarker for pytest classification.