Skip to content

Sofia-Rdv/SQLiteBookManager

Repository files navigation

Менеджер Книг на SQLite

Обзор

Этот проект представляет собой простой Python-скрипт для управления базой данных книг с использованием SQLite. Он предоставляет базовые операции CRUD (Create, Read, Update, Delete) для записей о книгах. Проект включает надежную систему логирования для отслеживания выполнения запросов и возникающих ошибок.

Функциональность

  • Создание и инициализация базы данных library.db с таблицей books.
  • Добавление новых книг с указанием названия, автора и года издания.
  • Получение полного списка всех книг в базе данных.
  • Обновление информации (названия, автора, года) для существующей книги.
  • Удаление книги по ее ID.
  • Интерактивный консольный интерфейс для управления приложением.
  • Комплексная система логирования с цветным выводом в консоль.

Структура проекта

SQLiteProject/
├── sqlite_task.py              # Основной файл приложения с логикой работы с БД и пользовательским интерфейсом
├── test_sqlite_task.py         # Файл с юнит-тестами для функций приложения
├── my_logger_config.py         # Модуль с настройками логирования и инициализацией логгеров
├── my_logging_config.yaml      # YAML-файл конфигурации для логирования
├── my_color_formatter.py       # Кастомный форматтер для цветного вывода логов в консоль
└── logs/                       # Директория с файлами логов
├── app.log                     # Информационные логи приложения
└── error.log                   # Логи ошибок и исключений

Структура базы данных

Приложение работает с базой данных SQLite library.db, содержащей одну таблицу books. Таблица books имеет следующую структуру:

| Колонка | Тип данных | Описание
|:--------|:-----------|:------------------------------------
| `id`    | INTEGER    | Уникальный идентификатор книги(PRIMARY KEY, AUTOINCREMENT)
| `title` | TEXT       | Название книги (NOT NULL)
| `author`| TEXT       | Автор книги (NOT NULL)
| `year`  | INTEGER    | Год издания книги (может быть NULL)

Начало работы

Требования

  • Python 3.x
  • sqlite3 (встроен в стандартную библиотеку Python)
  • pytest (для запуска тестов)
  • PyYAML (для загрузки конфигурации логирования)
  • Colorama - (для цветного вывода логов в консоль)

Установка

  1. Клонировать репозиторий:
git clone <URL_РЕПОЗИТОРИЯ>
cd <ИМЯ_ПАПКИ_ПРОЕКТА>
  1. Установить необходимые библиотеки (инструкцию см. ниже).
  2. Запустить приложение:
python sqlite_task.py

Инструкция по установке библиотек

  1. В командной строке или окне терминала ввести команду
  2. Нажать кнопку Enter

Команды для установки

  • pip install PyYAML - Для установки библиотеки PyYAML
  • pip install colorama - Для установки библиотеки Colorama
  • pip install pytest - Для установки библиотеки PyTest

Использование

Программа запускается через файл sqlite_task.py и предоставляет консольное меню со следующими опциями:

Меню: 0. Выход из программы - Выход из приложения

  1. Добавить книгу - Добавить новую книгу в таблицу books
  2. Получить список всех книг - Получить список всех книг из базы данных
  3. Обновить информацию о книге - Обновить информацию (названия, автора, года) для существующей книги
  4. Удалить книгу по ID - Удаление книги по ее ID

Пример использования

Конфигурация логирования загружена из файла: my_logging_config.yaml
2025-11-27 19:31:37 - my_app - INFO -Программа "sqlite_task" запущена.
2025-11-27 19:31:37 - my_app - INFO -Успешное подключение к базе данных: library.db
2025-11-27 19:31:37 - my_app - INFO -Таблица "books" проверена/создана в library.db.

Выберите действие:
1 - Добавить книгу
2 - Получить список всех книг
3 - Обновить информацию о книге
4 - Удалить книгу по ID
0 - Выход из программы.
Введите номер действия: 2
Вы выбрали получить список всех книг.
2025-11-27 19:55:01 - my_app - DEBUG -Выполнение запроса: SELECT id, title, author, year FROM books с параметрами: ().
2025-11-27 19:55:01 - my_app - DEBUG -SQL SELECT запрос выполнен, данные получены.
2025-11-27 19:55:01 - my_app - INFO -Получено 4 книг из базы данных.
Найдено книг: 4.
Книга с ID 1: Мастер и Маргарита М.А. Булгаков 1967
Книга с ID 2: Собачье сердце Михаил Булгаков 1968
Книга с ID 3: Горе от ума А.С. Грибоедов 1825
Книга с ID 5: Мертвые души Н.В. Гоголь 1842
2025-11-27 19:55:01 - my_app - INFO -Функция "Получить список всех книг" выполнена успешно (найдено книг: 4).

Выберите действие:
1 - Добавить книгу
2 - Получить список всех книг
3 - Обновить информацию о книге
4 - Удалить книгу по ID
0 - Выход из программы.
Введите номер действия: 0
Вы выбрали выход из программы.
2025-11-27 19:55:38 - my_app - INFO - Программа 'sqlite_task' завершена по желанию пользователя.
Соединение с базой данных закрыто.
2025-11-27 19:55:38 - my_app - INFO -Соединение с базой данных library.db закрыто.

Система логирования

Приложение реализует комплексную систему логирования, которая:

  • Записывает все события приложения(действия пользователя, изменения в БД) и ошибки.
  • Использует различные уровни логирования (INFO, WARNING, ERROR, DEBUG, CRITICAL).
  • Обеспечивает цветной вывод в консоль для лучшей читаемости.
  • Хранит логи в отдельных файлах(app.log для общей информации, error.log для ошибок) в директории logs/.

