Задача курса
Python: Реализуй TaskRepository и напиши тест с stub-репозиторием
Курс «Python для продвинутых: ООП, типизация и тестирование» · урок «Repository: отделение хранения данных от бизнес-логики»
Условие
Реализуй TaskRepository и напиши тест с stub-репозиторием
Тебе нужно реализовать класс TaskRepository, который хранит задачи в JSON-файле, и написать тест бизнес-функции complete_task с использованием stub-репозитория.
Что уже дано
Проверяющая система скрыто создаёт:
- файл
tasks.jsonна диске с тестовыми данными; - вспомогательные функции
load_json(path)иsave_json(path, data)в пространстве имён (они уже доступны без импорта).
Эти имена доступны в том же процессе и пространстве имён, где выполняется твой код:
load_json— читает JSON из файла поPath, возвращаетlist[dict];save_json— записываетlist[dict]в JSON-файл поPath;tasks_path— объектPath, указывающий наtasks.json.
Что нужно сделать
Определи на верхнем уровне:
@dataclass class Taskс полями:
id: inttitle: strdone: bool
class TaskRepositoryс методами:
__init__(self, path: Path) -> None— сохраняет путь вself._path;load(self) -> list[Task]— читает файл черезload_json(self._path)и возвращает список объектовTask(используйTask(**row)для каждой строки);save(self, tasks: list[Task]) -> None— сериализует список черезasdictи записывает черезsave_json(self._path, rows).
Внутри load и save не должно быть бизнес-логики: только чтение/запись и преобразование между словарями и объектами.
def complete_task(repo, task_id: int) -> None— бизнес-функция, которая:
- вызывает
repo.load(); - находит задачу с нужным
idи устанавливаетdone = True; - вызывает
repo.save(tasks).
Функция не должна содержать вызовы load_json, save_json, open или любых других файловых операций напрямую.
class StubTaskRepository— stub для тестов:
__init__(self, tasks: list[Task])— сохраняет список вself._tasks;load(self) -> list[Task]— возвращаетself._tasks;save(self, tasks: list[Task]) -> None— сохраняет переданный список вself._tasks.
- Верхнеуровневый код теста — создай
StubTaskRepositoryс тремя задачами (id=1 done=False, id=2 done=False, id=3 done=True), вызовиcomplete_task(stub_repo, 2)и сохрани результатstub_repo.load()в переменнуюresult_tasks.
Ввод и вывод
stdin не используется. Печатать через print в stdout ничего не нужно.
Проверяющая система после выполнения твоего кода читает следующие верхнеуровневые имена:
Task— класс-dataclass;TaskRepository— класс репозитория;complete_task— бизнес-функция;StubTaskRepository— stub-класс;result_tasks— список объектовTaskпосле вызоваcomplete_taskна stub.
Пример использования
repo = StubTaskRepository([
Task(1, "A", False),
Task(2, "B", False),
])
complete_task(repo, 2)
print([(task.id, task.done) for task in repo.load()])
Результат:
[(1, False), (2, True)]
