diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0a5117c --- /dev/null +++ b/.gitignore @@ -0,0 +1,127 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation docs/ +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pypa/cython +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# IDE +.vscode/ +.idea/ + +# OS +.DS_Store +Thumbs.db \ No newline at end of file diff --git a/README.md b/README.md index 1cc701d..1a1ee24 100644 --- a/README.md +++ b/README.md @@ -1 +1,48 @@ -# qa_python \ No newline at end of file +# Проект: Тестирование BooksCollector + +## Описание +Этот проект реализует юнит-тесты для класса `BooksCollector`, который позволяет: +- Добавлять книги в коллекцию. +- Устанавливать жанр книги. +- Добавлять книги в избранное. +- Получать список книг по жанрам. +- Получать список книг, подходящих детям. + +## Тесты + +### Метод `add_new_book` +- `test_add_new_book_success` — проверяет добавление книги с корректным названием. +- `test_add_new_book_name_too_long_failed` — проверяет, что книга с длинным названием не добавляется. +- `test_add_new_book_name_empty_failed` — проверяет, что пустое название не добавляется. +- `test_add_new_book_multiple_names_success` — параметризованный тест на добавление нескольких книг. + +### Метод `set_book_genre` +- `test_set_book_genre_success` — проверяет установку жанра, если книга и жанр корректны. +- `test_set_book_genre_not_in_list_failed` — проверяет, что нельзя установить жанр, которого нет в списке. +- `test_set_book_genre_book_not_added_failed` — проверяет, что нельзя установить жанр книге, которой нет в списке. + +### Метод `get_book_genre` +- `test_get_book_genre_success` — проверяет, что возвращается установленный жанр. +- `test_get_book_genre_not_found_returns_none` — проверяет, что возвращается `None`, если книги нет. +- `test_get_book_genre_no_genre_set_returns_empty_string` — проверяет, что возвращается пустая строка, если жанр не установлен. + +### Метод `get_books_with_specific_genre` +- `test_get_books_with_specific_genre_success` — проверяет, что возвращается список книг с указанным жанром. + +### Метод `get_books_genre` +- `test_get_books_genre_returns_current_dict` — проверяет, что возвращается текущий словарь `books_genre`. + +### Метод `get_books_for_children` +- `test_get_books_for_children_success` — проверяет, что возвращаются только книги без возрастного рейтинга. + +### Метод `add_book_in_favorites` +- `test_add_book_in_favorites_success` — проверяет добавление книги в избранное. +- `test_add_book_in_favorites_not_in_books_genre_failed` — проверяет, что нельзя добавить в избранное книгу, которой нет в списке. +- `test_add_book_in_favorites_duplicate_failed` — проверяет, что нельзя дважды добавить одну и ту же книгу в избранное. + +### Метод `delete_book_from_favorites` +- `test_delete_book_from_favorites_success` — проверяет удаление книги из избранного. + +### Метод `get_list_of_favorites_books` +- `test_get_list_of_favorites_books_empty_initially` — проверяет, что при старте список избранных пуст. +- `test_get_list_of_favorites_books_returns_correct_list` — проверяет, что возвращается правильный список избранных книг. \ No newline at end of file diff --git a/tests.py b/tests.py index 383385e..960e8f1 100644 --- a/tests.py +++ b/tests.py @@ -1,24 +1,156 @@ +import pytest from main import BooksCollector -# класс TestBooksCollector объединяет набор тестов, которыми мы покрываем наше приложение BooksCollector -# обязательно указывать префикс Test -class TestBooksCollector: +# Тесты для метода add_new_book +class TestAddNewBook: - # пример теста: - # обязательно указывать префикс test_ - # дальше идет название метода, который тестируем add_new_book_ - # затем, что тестируем add_two_books - добавление двух книг - def test_add_new_book_add_two_books(self): - # создаем экземпляр (объект) класса BooksCollector + def test_add_new_book_success(self): collector = BooksCollector() + collector.add_new_book("Гарри Поттер") + assert "Гарри Поттер" in collector.books_genre + assert collector.books_genre["Гарри Поттер"] == "" - # добавляем две книги - collector.add_new_book('Гордость и предубеждение и зомби') - collector.add_new_book('Что делать, если ваш кот хочет вас убить') + def test_add_new_book_name_too_long_failed(self): + collector = BooksCollector() + long_name = "A" * 41 + collector.add_new_book(long_name) + assert long_name not in collector.books_genre + + def test_add_new_book_name_empty_failed(self): + collector = BooksCollector() + collector.add_new_book("") + assert "" not in collector.books_genre + + @pytest.mark.parametrize("name", ["Война и мир", "1984", "Мастер и Маргарита"]) + def test_add_new_book_multiple_names_success(self, name): + collector = BooksCollector() + collector.add_new_book(name) + assert name in collector.books_genre + + +# Тесты для метода set_book_genre +class TestSetBookGenre: + + def test_set_book_genre_success(self): + collector = BooksCollector() + collector.add_new_book("Тёмные alley") + collector.set_book_genre("Тёмные alley", "Фантастика") + assert collector.get_book_genre("Тёмные alley") == "Фантастика" + + def test_set_book_genre_not_in_list_failed(self): + collector = BooksCollector() + collector.add_new_book("Тёмные alley") + collector.set_book_genre("Тёмные alley", "Боевик") + assert collector.get_book_genre("Тёмные alley") != "Боевик" + + def test_set_book_genre_book_not_added_failed(self): + collector = BooksCollector() + collector.set_book_genre("Тёмные alley", "Фантастика") + assert collector.get_book_genre("Тёмные alley") is None + + +# Тесты для метода get_book_genre +class TestGetBookGenre: + + def test_get_book_genre_success(self): + collector = BooksCollector() + collector.add_new_book("Тёмные alley") + collector.set_book_genre("Тёмные alley", "Фантастика") + assert collector.get_book_genre("Тёмные alley") == "Фантастика" + + def test_get_book_genre_not_found_returns_none(self): + collector = BooksCollector() + assert collector.get_book_genre("Неизвестная книга") is None + + def test_get_book_genre_no_genre_set_returns_empty_string(self): + collector = BooksCollector() + collector.add_new_book("Тёмные alley") + assert collector.get_book_genre("Тёмные alley") == "" + + +# Тесты для метода get_books_with_specific_genre +class TestGetBooksWithSpecificGenre: + + def test_get_books_with_specific_genre_success(self): + collector = BooksCollector() + collector.add_new_book("Книга1") + collector.add_new_book("Книга2") + collector.set_book_genre("Книга1", "Фантастика") + collector.set_book_genre("Книга2", "Фантастика") + result = collector.get_books_with_specific_genre("Фантастика") + assert "Книга1" in result + assert "Книга2" in result + assert len(result) == 2 - # проверяем, что добавилось именно две - # словарь books_rating, который нам возвращает метод get_books_rating, имеет длину 2 - assert len(collector.get_books_rating()) == 2 - # напиши свои тесты ниже - # чтобы тесты были независимыми в каждом из них создавай отдельный экземпляр класса BooksCollector() \ No newline at end of file +# Тесты для метода get_books_genre +class TestGetBooksGenre: + + def test_get_books_genre_returns_current_dict(self): + collector = BooksCollector() + collector.add_new_book("Книга1") + collector.set_book_genre("Книга1", "Фантастика") + result = collector.get_books_genre() + assert result == {"Книга1": "Фантастика"} + + +# Тесты для метода get_books_for_children +class TestGetBooksForChildren: + + def test_get_books_for_children_success(self): + collector = BooksCollector() + collector.add_new_book("Сказка") + collector.add_new_book("Ужасы") + collector.set_book_genre("Сказка", "Мультфильмы") + collector.set_book_genre("Ужасы", "Ужасы") + result = collector.get_books_for_children() + assert "Сказка" in result + assert "Ужасы" not in result + + +# Тесты для метода add_book_in_favorites +class TestAddBookInFavorites: + + def test_add_book_in_favorites_success(self): + collector = BooksCollector() + collector.add_new_book("Марсианские хроники") + collector.add_book_in_favorites("Марсианские хроники") + assert "Марсианские хроники" in collector.get_list_of_favorites_books() + + def test_add_book_in_favorites_not_in_books_genre_failed(self): + collector = BooksCollector() + collector.add_book_in_favorites("Марсианские хроники") + assert "Марсианские хроники" not in collector.get_list_of_favorites_books() + + def test_add_book_in_favorites_duplicate_failed(self): + collector = BooksCollector() + collector.add_new_book("Марсианские хроники") + collector.add_book_in_favorites("Марсианские хроники") + collector.add_book_in_favorites("Марсианские хроники") + assert collector.favorites.count("Марсианские хроники") == 1 + + +# Тесты для метода delete_book_from_favorites +class TestDeleteBookFromFavorites: + + def test_delete_book_from_favorites_success(self): + collector = BooksCollector() + collector.add_new_book("Марсианские хроники") + collector.add_book_in_favorites("Марсианские хроники") + collector.delete_book_from_favorites("Марсианские хроники") + assert "Марсианские хроники" not in collector.get_list_of_favorites_books() + + +# Тесты для метода get_list_of_favorites_books +class TestGetListOfFavoritesBooks: + + def test_get_list_of_favorites_books_empty_initially(self): + collector = BooksCollector() + assert collector.get_list_of_favorites_books() == [] + + def test_get_list_of_favorites_books_returns_correct_list(self): + collector = BooksCollector() + collector.add_new_book("Марсианские хроники") + collector.add_book_in_favorites("Марсианские хроники") + result = collector.get_list_of_favorites_books() + assert result == ["Марсианские хроники"] \ No newline at end of file