Файлы логов

  • app.log: Содержит общую информацию о работе приложения, включая действия пользователя, успешное выполнение операций с базой данных и информационные сообщения.
  • error.log: Записывает все сообщения уровня ERROR и выше, включая ошибки выполнения запросов к БД, исключения и критические сбои.

Компоненты логирования

Настройка системы логирования осуществляется через следующие файлы:

  • my_logger_config.py: Настраивает конфигурацию логирования
  • my_logging_config.yaml: Конфигурация для различных логгеров
  • my_color_formatter.py: Кастомный форматтер для цветного вывода в консоль

Тестирование

В проекте применяется двухуровневый подход к тестированию для обеспечения надежности и корректности работы кода:

1. Doctests

Используются doctests - это тесты, встроенные прямо в строки документации (docstrings) ключевых функций (create_connection, execute_query, get_year_input, get_id_input) и метода __post_init__ в классе Year. Они служат для:

  • Демонстрации ожидаемого поведения: Показывают примеры использования функции и их предсказуемые результаты.
  • Быстрой проверки базовой функциональности: Обеспечивают моментальный фидбек о корректности простых сценариев.

2. Юнит-тесты с Pytest

Для комплексного и глубокого тестирования функционала менеджера книг используется фреймворк Pytest. Все основные юнит-тесты расположены в файле test_sqlite_task.py. Эти тесты охватывают все CRUD-операции, включая добавление, просмотр, обновление и удаление книг, а также проверяют различные граничные случаи и сценарии ошибок:

  • Изоляция тестов: Используется фикстура in_memory_db, которая создает временную базу данных SQLite в оперативной памяти для каждого теста. Это гарантирует, что тесты полностью изолированы друг от друга и не влияют на состояние других.
  • Полное покрытие CRUD-операций: Тестируются успешные сценарии добавления, получения, обновления и удаления данных.
  • Обработка граничных случаев: Проверяется поведение функций при отсутствии обязательных параметров, при передачи None для опциональных полей (например, года издания книги), а также при попытках обновления или удаления несуществующих записей(книг).
  • Имитация ошибок внешних зависимостей: С помощью unittest.mock.patch имитируются сбои при подключении к базе данных, чтобы убедиться, что приложение корректно обрабатывает такие случаи.
  • Параметризация тестов: Активно применяется @pytest.mark.parametrize для эффективного тестирования множества входных данных и сценариев с минимальным дублированием кода.

Запуск тестов

Запуск Doctests

Doctests могут запускаться автоматически как часть конфигурации запуска тестов в некоторых IDE (например, PyCharm).

Также doctests можно запустить из командной строки:

python -m doctest -v имя_файла.py

где 'имя_файла.py' - имя файла с вашим кодом.

Юнит-тесты с Pytest

Файл с тестированием можно запустить как и обычный код, через кнопку run.

Также юнит-тесты можно запустить из командной строки:

  • pytest - Краткий вариант результата юнит-тестов
  • pytest -v - Более детальный вывод результата юнит-тестов
  • pytest --doctest-modules - Результат всех тестов (doctests и юнит-тестов)

Пример doctest из проекта

Doctest из функции get_year_input, который проверяет вводимый пользователем год издания на допустимый диапазон, тип данных и обработку пустой строки:

# Корректный ввод
>>> get_year_input('Введите год издания книги: ') # doctest: +SKIP
Введите год издания книги: 1789
Year(value=1789)

>>> # Введена пустая строка
>>> get_year_input('Введите год издания книги: ') # doctest: +SKIP
Введите год издания книги:
None

>>> # Введено нецелочисленное значение
>>> try:
...     get_year_input('Введите год издания книги: ') # doctest: +SKIP
... except ValueError as e:
...     print(e)
Введите год издания книги: abc
Год издания должен быть целым числом. Получено: abc

>>> # Введен год не соответствующий диапазону
>>> try:
...     get_year_input('Введите год издания книги: ') # doctest: +SKIP
... except ValueError as e:
...     print(e)
Введите год издания книги: 2029
Год издания должен быть в диапазоне от 868 до 2025. Получено: 2029

Пример юнит-теста с Pytest из проекта

Юнит-тест из файла test_sqlite_task.py для функции add_book, который тестирует неудачное добавление книги с неверными параметрами (отсутствует название или автор книги, title, author NOT NULL):

import pytest
import sqlite3
from sqlite_task import add_book

@pytest.mark.parametrize(
    'title, author, year',
    [
        (None, 'Author X', 2020),
        ('Book Y', None, 2000)
    ]
)
def test_add_book_parametrizes_failure_cases(
        in_memory_db: sqlite3.Connection,
        title: str | None,
        author: str | None,
        year: int | None):
    """
    Тестирует неудачное добавление книги с неверными параметрами (title/author - NOT NULL).
    Ожидается, что функция add_book вернет None при ошибке.
    :param in_memory_db: sqlite3.Connection: Объект подключения к базе данных в памяти.
    :param title: str | None: Название книги (или None, если не указано).
    :param author: str | None: Автор книги (или None, если не указано).
    :param year: int | None: Год издания книги (или None, если не указано).
    """
    book_id = add_book(':memory:', title, author, year, conn=in_memory_db)
    assert book_id is None

About

Простой менеджер книг на SQLite с логированием и тестами на Python

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages