From f5b49656b816247712f2dcbdbf94847bf51360e0 Mon Sep 17 00:00:00 2001 From: ivannosovec Date: Fri, 30 Jan 2026 10:01:12 +0300 Subject: [PATCH 1/2] =?UTF-8?q?=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD?= =?UTF-8?q?=D0=BD=D1=8B=D0=B9=20=20tests.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests.py | 236 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 219 insertions(+), 17 deletions(-) diff --git a/tests.py b/tests.py index 383385e..dc86ab8 100644 --- a/tests.py +++ b/tests.py @@ -1,24 +1,226 @@ -from main import BooksCollector +import pytest + -# класс TestBooksCollector объединяет набор тестов, которыми мы покрываем наше приложение BooksCollector -# обязательно указывать префикс Test class TestBooksCollector: - # пример теста: - # обязательно указывать префикс test_ - # дальше идет название метода, который тестируем add_new_book_ - # затем, что тестируем add_two_books - добавление двух книг - def test_add_new_book_add_two_books(self): - # создаем экземпляр (объект) класса BooksCollector + # Тест 1: Проверка инициализации коллектора + def test_init_books_collector(self): + collector = BooksCollector() + assert collector.books_genre == {} + assert collector.favorites == [] + assert collector.genre == ['Фантастика', 'Ужасы', 'Детективы', 'Мультфильмы', 'Комедии'] + assert collector.genre_age_rating == ['Ужасы', 'Детективы'] + + # Тест 2: Параметризованный тест для добавления новой книги + @pytest.mark.parametrize('book_name, expected', [ + ('Война и мир', True), # валидное название + ('A' * 40, True), # граничное значение (40 символов) + ('Книга', True), # обычное название + ('', False), # пустая строка + ('A' * 41, False), # слишком длинное название (41 символ) + ]) + def test_add_new_book(self, book_name, expected): + collector = BooksCollector() + collector.add_new_book(book_name) + + if expected: + assert book_name in collector.books_genre + assert collector.books_genre[book_name] == '' + else: + assert book_name not in collector.books_genre + + # Тест 3: Нельзя добавить одну книгу дважды + def test_add_new_book_twice(self): + collector = BooksCollector() + book_name = 'Мастер и Маргарита' + + collector.add_new_book(book_name) + collector.add_new_book(book_name) # повторная попытка + + assert len(collector.books_genre) == 1 + assert list(collector.books_genre.keys()) == [book_name] + + # Тест 4: Установка жанра для книги + def test_set_book_genre_valid(self): + collector = BooksCollector() + collector.add_new_book('1984') + collector.set_book_genre('1984', 'Фантастика') + + assert collector.get_book_genre('1984') == 'Фантастика' + + # Тест 5: Нельзя установить несуществующий жанр + def test_set_book_genre_invalid_genre(self): + collector = BooksCollector() + collector.add_new_book('Книга') + collector.set_book_genre('Книга', 'Несуществующий жанр') + + assert collector.get_book_genre('Книга') == '' + + # Тест 6: Получение жанра книги + def test_get_book_genre(self): + collector = BooksCollector() + collector.add_new_book('Преступление и наказание') + collector.set_book_genre('Преступление и наказание', 'Детективы') + + assert collector.get_book_genre('Преступление и наказание') == 'Детективы' + assert collector.get_book_genre('Несуществующая книга') is None + + # Тест 7: Получение книг с определенным жанром + def test_get_books_with_specific_genre(self): collector = BooksCollector() + + # Добавляем книги разных жанров + books = [ + ('Солярис', 'Фантастика'), + ('Оно', 'Ужасы'), + ('Шерлок Холмс', 'Детективы'), + ('Зеленая миля', 'Фантастика') + ] + + for name, genre in books: + collector.add_new_book(name) + collector.set_book_genre(name, genre) + + fantasy_books = collector.get_books_with_specific_genre('Фантастика') + assert len(fantasy_books) == 2 + assert 'Солярис' in fantasy_books + assert 'Зеленая миля' in fantasy_books - # добавляем две книги - collector.add_new_book('Гордость и предубеждение и зомби') - collector.add_new_book('Что делать, если ваш кот хочет вас убить') + # Тест 8: Получение всех книг + def test_get_books_genre(self): + collector = BooksCollector() + collector.add_new_book('Книга 1') + collector.add_new_book('Книга 2') + + books = collector.get_books_genre() + assert isinstance(books, dict) + assert len(books) == 2 + + # Тест 9: Получение книг для детей + def test_get_books_for_children(self): + collector = BooksCollector() + + # Книги с разными жанрами + children_books = [ + ('Гарри Поттер', 'Фантастика'), + ('Ну погоди!', 'Мультфильмы'), + ('Маска', 'Комедии') + ] + + adult_books = [ + ('Сияние', 'Ужасы'), + ('Десять негритят', 'Детективы') + ] + + # Добавляем все книги + for name, genre in children_books + adult_books: + collector.add_new_book(name) + collector.set_book_genre(name, genre) + + children_only = collector.get_books_for_children() + + # Проверяем, что только детские книги + assert len(children_only) == 3 + for name, _ in children_books: + assert name in children_only + + for name, _ in adult_books: + assert name not in children_only - # проверяем, что добавилось именно две - # словарь books_rating, который нам возвращает метод get_books_rating, имеет длину 2 - assert len(collector.get_books_rating()) == 2 + # Тест 10: Параметризованный тест для добавления в избранное + @pytest.mark.parametrize('book_in_dict, expected_in_favorites', [ + (True, True), # книга в словаре → добавляется в избранное + (False, False), # книги нет в словаре → не добавляется + ]) + def test_add_book_in_favorites(self, book_in_dict, expected_in_favorites): + collector = BooksCollector() + book_name = 'Избранная книга' + + if book_in_dict: + collector.add_new_book(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 - # напиши свои тесты ниже - # чтобы тесты были независимыми в каждом из них создавай отдельный экземпляр класса BooksCollector() \ No newline at end of file + # Тест 11: Нельзя добавить книгу в избранное дважды + def test_add_book_in_favorites_twice(self): + collector = BooksCollector() + book_name = 'Двойное избранное' + + collector.add_new_book(book_name) + collector.add_book_in_favorites(book_name) + collector.add_book_in_favorites(book_name) # повторная попытка + + assert len(collector.favorites) == 1 + assert collector.favorites == [book_name] + + # Тест 12: Удаление книги из избранного + def test_delete_book_from_favorites(self): + collector = BooksCollector() + book_name = 'Удаляемая книга' + + collector.add_new_book(book_name) + collector.add_book_in_favorites(book_name) + + # Проверяем, что книга добавилась + assert book_name in collector.favorites + + # Удаляем + collector.delete_book_from_favorites(book_name) + assert book_name not in collector.favorites + assert collector.favorites == [] + + # Тест 13: Удаление несуществующей книги из избранного + def test_delete_nonexistent_book_from_favorites(self): + collector = BooksCollector() + + # Попытка удалить несуществующую книгу не должна вызывать ошибку + collector.delete_book_from_favorites('Несуществующая книга') + assert collector.favorites == [] + + # Тест 14: Получение списка избранных книг + def test_get_list_of_favorites_books(self): + collector = BooksCollector() + + # Добавляем несколько книг в избранное + books = ['Книга 1', 'Книга 2', 'Книга 3'] + for book in books: + collector.add_new_book(book) + collector.add_book_in_favorites(book) + + favorites = collector.get_list_of_favorites_books() + + assert isinstance(favorites, list) + assert len(favorites) == 3 + assert favorites == books + + # Тест 15: Комплексный тест - несколько операций + def test_complex_scenario(self): + collector = BooksCollector() + + # Добавляем книги + collector.add_new_book('Властелин колец') + collector.add_new_book('Оно') + collector.add_new_book('Том и Джерри') + + # Устанавливаем жанры + collector.set_book_genre('Властелин колец', 'Фантастика') + collector.set_book_genre('Оно', 'Ужасы') + collector.set_book_genre('Том и Джерри', 'Мультфильмы') + + # Добавляем в избранное + collector.add_book_in_favorites('Властелин колец') + collector.add_book_in_favorites('Том и Джерри') + + # Проверяем + assert collector.get_book_genre('Властелин колец') == 'Фантастика' + assert len(collector.get_books_for_children()) == 2 # Фантастика и Мультфильмы + assert len(collector.get_list_of_favorites_books()) == 2 + + # Удаляем из избранного + collector.delete_book_from_favorites('Том и Джерри') + assert collector.get_list_of_favorites_books() == ['Властелин колец'] From 81a4600729154f1d01cfafa2ea70fba9bef0f350 Mon Sep 17 00:00:00 2001 From: ivannosovec Date: Fri, 30 Jan 2026 10:09:09 +0300 Subject: [PATCH 2/2] Revert "Sprint_4" --- .gitignore | 21 ------------------- __pycache__/main.cpython-38.pyc | Bin 0 -> 2030 bytes __pycache__/test.cpython-38-pytest-7.1.2.pyc | Bin 0 -> 8183 bytes 3 files changed, 21 deletions(-) delete mode 100644 .gitignore create mode 100644 __pycache__/main.cpython-38.pyc create mode 100644 __pycache__/test.cpython-38-pytest-7.1.2.pyc diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 1a1a737..0000000 --- a/.gitignore +++ /dev/null @@ -1,21 +0,0 @@ -# Python -__pycache__/ -*.py[cod] -*.class -*.so -.Python - -# pytest -.pytest_cache/ -.coverage -htmlcov/ - -# OS -.DS_Store -Thumbs.db - -# IDE -.vscode/ -.idea/ -*.swp -*.swo diff --git a/__pycache__/main.cpython-38.pyc b/__pycache__/main.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5786eeb8eea4dc1762353e0d9309eb8d1407edbf GIT binary patch literal 2030 zcmb7FO>Y}F5GA=Qc`dI$>NrlLq-jwYMHQgYy$FmT3DBD^PA)W9_a&t`k^T zpOPOEAN7~^nq1OrZ#{J$SBj*y9H1099CC-`n>RDm%kAw3qxSjlt5^3o82g0Da`R~N zgu2})@dr~(@ekDBi!M{*gtfdrt*&*HfPIY4lZ1)oHA$ z4HeK>SDUIq7jh68o5}G-cA6$~Y|_^Rs2%sB;-B@R_4r zWG>|I#aSJ*WwcYTV~}%Swn(%*2ib(A7d6vMhMJau-0WbfUdE^Dz^>Jq13!!3HrdX6 zX!6N}iVqdzn`s7$g&QZ#AP5FH4Q{xGf_Pp=ffBJUhSxDvOjj_}Xx~>VpVDN=E*)j& zIOiEh?KmQj9X4^rp0mH2e~L@*($D>zp9%AGEcf~n-LpmWx;b>z;C#qE|Nxns&x=o~kmG7eLRNArbM}w$8Bi2Qsy9I;!3aVl$mmbVLTYtbISzGYR zxX%yxJ`Z>(Ccjl8^zAdQl{b>zL3v#T{i%{X|CdX#IF2p3-(D zTq~9N%M3wTnG^_Ara0RmjYbLz)hl;Z>XK<55-?&Ab8`n`U3T3@={e$~M1Fmqj>z1? zZN@|1;FF^Y^0k|8hVLF0_n1(j9=iN;Ps}o8;eb*p>NtI?*J5odJ<^#j;SNk1F91IT zV0g*^w^f0A^S=KRbVua6px;B#M-jcy>0klL!L)4vn^o(>3aoEz>$F0=>v&eBEE-bA zsX8A)52bu_-W!!)%qAUgb|DTRZbN(zaTfx-oBI$yKrCv?X?T(ik{sRr^9CZQxt||2 c0zaq+HTS(k84sIv2Nc2M6525={-MtP1Ay7ZO8@`> literal 0 HcmV?d00001 diff --git a/__pycache__/test.cpython-38-pytest-7.1.2.pyc b/__pycache__/test.cpython-38-pytest-7.1.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b2898a8a207c1ae4014c5ac436acbbfebcdd6cd4 GIT binary patch literal 8183 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