Testing¶
Istota uses TDD with pytest and pytest-asyncio. The test suite has ~6,500 tests across ~200 files.
Running tests¶
uv run pytest tests/ -v # Unit tests
uv run pytest -m integration -v # Integration tests
uv run pytest tests/ --cov=istota --cov-report=term-missing # Coverage
Integration tests are deselected by default (configured in pyproject.toml). They require a live Nextcloud instance and are marked with @pytest.mark.integration.
Test patterns¶
Real SQLite via tmp_path: No database mocking. Tests create real SQLite databases initialized from schema.sql. This catches actual SQL issues that mocks would hide.
unittest.mock for external dependencies: HTTP calls, subprocess invocations, and file system operations outside the test directory are mocked.
Class-based tests: Tests are organized in classes grouping related scenarios.
Shared fixtures (conftest.py)¶
| Fixture | Purpose |
|---|---|
db_path |
Initialized SQLite database from schema.sql |
db_conn |
Database connection |
make_task |
Factory for creating test tasks |
make_config |
Factory for creating Config objects |
make_user_config |
Factory for creating UserConfig objects |
Testing skills¶
Skill loader tests require isolation from bundled skills:
# Pass bundled_dir to isolate from bundled skills
index = load_skill_index(skills_dir, bundled_dir=_empty_bundled(tmp_path))
Executor tests set bundled_skills_dir on the Config object to an empty directory to isolate from bundled skills.
TDD workflow¶
For new features:
- Read existing codebase structure and test patterns
- Write failing tests covering happy path, edge cases, and error handling
- Run tests to confirm they fail
- Implement the feature
- Run tests and iterate until all pass
- Run linters/type checkers if configured
- Commit