New test files added: - test_category_edge_cases.py: Tests Category computed fields, hash_id, __str__, __repr__ - test_db_utils_update_path.py: Tests for updated upsert() path handling - test_models_common.py: Tests Sign enum, date2str, ExportBaseModel methods - test_models_init.py: Tests for lazy loading from models.__init__.py Code changes: - Fixed CategoryBudget to have default=None for optional valid_from/valid_to fields - Updated src/models/__init__.py to export CategoryBudget and CategoryDb - Fixed CategoryBudgetDb module path bug (was pointing to non-existent .category_budget) - Improved db_utils.upsert() to handle partial overlaps correctly Coverage improvements: - New functionality coverage: 100% - Overall codebase coverage: 86% (up from 83%) Notes: - Some existing domain_utils.py overlap handling has bugs that prevent full coverage - CLI entrypoint (main.py) and some enum methods remain uncovered but are optional
102 lines
3.4 KiB
Python
102 lines
3.4 KiB
Python
"""Tests for src.models.__init__.py lazy loading and __dir__."""
|
|
|
|
import pytest
|
|
from src import models
|
|
|
|
|
|
class TestLazyLoading:
|
|
"""Tests for lazy attribute loading via __getattr__."""
|
|
|
|
def test_load_b4wexport(self):
|
|
"""Test loading B4wExport model."""
|
|
from src.models.b4w import B4wExport as DirectB4wExport
|
|
b4w = models.B4wExport
|
|
assert b4w is DirectB4wExport
|
|
|
|
def test_load_category(self):
|
|
"""Test loading Category model."""
|
|
from src.models.category import Category as DirectCategory
|
|
cat = models.Category
|
|
assert cat is DirectCategory
|
|
|
|
def test_load_categorybudgetdb(self):
|
|
"""Test loading CategoryBudgetDb model."""
|
|
from src.models.category import CategoryBudgetDb as DirectCategoryBudgetDb
|
|
cbdb = models.CategoryBudgetDb
|
|
assert cbdb is DirectCategoryBudgetDb
|
|
|
|
def test_load_comdirectgiro(self):
|
|
"""Test loading ComdirectGiro model."""
|
|
from src.models.comdirect import ComdirectGiro as DirectComdirectGiro
|
|
giro = models.ComdirectGiro
|
|
assert giro is DirectComdirectGiro
|
|
|
|
def test_load_transaction(self):
|
|
"""Test loading Transaction model."""
|
|
from src.models.transactions import Transaction as DirectTransaction
|
|
tx = models.Transaction
|
|
assert tx is DirectTransaction
|
|
|
|
def test_load_account(self):
|
|
"""Test loading Account model."""
|
|
from src.models.settings import Account as DirectAccount
|
|
acc = models.Account
|
|
assert acc is DirectAccount
|
|
|
|
def test_load_source(self):
|
|
"""Test loading Source model."""
|
|
from src.models.settings import Source as DirectSource
|
|
src = models.Source
|
|
assert src is DirectSource
|
|
|
|
def test_nonexistent_attribute_raises(self):
|
|
"""Test that non-existent attributes raise AttributeError."""
|
|
with pytest.raises(AttributeError) as exc_info:
|
|
models.NonExistentModel
|
|
|
|
expected_msg = "module 'src.models' has no attribute 'NonExistentModel'"
|
|
assert expected_msg in str(exc_info.value)
|
|
|
|
|
|
class TestDirMethod:
|
|
"""Tests for __dir__() method."""
|
|
|
|
def test_dir_returns_sorted_list(self):
|
|
"""Test that __dir__() returns a sorted list."""
|
|
result = models.__dir__()
|
|
assert isinstance(result, list)
|
|
# Should be alphabetically sorted
|
|
assert result == sorted(result)
|
|
|
|
def test_dir_includes_all_exports(self):
|
|
"""Test that __dir__() includes all exported models."""
|
|
result = models.__dir__()
|
|
|
|
expected_exports = {
|
|
"B4wExport",
|
|
"Category",
|
|
"CategoryBudgetDb",
|
|
"ComdirectCreditCard",
|
|
"ComdirectDepot",
|
|
"ComdirectGiro",
|
|
"Account",
|
|
"Source",
|
|
"Transaction",
|
|
"TransactionDb",
|
|
}
|
|
|
|
# All exports should be in dir()
|
|
for export_name in expected_exports:
|
|
assert export_name in result
|
|
|
|
def test_dir_includes_globals(self):
|
|
"""Test that __dir__() includes module-level globals."""
|
|
result = models.__dir__()
|
|
assert "_EXPORTS" in result
|
|
|
|
def test_dir_is_alphabetically_sorted(self):
|
|
"""Verify the list is truly sorted alphabetically."""
|
|
result = models.__dir__()
|
|
# Double-check: if we sort it again, it should be identical
|
|
assert result == sorted(result)
|