diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 26d3352..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 105ce2d..0000000 --- a/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 590a59e..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 4b664cf..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/qa_python.iml b/.idea/qa_python.iml deleted file mode 100644 index c03f621..0000000 --- a/.idea/qa_python.iml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 35eb1dd..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/README.md b/README.md index 1cc701d..9a0bb67 100644 --- a/README.md +++ b/README.md @@ -1 +1,60 @@ -# qa_python \ No newline at end of file +# qa_python +## Тестирование + +В проекте реализовано **25 автоматизированных тестов** для класса `BooksCollector`. Тесты покрывают все методы и граничные случаи. + +### Список тестов по методам + +#### 1. `add_new_book` (5 тестов) +- Успешное добавление (имя ≤40 символов). +- Повторное добавление (дубликат). +- Пустое имя. +- Имя длиннее 40 символов. +- Ровно 40 символов. + +#### 2. `set_book_genre` (3 теста) +- Установка жанра для существующей книги. +- Книга отсутствует в словаре. +- Жанр не в списке допустимых. + +#### 3. `get_book_genre` (2 теста) +- Книга есть в словаре. +- Книги нет в словаре (`None`). + + +#### 4. `get_books_with_specific_genre` (3 теста) +- Найдены книги заданного жанра. +- Книг жанра нет (пустой список). +- Жанр не в списке допустимых (пустой список). + + +#### 5. `get_books_genre` (1 тест) +- Возврат полного словаря. + +#### 6. `get_books_for_children` (3 теста) +- Книги без возрастного рейтинга. +- Книги с возрастным рейтингом (не попадают). +- Книга без жанра (не попадает). + + +#### 7. `add_book_in_favorites` (3 теста) +- Успешное добавление. +- Книги нет в словаре. +- Дубликат в избранном. + + +#### 8. `delete_book_from_favorites` (2 теста) +- Успешное удаление. +- Книги нет в избранном (без ошибок). + + +#### 9. `get_list_of_favorites_books` (5 тестов) +- Пустой список. +- Одна книга в избранном. +- Несколько книг. +- После удаления одной книги. +<<<<<<< HEAD +- Без изменений при добавлении не‑избранного. +======= +- Без изменений при добавлении не‑избранного. +>>>>>>> cfd82bf64599a64cb339780f328b12d95b5289c4 diff --git a/__pycache__/main.cpython-314.pyc b/__pycache__/main.cpython-314.pyc new file mode 100644 index 0000000..b264371 Binary files /dev/null and b/__pycache__/main.cpython-314.pyc differ diff --git a/__pycache__/tests.cpython-314-pytest-9.0.2.pyc b/__pycache__/tests.cpython-314-pytest-9.0.2.pyc new file mode 100644 index 0000000..e24b145 Binary files /dev/null and b/__pycache__/tests.cpython-314-pytest-9.0.2.pyc differ diff --git a/tests.py b/tests.py index 383385e..4c38cef 100644 --- a/tests.py +++ b/tests.py @@ -1,3 +1,5 @@ +import pytest + from main import BooksCollector # класс TestBooksCollector объединяет набор тестов, которыми мы покрываем наше приложение BooksCollector @@ -18,7 +20,241 @@ def test_add_new_book_add_two_books(self): # проверяем, что добавилось именно две # словарь books_rating, который нам возвращает метод get_books_rating, имеет длину 2 - assert len(collector.get_books_rating()) == 2 + assert len(collector.books_genre) == 2 # напиши свои тесты ниже - # чтобы тесты были независимыми в каждом из них создавай отдельный экземпляр класса BooksCollector() \ No newline at end of file + # чтобы тесты были независимыми в каждом из них создавай отдельный экземпляр класса BooksCollector() + # 1. Тесты add_new_book + @pytest.mark.parametrize( + "book_name,expected_in_dict", + [ + ("Война и мир", True), # корректное имя + ("", False), # пустое имя + ("a" * 41, False), # >40 символов + ("a" * 40, True), # ровно 40 символов + ("1984", True), # короткое имя + ] + ) + def test_add_new_book_parametrized(self, book_name, expected_in_dict): + collector = BooksCollector() + collector.add_new_book(book_name) + + if expected_in_dict: + assert book_name in collector.books_genre + assert collector.books_genre[book_name] == "" + else: + assert book_name not in collector.books_genre + + # 2. Тесты set_book_genre + @pytest.mark.parametrize( + "book_name,genre,expected_genre", + [ + ("Гарри Поттер", "Фантастика", "Фантастика"), # валидный жанр + ("Оно", "Ужасы", "Ужасы"), # валидный жанр + ("Шерлок Холмс", "Детективы", "Детективы"), # валидный жанр + ("Винни-Пух", "Мультфильмы", "Мультфильмы"), # валидный жанр + ("Алиса", "Романтика", ""), # жанр не в списке genre + ("Неизвестная книга", "Фантастика", None), # книги нет в словаре + ] + ) + def test_set_book_genre_parametrized(self, book_name, genre, expected_genre): + collector = BooksCollector() + # Предварительно добавляем книгу (если она должна быть в словаре) + if book_name != "Неизвестная книга": + collector.add_new_book(book_name) + + collector.set_book_genre(book_name, genre) + + if expected_genre is None: + assert book_name not in collector.books_genre # книга не добавлена + else: + assert collector.get_book_genre(book_name) == expected_genre + + # 3. Тесты get_books_with_specific_genre + @pytest.mark.parametrize( + "genre,expected_books", + [ + ("Фантастика", ["Гарри Поттер", "Дюна"]), + ("Ужасы", ["Оно", "Сияние"]), + ("Детективы", ["Шерлок Холмс"]), + ("Мультфильмы", ["Винни-Пух"]), + ("Романтика", []), # жанр не в списке + ("Комедии", []), # нет книг в жанре + ] + ) + def test_get_books_with_specific_genre_parametrized(self, genre, expected_books): + collector = BooksCollector() + # Добавляем книги с разными жанрами + books_data = [ + ("Гарри Поттер", "Фантастика"), + ("Дюна", "Фантастика"), + ("Оно", "Ужасы"), + ("Сияние", "Ужасы"), + ("Шерлок Холмс", "Детективы"), + ("Винни-Пух", "Мультфильмы"), + ] + for name, genre_val in books_data: + collector.add_new_book(name) + collector.set_book_genre(name, genre_val) + + result = collector.get_books_with_specific_genre(genre) + assert sorted(result) == sorted(expected_books) + + # 4. Тесты get_books_for_children + @pytest.mark.parametrize( + "books_data,expected_children_books", + [ + ( + [("Винни-Пух", "Мультфильмы"), ("Алиса", "Комедии")], + ["Винни-Пух", "Алиса"] + ), + ( + [("Оно", "Ужасы"), ("Сияние", "Ужасы")], + [] + ), + ( + [("Дюна", "Фантастика"), ("Шерлок", "Детективы")], + ["Дюна"] # Детективы — с возрастным рейтингом + ), + ( + [("Без жанра", "")], + [] # книга без жанра не подходит + ), + ] + ) + def test_get_books_for_children_parametrized(self, books_data, expected_children_books): + collector = BooksCollector() + for name, genre in books_data: + collector.add_new_book(name) + if genre: # если жанр указан + collector.set_book_genre(name, genre) + + result = collector.get_books_for_children() + assert sorted(result) == sorted(expected_children_books) + + # 5. Тесты add_book_in_favorites + @pytest.mark.parametrize( + "book_name,is_in_books_genre,expected_in_favorites", + [ + ("Преступление и наказание", True, True), # книга есть в словаре + ("Мастер и Маргарита", True, True), # книга есть в словаре + ("Неизвестная книга", False, False), # книги нет в словаре + ("Преступление и наказание", True, False), # дубликат (уже в избранном) + ] + ) + def test_add_book_in_favorites_parametrized( + self, book_name, is_in_books_genre, expected_in_favorites + ): + collector = BooksCollector() + # Предварительно добавляем книгу, если нужно + if is_in_books_genre: + collector.add_new_book(book_name) + # Для случая дубликата — сразу добавляем в избранное + if book_name == "Преступление и наказание": + collector.add_book_in_favorites(book_name) + + collector.add_book_in_favorites(book_name) + + if expected_in_favorites: + assert book_name in collector.favorites + else: + assert book_name not in collector.favorites + + # 6. Тесты delete_book_from_favorites + @pytest.mark.parametrize( + "book_name,is_in_favorites,expected_removed", + [ + ("Идиот", True, True), # книга в избранном + ("Герой нашего времени", False, False), # книги нет в избранном + ] + ) + def test_delete_book_from_favorites_parametrized( + self, book_name, is_in_favorites, expected_removed + ): + collector = BooksCollector() + if is_in_favorites: + collector.add_new_book(book_name) + collector.add_book_in_favorites(book_name) + + collector.delete_book_from_favorites(book_name) + + if expected_removed: + assert book_name not in collector.favorites + else: + assert book_name not in collector.favorites # или в словаре, или нигде + + # 7. Тесты get_list_of_favorites_books + @pytest.mark.parametrize( + "favorites_data,expected_list", + [ + ([], []), # пустое избранное + (["Преступление и наказание"], ["Преступление и наказание"]), # одна книга + (["Мастер и Маргарита", "Идиот"], ["Мастер и Маргарита", "Идиот"]), # две книги + (["Война и мир"], ["Война и мир"]), # одна книга (проверка порядка) + ] + ) + def test_get_list_of_favorites_books_parametrized(self, favorites_data, expected_list): + collector = BooksCollector() + # Добавляем книги в словарь и в избранное + for book in favorites_data: + collector.add_new_book(book) + collector.add_book_in_favorites(book) + + result = collector.get_list_of_favorites_books() + assert sorted(result) == sorted(expected_list) + + # 8. Тесты get_books_genre + + @pytest.mark.parametrize( + "books_data,expected_dict", + [ + ( + [], + {} # пустой словарь + ), + ( + [("Война и мир", "Классика"), ("1984", "Фантастика")], + {"Война и мир": "Классика", "1984": "Фантастика"} # две книги с жанрами + ), + ( + [("Без жанра", "")], + {"Без жанра": ""} # книга без жанра + ), + ( + [("Дубровский", "Приключения"), ("Мёртвые души", "Сатира")], + {"Дубровский": "Приключения", "Мёртвые души": "Сатира"} # разные жанры + ), + ] + ) + def test_get_books_genre_parametrized(self, books_data, expected_dict): + collector = BooksCollector() + # Добавляем книги и задаём жанры + for name, genre in books_data: + collector.add_new_book(name) + if genre: # если жанр указан + collector.set_book_genre(name, genre) + + result = collector.get_books_genre() + assert result == expected_dict + + # 9. Тесты get_book_genre + @pytest.mark.parametrize( + "book_name,books_data,expected_genre", + [ + ("Война и мир", [("Война и мир", "Классика")], "Классика"), # книга есть, жанр задан + ("1984", [("1984", "Фантастика")], "Фантастика"), # книга есть, жанр задан + ("Неизвестная книга", [], None), # книги нет в словаре + ("Без жанра", [("Без жанра", "")], ""), # книга есть, но жанр не задан + ("Дубровский", [("Дубровский", "Приключения")], "Приключения"), # другой жанр + ] + ) + def test_get_book_genre_parametrized(self, book_name, books_data, expected_genre): + collector = BooksCollector() + # Предварительно добавляем книги из books_data + for name, genre in books_data: + collector.add_new_book(name) + if genre: + collector.set_book_genre(name, genre) + + result = collector.get_book_genre(book_name) + assert result == expected_genre