Files
openttd-client/docs/TESTING.md
kovagoadi aebd5f4ef5
Some checks failed
Continuous Integration / lint-and-security (pull_request) Failing after 39s
Continuous Integration / tests-and-coverage (pull_request) Successful in 24s
Add admin port support with other major refactorations
2026-06-29 19:47:48 +02:00

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 (OpenTTDClient and OpenTTDAdminClient) 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 local lib/ directory.
  • markers: Registers the custom e2e marker for pytest classification.