Testing
Approach
GeoTUI uses a combination of TDD (Test-Driven Development) and BDD (Behaviour-Driven Development) with a minimum coverage target of 80%.
Running Tests
# Run all tests
pytest
# Run with coverage report
pytest --cov=geotui --cov-report=html
# Run only unit tests
pytest tests/unit/
# Run only BDD tests
pytest tests/bdd/
# Run a specific test
pytest tests/unit/test_app.py::TestGeoTUIApp::test_launch -v
Test Structure
tests/
├── unit/ # Unit tests
│ ├── test_app.py # App launch and interaction tests
│ ├── test_client.py # GeoServer client tests
│ ├── test_config.py # Configuration and encryption tests
│ ├── test_i18n.py # Internationalisation tests
│ ├── test_publisher.py # Publisher tests
│ ├── test_report.py # PDF report tests
│ └── test_theme.py # Theme and colour tests
├── bdd/ # BDD tests
│ ├── features/ # Gherkin feature files
│ └── step_defs/ # Step definitions
└── conftest.py # Shared fixtures
Writing Unit Tests
Use pytest with async support via pytest-asyncio. Textual provides AppTest for testing TUI interactions:
import pytest
from textual.testing import AppTest
from geotui.app import GeoTUIApp
class TestMyFeature:
@pytest.mark.asyncio
async def test_feature_works(self) -> None:
app = GeoTUIApp()
async with AppTest.run_test(app) as pilot:
# Interact with the app
await pilot.press("f9")
# Assert on app state
assert pilot.app.screen.name == "settings"
Writing BDD Tests
Feature files use Gherkin syntax in tests/bdd/features/:
Feature: Connection Management
As a GeoServer administrator
I want to manage my server connections
So that I can work with multiple GeoServer instances
Scenario: Add a new connection
Given the application is running
And the settings screen is open
When I click the Add button
And I fill in the connection details
And I click Save
Then the connection appears in the list
Step definitions go in tests/bdd/step_defs/:
from pytest_bdd import given, when, then, scenario
@scenario("../features/connections.feature", "Add a new connection")
def test_add_connection():
pass
@given("the application is running")
def app_running(app):
assert app.is_running
Testing the GeoServer Client
Use httpx's mock transport or respx for mocking HTTP responses:
import respx
from httpx import Response
from geotui.client import GeoServerClient
@respx.mock
async def test_list_workspaces():
respx.get("https://example.com/geoserver/rest/workspaces").mock(
return_value=Response(200, json={
"workspaces": {"workspace": [{"name": "test"}]}
})
)
client = GeoServerClient("https://example.com", "admin", "pass")
workspaces = await client.list_workspaces()
assert workspaces == [{"name": "test"}]
Coverage
View the HTML coverage report after running tests with --cov-report=html:
pytest --cov=geotui --cov-report=html
open htmlcov/index.html