macxred / pyledger

Python package to streamline the implementation and management of accounting systems.
MIT License
0 stars 0 forks source link

Write Base tests classes for pyLedger #9

Open lasuk opened 2 months ago

lasuk commented 2 months ago

Tasks:

  1. Write unit tests to test accessors, mutators, and mirroring using TestLedger or MemoryLedger. Copy existing test code from CashCtrlLedger where helpful.

Test Architecture

  1. Ideally, tests should accept a ledger class to test as an argument. Default is TestLedger. The same tests can then be used to test accessors and mutators on other ledger implementations, such as CashCtrlLedger.
AlexTheWizardL commented 1 month ago

Task: Implement Test Strategy for Multiple LedgerEngine Implementations

Objective: Implement a test strategy that allows for testing multiple implementations of the LedgerEngine abstract class without duplicating test logic. This strategy should be scalable, allowing new implementations to be added with minimal changes to the test code.

Requirements:

  1. Abstract Base Test Class:

    • Create an abstract base test class that contains common CRUD operation tests for LedgerEngine implementations.
    • This class should define tests such as test_create_entry, test_update_entry, and test_delete_entry.
    • Use pytest fixtures to manage the setup for each implementation.
  2. Concrete Test Classes:

    • For each LedgerEngine implementation, create a concrete test class that inherits from the abstract base test class.
    • Each concrete test class should implement a ledger fixture that returns an instance of the specific LedgerEngine implementation.
    • These concrete test classes should be located in the appropriate packages, depending on the implementation.
  3. Support for Future Implementations:

    • The test structure should support adding new LedgerEngine implementations with minimal changes.
    • When a new implementation is added, simply create a new test class that inherits from the abstract base test class and provides the appropriate ledger fixture.

Example Implementation:

# tests/base_test_ledger.py

import pytest
import pandas as pd
from abc import ABC, abstractmethod

class BaseLedgerTest(ABC):

    @abstractmethod
    @pytest.fixture
    def ledger(self):
        pass

    def test_create_entry(self, ledger):
        entry = pd.DataFrame([{"id": "1", "data": "test data"}])
        ledger.create(entry)
        assert ledger.get("1") is not None

    def test_update_entry(self, ledger):
        entry = pd.DataFrame([{"id": "1", "data": "test data"}])
        ledger.create(entry)
        updated_entry = pd.DataFrame([{"id": "1", "data": "updated data"}])
        ledger.update("1", updated_entry)
        assert ledger.get("1").iloc[0]["data"] == "updated data"

    def test_delete_entry(self, ledger):
        entry = pd.DataFrame([{"id": "1", "data": "test data"}])
        ledger.create(entry)
        ledger.delete("1")
        assert ledger.get("1") is None
# tests/test_memory_ledger.py

import pytest
from .base_test_ledger import BaseLedgerTest
from yourpackage.memory_ledger import MemoryLedger

class TestMemoryLedger(BaseLedgerTest):
    @pytest.fixture
    def ledger(self):
        return MemoryLedger()
# tests/test_cashctrl_ledger.py

import pytest
from .base_test_ledger import BaseLedgerTest
from yourpackage.cashctrl_ledger import CashCtrlLedger
from yourpackage.api_client import ApiClient  # Assuming a mock or test client

class TestCashCtrlLedger(BaseLedgerTest):
    @pytest.fixture
    def ledger(self):
        client = ApiClient()
        return CashCtrlLedger(client)
# tests/test_new_ledger.py

import pytest
from .base_test_ledger import BaseLedgerTest
from newpackage.new_ledger import NewLedger  # Your new ledger implementation

class TestNewLedger(BaseLedgerTest):
    @pytest.fixture
    def ledger(self):
        return NewLedger()

Benefits:

Next Steps:


This approach follows best practices seen in large open-source projects like Django and Pandas, ensuring a scalable and maintainable testing strategy for your LedgerEngine implementations.