From a728d1cfec889dc02324f2c5049f5b0f08e90868 Mon Sep 17 00:00:00 2001 From: Kirill Martyushov Date: Fri, 19 Dec 2025 21:42:22 +0300 Subject: [PATCH 1/8] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=AE=D0=BD=D0=B8=D1=82=20=D1=82=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D0=BE=D0=B2=20=D0=B4=D0=BB=D1=8F=20=D0=BF=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D0=B8=20=D0=BA=D0=BB=D0=B0=D1=81?= =?UTF-8?q?=D1=81=D0=B0=20BooksCollector,=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BE=D0=BF=D0=B8=D1=81=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D1=82=D0=B5=D1=81=D1=82=D0=BE=D0=B2=20?= =?UTF-8?q?=D0=B2=20=20READMDE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 50 ++++- __pycache__/books_data.cpython-314.pyc | Bin 0 -> 511 bytes .../conftest.cpython-314-pytest-9.0.1.pyc | Bin 0 -> 758 bytes __pycache__/main.cpython-314.pyc | Bin 0 -> 3686 bytes __pycache__/test.cpython-314-pytest-9.0.1.pyc | Bin 0 -> 26641 bytes books_data.py | 7 + conftest.py | 12 ++ test.py | 191 ++++++++++++++++++ 8 files changed, 259 insertions(+), 1 deletion(-) create mode 100644 __pycache__/books_data.cpython-314.pyc create mode 100644 __pycache__/conftest.cpython-314-pytest-9.0.1.pyc create mode 100644 __pycache__/main.cpython-314.pyc create mode 100644 __pycache__/test.cpython-314-pytest-9.0.1.pyc create mode 100644 books_data.py create mode 100644 conftest.py create mode 100644 test.py diff --git a/README.md b/README.md index 1cc701d..c6f0d89 100644 --- a/README.md +++ b/README.md @@ -1 +1,49 @@ -# qa_python \ No newline at end of file +# Тестирование приложения BooksCollector + +Проект содержит набор автотестов для проверки работоспособности приложения `BooksCollector`. Тесты написаны на языке **Python** с использованием фреймворка **pytest**. + +## Структура проекта + +* **`main.py`** — содержит исходный код класса `BooksCollector`. +* **`test.py`** — основной файл с тестами (класс `TestBooksCollector`). +* **`conftest.py`** — хранит общую фикстуру `collector_with_books`, которая автоматически подтягивается в тесты. +* **`books_data.py`** — содержит тестовые данные и параметры (например, список `BOOK_WITH_GENRE`), вынесенные из кода тестов. + + + +## Описание реализованных тестов + +### 1. Добавление книг в коллекцию (`add_new_book`) +* **test_add_new_book_add_two_books**: Проверка успешного добавления нескольких книг в пустую коллекцию. +* **test_add_new_book_ignore_duplicate_name**: Проверка того, что книга с уже существующим именем не добавляется повторно. +* **test_add_new_book_igonore_empty_name**: Проверка запрета на добавление книги с пустым названием. +* **test_add_new_book_igonore_book_name_longer_than_41_symblos**: Проверка граничного значения длины названия: книги с именами длиной 41 символ и более не добавляются. + +### 2. Установка и получение жанров (`set_book_genre`, `get_book_genre`) +* **test_set_book_genre**: (Параметризованный) Проверка корректной установки допустимого жанра для существующих книг. +* **test_set_book_genre_ignore_genre_not_in_list**: Проверка того, что жанр не устанавливается, если его нет в списке доступных (`self.genre`). +* **test_set_book_genre_ignore_book_not_in_collection**: Проверка того, что невозможно установить жанр книге, которой нет в коллекции. +* **test_get_book_genre_book_exist**: Проверка получения жанра для книги, которая есть в коллекции. +* **test_get_book_genre_book_not_exist**: Проверка, что при запросе жанра для отсутствующей книги возвращается `None`. + +### 3. Фильтрация и словари (`get_books_genre`, `get_books_with_specific_genre`) +* **test_get_books_genre_book_exist**: Проверка получения полного словаря `books_genre`. Тест подтверждает соответствие итогового словаря эталонному набору данных. +* **test_get_books_with_specific_genre**: (Параметризованный) Проверка фильтрации книг по конкретному жанру. Подтверждает, что метод возвращает список названий книг, соответствующих запросу. + +### 4. Детская библиотека (`get_books_for_children`) +* **test_get_books_for_children_only_children_genres**: Проверка корректной фильтрации книг для детей. Убеждаемся, что в список попадают только безопасные жанры без возрастного рейтинга. +* **test_get_books_for_children_no_children_genres**: (Параметризованный) Проверка исключения жанров "Ужасы" и "Детективы" из выдачи для детей. + +### 5. Работа с «Избранным» (`favorites`) +* **test_add_book_in_favorites_one_book**: Проверка успешного добавления книги в список избранного. +* **test_add_book_in_favorites_ignore_duplicates**: Проверка защиты от повторного добавления одной и той же книги в избранное. +* **tes_delete_book_from_favorites_one_book**: Проверка удаления единственной книги из избранного. +* **test_delete_book_from_favorites_one_of_many**: Проверка точечного удаления: при удалении одной книги остальные должны остаться в списке. +* **test_delete_book_from_favorites_book_not_in_favorites**: Проверка того, что попытка удаления книги, которой нет в избранном, не вызывает ошибок и не меняет список. +* **test_get_list_of_favorites_books_return_favorites**: Проверка получения полного списка избранных книг. +* **test_get_list_of_favorites_books_empty_favorites**: Проверка работы метода при пустом списке избранного. + +## Технические особенности тестов +* **Фикстуры**: Применяется фикстура `collector_with_books` из `conftest.py` для быстрой предустановки объекта с набором данных. +* **Параметризация**: Используется `@pytest.mark.parametrize` с данными из `books_data.py`. +* **Множества (Set)**: Применяются для сравнения списков, где порядок элементов не имеет значения. \ No newline at end of file diff --git a/__pycache__/books_data.cpython-314.pyc b/__pycache__/books_data.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..802e4946667bc97eae4a243792b5a2f22a649875 GIT binary patch literal 511 zcmXw0O-mb56nztCVpL2(iy&4Q5sF$eZd_QAA_=K21%=mAH$t$)Md(LD%q#>KCJGhe z2SisYc3~-WQHa4Q(R}nToVN>E75WDP`2#&KZ6CZl_v4&%?|t()IM^?EMlNDWX$bLK z2mg=%pVOJ5vn!;KhU1ey*+Xkei`FlDX#=v)@i|sj$o@$&J>Whf9A8m}r}C;`;}%tQ zV&glibbm0ri#i&-CHH}benAO!l}AbCXe+p9LHEX$#<_YxT$8Bl1^3C{@P@#rI?tV|oNP-J!W zWqj?$>*w+1*ousO6CL72Yc#sB{wkeGe$2+_*59U5@3!KJjqHY#-fjgJKco`w`^~2r z{WknpVr!nJ-D4QWFDs1M7|dr)Yw%zP=EJ77gvcA1YfWnkGZC24rZtA~FifXC;2-wq ILm89gKNW1_EC2ui literal 0 HcmV?d00001 diff --git a/__pycache__/conftest.cpython-314-pytest-9.0.1.pyc b/__pycache__/conftest.cpython-314-pytest-9.0.1.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0b826d7d403825b6507bc85211e42403350fc735 GIT binary patch literal 758 zcmZ8f&ubGw6n^_Nn>4AhB&J?=7nGJ&>?x-rMOvZ>g|tLzFVSV2Om#8Y4KovBz(Yhq z{SO2$Uj1(@ipoIg#f!Jr`~$w(WFz*$%)IZt_q~1J%-&uu(|>16uRwJU zdA_CG0MGa>ann=8@^&0QXFGAPM>;&F7`d{&x3}vbHXhae2eoFa_TQ)m(llJtm$*%! zjZ$WoeqaFYR1Os3{yM-2F=n8miwvn-MVvO!0P(B3HkCDy);EOcm-h{4Z|J}BPR0q24jDLuKR;=GDyG} zp*)PE4N68d#xkB#;VU%2y$jQ55emCI3?9wvF;R`;bB$4wO zXdb7b@;?>U-G1C1_Q)1pMJV5h-NNl$QxxS4;0?SkoPu)-Yp6uE-rBG13)N7{Qw`MO JAL%8%{sM;AtbqUk literal 0 HcmV?d00001 diff --git a/__pycache__/main.cpython-314.pyc b/__pycache__/main.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3b56b32f80303ead1c471f2159991927f424f1a2 GIT binary patch literal 3686 zcmb7GU2Gdg5Z<%zQYUtN*CuIb>?BU?xVeTp4Yg27LzL1V2~`cz0VxlK!?iD|!Lh^M zg$g84C`hC#5>!Gee-f2IsCgnl3#Alz-{+c*WCWim=;Ngl^p zOW@b0b%H4TQyh%Aei1mM;z@X51XggG;)NZB`s;#90?itlZVS$c#D3J&yr$BWkqF5+*N@bBH8sHJc^RQO^;;KI3CHGV24xVRFXX&)BL!oSW@E z%b|P7=jy-g{R>yO$+YaHa5sqUo!1Q8o73{E9*V)S`Fv_Y)6vg(oQgOSNM$l=Uc0Db znCwskob^g1jD8XXKq_{W#C}WcFNsl0j9x!c66N1T`9|tybS?9pTue;eK3_^qnTe_L z(EgPZr9jvUgg<)bkHFyHUNU-&vqYI9;nMZ^VV@!X65Hdf)XeM0K$nRkK4&8{_3?sn zY)rq~)jLC5q>CB>)ZG77Zd&#*xTqgY0XjsA?n8kCI-Vse<`+vHQL7`m?vLIOe(3q8XMOl+dFa4aY~%^cA9bLqcWx7!BW$hagxHykQ9^rR za@AG5#q=Q%TgVUuzU<`PRyC#;9dT+xh(AQx^tnN<_k;&?7UbX9yaZW?1RhjWF=>2^Y9Ju{f<8rrP4 zda?V-=?EdMqz^2sxbig$*#acE1>J5*EiP*L45U!TC?u1;53iZ7Ud$R7RDDrPXXmnM zhf0ibb{p!Q0Ub{tk4GXA=ce{n(Qi84ez<{&J6f~IKMU(a=wflxH-Pl?hv3ijhpr1> z_pJ7;M-G=`!=+f#iX}_2aVs`nj7?Zl)=dc5v@{sNC#EmgMg|^oGnmF3 z+N`IJhZ8Ojxhi;q16~X!(Etjh9UTH8^G*%e<4|y}K-KhxY%W8gGS{*l9=yi6y*141 z?d_p$p|3Z?UG-@Y5P{x))7MiD^_M~;R%oOY8nZ%U#n9o)r&mst#m-WA%nFYc#j!Q* z*Vli1z4+*pWofV^$(AJFh!v$#pjSAF^cn=N?vNkfVVmtxI#?+NeSJ=XIoL2h8ORAN zn>5ik%Oa5$sI7PVgz=Lt=SD}hEcT^ zAvAUi)fNh`Y7e5*lhJaTp*aA}(ZWIgfpS24fBN!t zDKKCK2Cm17f&B=};DgEGe`YQg>&DC#!dsNf>V{gFtGU43((MBcj_hEI)nCU;%`)2i zZ(e@W^!2hMQ+PhYvrod8F+TC&W!$E!3x&*54*LOBePt&Sj}?*P>fVS@*0pTEli%!cNTX&T>W9+5tn{e=$q{qR8ZHeRe Ryd1~<<2l0hZ4eM_!hh?32O9tY literal 0 HcmV?d00001 diff --git a/__pycache__/test.cpython-314-pytest-9.0.1.pyc b/__pycache__/test.cpython-314-pytest-9.0.1.pyc new file mode 100644 index 0000000000000000000000000000000000000000..50df83f76bf634f6f4c9c2c7fa865e5652b903e8 GIT binary patch literal 26641 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 OPemgKuWBS&`Tqf__iLE| literal 0 HcmV?d00001 diff --git a/books_data.py b/books_data.py new file mode 100644 index 0000000..c916e02 --- /dev/null +++ b/books_data.py @@ -0,0 +1,7 @@ +BOOK_WITH_GENRE = [ + ["Цветы для Элджернона", "Фантастика"], + ["Оно", "Ужасы"], + ["Убийство в Восточном экспрессе", "Детективы"], + ["Приключения Винни", "Мультфильмы"], + ["Горе от ума", "Комедии"] + ] \ No newline at end of file diff --git a/conftest.py b/conftest.py new file mode 100644 index 0000000..1c9d442 --- /dev/null +++ b/conftest.py @@ -0,0 +1,12 @@ +import pytest +from main import BooksCollector +from books_data import BOOK_WITH_GENRE + + +@pytest.fixture +def collector_with_books(): + collector = BooksCollector() + for name, genre in BOOK_WITH_GENRE: + collector.add_new_book(name) + collector.set_book_genre(name, genre) + return collector \ No newline at end of file diff --git a/test.py b/test.py new file mode 100644 index 0000000..5293539 --- /dev/null +++ b/test.py @@ -0,0 +1,191 @@ +import pytest +from main import BooksCollector +from books_data import BOOK_WITH_GENRE + +# класс TestBooksCollector объединяет набор тестов, которыми мы покрываем наше приложение BooksCollector +# обязательно указывать префикс Test +class TestBooksCollector: + + # пример теста: + # обязательно указывать префикс test_ + # дальше идет название метода, который тестируем add_new_book_ + # затем, что тестируем add_two_books - добавление двух книг + def test_add_new_book_add_two_books(self): + # создаем экземпляр (объект) класса BooksCollector + collector = BooksCollector() + + # добавляем две книги + collector.add_new_book('Гордость и предубеждение и зомби') + collector.add_new_book('Что делать, если ваш кот хочет вас убить') + + # проверяем, что добавилось именно две + # словарь books_rating, который нам возвращает метод get_books_gengre, имеет длину 2 + assert len(collector.get_books_genre()) == 2 + + # Тест на проверку игнорирования дубликатов при добавлении книги + def test_add_new_book_ignore_duplicate_name(self): + collector = BooksCollector() + # Добавляем две книги с одинаковым именем + collector.add_new_book('Гордость и предубеждение и зомби') + collector.add_new_book('Гордость и предубеждение и зомби') + # Проверяем, что добавиласьь только одна книга + assert len(collector.get_books_genre()) == 1 + + # Тест на проверку игнорирования пустого имени при добавлении книги + def test_add_new_book_igonore_empty_name(self): + collector = BooksCollector() + # Добавляем книгу с пустым именем + collector.add_new_book("") + # Проверяем, что книга не добавилась + assert len(collector.get_books_genre()) == 0 + + # Тест на проверку игнорирования добавления книги с именем длинее 40 символа + def test_add_new_book_igonore_book_name_longer_than_41_symblos(self): + collector = BooksCollector() + # Создаем имя длиной 41 символа + name = "A" * 41 + # Добавляем книгу с именем длиной 41 символа + collector.add_new_book(name) + # # Проверяем, что книга не добавилась + assert len(collector.get_books_genre()) == 0 + + # Тест на проверку установки жанра книги черрез параметризацию + @pytest.mark.parametrize("book, genre", BOOK_WITH_GENRE) + def test_set_book_genre(self, book, genre): + collector = BooksCollector() + # Добавляем книгу + collector.add_new_book(book) + # Устанавливаем жанр книги + collector.set_book_genre(book, genre) + # Проверяем, что жанр книги установлен правильно + assert collector.get_book_genre(book) == genre + + # Тест на проверку игнорирования установки жанра книги не из списка жанров + def test_set_book_genre_ignore_genre_not_in_list(self): + collector = BooksCollector() + # Добавляем книгу + collector.add_new_book('Гордость и предубеждение и зомби') + # Добаляем жанр не из списка жанров + collector.set_book_genre('Гордость и предубеждение и зомби', 'Роман') + # Проверяем, что жанр книги не установлен + assert collector.get_book_genre('Гордость и предубеждение и зомби') == '' + + # Тест на проверку игнорирования установки жанра книги, которой нет в коллекции + def test_set_book_genre_ignore_book_not_in_collection(self): + collector = BooksCollector() + # Добавляем жанр книге, которой нет в коллекции + collector.set_book_genre('Гордость и предубеждение и зомби', 'Ужасы') + # Проверяем, что жанр книги не установлен + assert collector.get_book_genre('Гордость и предубеждение и зомби') is None + + # Тест на проверку получения жанра книги с фикстурой + def test_get_book_genre_book_exist(self, collector_with_books): + collector = collector_with_books + assert collector.get_book_genre("Оно") == "Ужасы" + + # Тест на проверку получения жанра книги, которой нет в коллекции, с фикстурой + def test_get_book_genre_book_not_exist(self, collector_with_books): + collector = collector_with_books + assert collector.get_book_genre("Неизвестная книга") is None + + # Тест на проверку получения списка книг с определнным жанром черрез параметризацию + @pytest.mark.parametrize("book, genre", BOOK_WITH_GENRE) + def test_get_books_with_specific_genre(self, book, genre, collector_with_books): + collector = collector_with_books + # Добавляем книгу + collector.add_new_book(book) + # Устанавливаем жанр книги + collector.set_book_genre(book, genre) + # Проверяем, что книга возвращается в списке книг с определенным жанром + assert book in collector.get_books_with_specific_genre(genre) + + # Тест на проверку получения словаря books_genre + def test_get_books_genre_book_exist (self, collector_with_books): + collector = collector_with_books + # Преобразуем список книг с жанрами в словарь + dic_books = dict(BOOK_WITH_GENRE) + # Проверяем, что метод возвращает правильный словарь книг с жанрами + assert collector.get_books_genre() == dic_books + + # Тест на проверку получения списка книг, подходящих для детей + def test_get_books_for_children_only_children_genres(self, collector_with_books): + collector = collector_with_books + # Получаем список книг для детей + book_for_children = set(collector.get_books_for_children()) + # Проверяем, что в списке книг для детей только книги без возрастного рейтинга + assert book_for_children == {"Цветы для Элджернона", "Приключения Винни", "Горе от ума"} + + # Тест на проверку получения списка книг, подходящих для детей, когда все книги имеют возрастной рейтинг + @pytest.mark.parametrize("adult_genre", ['Ужасы', 'Детективы']) + def test_get_books_for_children_no_children_genres(self, adult_genre): + collector = BooksCollector() + # Добавляем книгу с возрастныи рейтингом + collector.add_new_book('Взрослая книга') + collector.set_book_genre('Взрослая книга', adult_genre) + # Проверяем, что список книг для детей пустой + assert collector.get_books_for_children() == [] + + #Тест на проверку добавление книги в избранное + def test_add_book_in_favorites_one_book(self, collector_with_books): + collector = collector_with_books + # Добавляем книгу в избранное + collector.add_book_in_favorites("Приключения Винни") + # Проверяем, что книга добавлена в избраное + assert "Приключения Винни" in collector.get_list_of_favorites_books() + + #Тест на проверку игнорирования дубликатов при добавлении книги в избранное + def test_add_book_in_favorites_ignore_duplicates(self, collector_with_books): + collector = collector_with_books + # Добавляем книгу в избранное + collector.add_book_in_favorites("Приключения Винни") + collector.add_book_in_favorites("Приключения Винни") + # Проверяем, что книга добавлена в избраное + assert len(collector.get_list_of_favorites_books()) == 1 + + #Тест на проверку удаления книги из избранного + def tes_delete_book_from_favorites_one_book(self, collector_with_books): + collector = collector_with_books + # Добавляем книгу в избранное + collector.add_book_in_favorites("Приключения Винни") + # Удаляем книгу из избранного + collector.delete_book_from_favorites("Приключения Винни") + # Проверяем, что книга удалена из избраного + assert "Приключения Винни" not in collector.get_list_of_favorites_books() + + #Тест на проверку удаления только одной книги из избранного при наличии нескольких книг + def test_delete_book_from_favorites_one_of_many(self, collector_with_books): + collector = collector_with_books + # Добавляем книги в избранное + collector.add_book_in_favorites("Приключения Винни") + collector.add_book_in_favorites("Горе от ума") + # Удаляем одну книгу из избранного + collector.delete_book_from_favorites("Приключения Винни") + # Проверяем, что удалена только одна книга из избраного + assert collector.get_list_of_favorites_books() == ["Горе от ума"] + + # Тест на проверку не удаления книги из избранного, если ее там нет + def test_delete_book_from_favorites_book_not_in_favorites(self, collector_with_books): + collector = collector_with_books + # Добавляем книгу в избранное + collector.add_book_in_favorites("Приключения Винни") + # Пытаемся удалить книгу, которой нет в избранном + collector.delete_book_from_favorites("Горе от ума") + # Проверяем, что в избранном осталась только добавленная книга + assert collector.get_list_of_favorites_books() == ["Приключения Винни"] + + # Тест на проверку получения списка избранных книг + def test_get_list_of_favorites_books_return_favorites(self, collector_with_books): + collector = collector_with_books + # Добавляем книги в избранное + collector.add_book_in_favorites("Приключения Винни") + collector.add_book_in_favorites("Горе от ума") + # Проверяем, что метод возвращает правильный список избранных книг + assert collector.get_list_of_favorites_books() == ["Приключения Винни", "Горе от ума"] + + # Тест на проверку получения списка избранных книг, когда избранное пусто + def test_get_list_of_favorites_books_empty_favorites(self, collector_with_books): + collector = collector_with_books + # Проверяем, что метод возвращает пустой список избранных книг + assert collector.get_list_of_favorites_books() == [] + + \ No newline at end of file From b3c65b2fb272d4db3055bf213c426c17b57106c1 Mon Sep 17 00:00:00 2001 From: Kirill Martyushov Date: Sat, 20 Dec 2025 18:14:16 +0300 Subject: [PATCH 2/8] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B7=D0=B0=D0=BC=D0=B5=D1=87=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20=D0=BF=D0=BE=20=D1=84=D0=B8=D0=BA=D1=81?= =?UTF-8?q?=D1=82=D1=83=D1=80=D0=B0=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- conftest.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/conftest.py b/conftest.py index 1c9d442..ccf63da 100644 --- a/conftest.py +++ b/conftest.py @@ -3,6 +3,12 @@ from books_data import BOOK_WITH_GENRE +# Фикстура для создания пустого эксземпляра BooksCollector +@pytest.fixture +def collector(): + return BooksCollector() + +# Фикстура для создания экземпляра BooksCollector с предзаполненными книгами и жанрами @pytest.fixture def collector_with_books(): collector = BooksCollector() From 94c1d4b15d58b6ea64a06a2f0470f90e50fae618 Mon Sep 17 00:00:00 2001 From: Kirill Martyushov Date: Sat, 20 Dec 2025 19:01:22 +0300 Subject: [PATCH 3/8] =?UTF-8?q?=D0=A3=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=BF=D0=B0=D0=BF=D0=BE=D0=BA=20=D0=B8=20=D1=84=D0=B0?= =?UTF-8?q?=D0=B9=D0=BB=D0=BE=D0=B2,=20=D0=BA=D0=BE=D1=82=D0=BE=D1=80?= =?UTF-8?q?=D1=8B=D0=B5=20=D0=BD=D0=B5=20=D0=BE=D1=82=D0=BD=D0=BE=D1=81?= =?UTF-8?q?=D1=8F=D1=82=D1=81=D1=8F=20=D0=BA=20=D1=80=D0=B5=D1=88=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D1=8E=20=D0=B7=D0=B0=D0=B4=D0=B0=D1=87=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __pycache__/books_data.cpython-314.pyc | Bin 511 -> 0 bytes .../conftest.cpython-314-pytest-9.0.1.pyc | Bin 758 -> 0 bytes __pycache__/main.cpython-314.pyc | Bin 3686 -> 0 bytes __pycache__/main.cpython-38.pyc | Bin 2030 -> 0 bytes __pycache__/test.cpython-314-pytest-9.0.1.pyc | Bin 26641 -> 0 bytes __pycache__/test.cpython-38-pytest-7.1.2.pyc | Bin 8183 -> 0 bytes tests.py | 24 ------------------ 7 files changed, 24 deletions(-) delete mode 100644 __pycache__/books_data.cpython-314.pyc delete mode 100644 __pycache__/conftest.cpython-314-pytest-9.0.1.pyc delete mode 100644 __pycache__/main.cpython-314.pyc delete mode 100644 __pycache__/main.cpython-38.pyc delete mode 100644 __pycache__/test.cpython-314-pytest-9.0.1.pyc delete mode 100644 __pycache__/test.cpython-38-pytest-7.1.2.pyc delete mode 100644 tests.py diff --git a/__pycache__/books_data.cpython-314.pyc b/__pycache__/books_data.cpython-314.pyc deleted file mode 100644 index 802e4946667bc97eae4a243792b5a2f22a649875..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 511 zcmXw0O-mb56nztCVpL2(iy&4Q5sF$eZd_QAA_=K21%=mAH$t$)Md(LD%q#>KCJGhe z2SisYc3~-WQHa4Q(R}nToVN>E75WDP`2#&KZ6CZl_v4&%?|t()IM^?EMlNDWX$bLK z2mg=%pVOJ5vn!;KhU1ey*+Xkei`FlDX#=v)@i|sj$o@$&J>Whf9A8m}r}C;`;}%tQ zV&glibbm0ri#i&-CHH}benAO!l}AbCXe+p9LHEX$#<_YxT$8Bl1^3C{@P@#rI?tV|oNP-J!W zWqj?$>*w+1*ousO6CL72Yc#sB{wkeGe$2+_*59U5@3!KJjqHY#-fjgJKco`w`^~2r z{WknpVr!nJ-D4QWFDs1M7|dr)Yw%zP=EJ77gvcA1YfWnkGZC24rZtA~FifXC;2-wq ILm89gKNW1_EC2ui diff --git a/__pycache__/conftest.cpython-314-pytest-9.0.1.pyc b/__pycache__/conftest.cpython-314-pytest-9.0.1.pyc deleted file mode 100644 index 0b826d7d403825b6507bc85211e42403350fc735..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 758 zcmZ8f&ubGw6n^_Nn>4AhB&J?=7nGJ&>?x-rMOvZ>g|tLzFVSV2Om#8Y4KovBz(Yhq z{SO2$Uj1(@ipoIg#f!Jr`~$w(WFz*$%)IZt_q~1J%-&uu(|>16uRwJU zdA_CG0MGa>ann=8@^&0QXFGAPM>;&F7`d{&x3}vbHXhae2eoFa_TQ)m(llJtm$*%! zjZ$WoeqaFYR1Os3{yM-2F=n8miwvn-MVvO!0P(B3HkCDy);EOcm-h{4Z|J}BPR0q24jDLuKR;=GDyG} zp*)PE4N68d#xkB#;VU%2y$jQ55emCI3?9wvF;R`;bB$4wO zXdb7b@;?>U-G1C1_Q)1pMJV5h-NNl$QxxS4;0?SkoPu)-Yp6uE-rBG13)N7{Qw`MO JAL%8%{sM;AtbqUk diff --git a/__pycache__/main.cpython-314.pyc b/__pycache__/main.cpython-314.pyc deleted file mode 100644 index 3b56b32f80303ead1c471f2159991927f424f1a2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3686 zcmb7GU2Gdg5Z<%zQYUtN*CuIb>?BU?xVeTp4Yg27LzL1V2~`cz0VxlK!?iD|!Lh^M zg$g84C`hC#5>!Gee-f2IsCgnl3#Alz-{+c*WCWim=;Ngl^p zOW@b0b%H4TQyh%Aei1mM;z@X51XggG;)NZB`s;#90?itlZVS$c#D3J&yr$BWkqF5+*N@bBH8sHJc^RQO^;;KI3CHGV24xVRFXX&)BL!oSW@E z%b|P7=jy-g{R>yO$+YaHa5sqUo!1Q8o73{E9*V)S`Fv_Y)6vg(oQgOSNM$l=Uc0Db znCwskob^g1jD8XXKq_{W#C}WcFNsl0j9x!c66N1T`9|tybS?9pTue;eK3_^qnTe_L z(EgPZr9jvUgg<)bkHFyHUNU-&vqYI9;nMZ^VV@!X65Hdf)XeM0K$nRkK4&8{_3?sn zY)rq~)jLC5q>CB>)ZG77Zd&#*xTqgY0XjsA?n8kCI-Vse<`+vHQL7`m?vLIOe(3q8XMOl+dFa4aY~%^cA9bLqcWx7!BW$hagxHykQ9^rR za@AG5#q=Q%TgVUuzU<`PRyC#;9dT+xh(AQx^tnN<_k;&?7UbX9yaZW?1RhjWF=>2^Y9Ju{f<8rrP4 zda?V-=?EdMqz^2sxbig$*#acE1>J5*EiP*L45U!TC?u1;53iZ7Ud$R7RDDrPXXmnM zhf0ibb{p!Q0Ub{tk4GXA=ce{n(Qi84ez<{&J6f~IKMU(a=wflxH-Pl?hv3ijhpr1> z_pJ7;M-G=`!=+f#iX}_2aVs`nj7?Zl)=dc5v@{sNC#EmgMg|^oGnmF3 z+N`IJhZ8Ojxhi;q16~X!(Etjh9UTH8^G*%e<4|y}K-KhxY%W8gGS{*l9=yi6y*141 z?d_p$p|3Z?UG-@Y5P{x))7MiD^_M~;R%oOY8nZ%U#n9o)r&mst#m-WA%nFYc#j!Q* z*Vli1z4+*pWofV^$(AJFh!v$#pjSAF^cn=N?vNkfVVmtxI#?+NeSJ=XIoL2h8ORAN zn>5ik%Oa5$sI7PVgz=Lt=SD}hEcT^ zAvAUi)fNh`Y7e5*lhJaTp*aA}(ZWIgfpS24fBN!t zDKKCK2Cm17f&B=};DgEGe`YQg>&DC#!dsNf>V{gFtGU43((MBcj_hEI)nCU;%`)2i zZ(e@W^!2hMQ+PhYvrod8F+TC&W!$E!3x&*54*LOBePt&Sj}?*P>fVS@*0pTEli%!cNTX&T>W9+5tn{e=$q{qR8ZHeRe Ryd1~<<2l0hZ4eM_!hh?32O9tY diff --git a/__pycache__/main.cpython-38.pyc b/__pycache__/main.cpython-38.pyc deleted file mode 100644 index 5786eeb8eea4dc1762353e0d9309eb8d1407edbf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 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@`> diff --git a/__pycache__/test.cpython-314-pytest-9.0.1.pyc b/__pycache__/test.cpython-314-pytest-9.0.1.pyc deleted file mode 100644 index 50df83f76bf634f6f4c9c2c7fa865e5652b903e8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26641 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 OPemgKuWBS&`Tqf__iLE| diff --git a/__pycache__/test.cpython-38-pytest-7.1.2.pyc b/__pycache__/test.cpython-38-pytest-7.1.2.pyc deleted file mode 100644 index b2898a8a207c1ae4014c5ac436acbbfebcdd6cd4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8183 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 Date: Sat, 20 Dec 2025 19:02:25 +0300 Subject: [PATCH 4/8] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BE=D0=BF=D0=B8=D1=81=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=B2=20README?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c6f0d89..8b5acea 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ ### 5. Работа с «Избранным» (`favorites`) * **test_add_book_in_favorites_one_book**: Проверка успешного добавления книги в список избранного. * **test_add_book_in_favorites_ignore_duplicates**: Проверка защиты от повторного добавления одной и той же книги в избранное. -* **tes_delete_book_from_favorites_one_book**: Проверка удаления единственной книги из избранного. +* **test_delete_book_from_favorites_one_book**: Проверка удаления единственной книги из избранного. * **test_delete_book_from_favorites_one_of_many**: Проверка точечного удаления: при удалении одной книги остальные должны остаться в списке. * **test_delete_book_from_favorites_book_not_in_favorites**: Проверка того, что попытка удаления книги, которой нет в избранном, не вызывает ошибок и не меняет список. * **test_get_list_of_favorites_books_return_favorites**: Проверка получения полного списка избранных книг. From c230847a7ac8f9e87628cfc5d4f532e034f59406 Mon Sep 17 00:00:00 2001 From: Kirill Martyushov Date: Sat, 20 Dec 2025 19:04:04 +0300 Subject: [PATCH 5/8] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B7=D0=B0=D0=BC=D0=B5=D1=87=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=BF=D0=BE=20=D1=82=D0=B5=D1=81=D1=82?= =?UTF-8?q?=D0=B0=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test.py | 95 +++++++++++++++++++++++++++------------------------------ 1 file changed, 45 insertions(+), 50 deletions(-) diff --git a/test.py b/test.py index 5293539..09bd414 100644 --- a/test.py +++ b/test.py @@ -1,4 +1,5 @@ import pytest +from conftest import collector from main import BooksCollector from books_data import BOOK_WITH_GENRE @@ -10,10 +11,7 @@ class TestBooksCollector: # обязательно указывать префикс test_ # дальше идет название метода, который тестируем add_new_book_ # затем, что тестируем add_two_books - добавление двух книг - def test_add_new_book_add_two_books(self): - # создаем экземпляр (объект) класса BooksCollector - collector = BooksCollector() - + def test_add_new_book_add_two_books(self, collector): # добавляем две книги collector.add_new_book('Гордость и предубеждение и зомби') collector.add_new_book('Что делать, если ваш кот хочет вас убить') @@ -23,8 +21,7 @@ def test_add_new_book_add_two_books(self): assert len(collector.get_books_genre()) == 2 # Тест на проверку игнорирования дубликатов при добавлении книги - def test_add_new_book_ignore_duplicate_name(self): - collector = BooksCollector() + def test_add_new_book_ignore_duplicate_name(self, collector): # Добавляем две книги с одинаковым именем collector.add_new_book('Гордость и предубеждение и зомби') collector.add_new_book('Гордость и предубеждение и зомби') @@ -32,16 +29,14 @@ def test_add_new_book_ignore_duplicate_name(self): assert len(collector.get_books_genre()) == 1 # Тест на проверку игнорирования пустого имени при добавлении книги - def test_add_new_book_igonore_empty_name(self): - collector = BooksCollector() + def test_add_new_book_igonore_empty_name(self, collector): # Добавляем книгу с пустым именем collector.add_new_book("") # Проверяем, что книга не добавилась assert len(collector.get_books_genre()) == 0 # Тест на проверку игнорирования добавления книги с именем длинее 40 символа - def test_add_new_book_igonore_book_name_longer_than_41_symblos(self): - collector = BooksCollector() + def test_add_new_book_igonore_book_name_longer_than_41_symblos(self, collector): # Создаем имя длиной 41 символа name = "A" * 41 # Добавляем книгу с именем длиной 41 символа @@ -51,8 +46,7 @@ def test_add_new_book_igonore_book_name_longer_than_41_symblos(self): # Тест на проверку установки жанра книги черрез параметризацию @pytest.mark.parametrize("book, genre", BOOK_WITH_GENRE) - def test_set_book_genre(self, book, genre): - collector = BooksCollector() + def test_set_book_genre(self, collector, book, genre): # Добавляем книгу collector.add_new_book(book) # Устанавливаем жанр книги @@ -61,8 +55,7 @@ def test_set_book_genre(self, book, genre): assert collector.get_book_genre(book) == genre # Тест на проверку игнорирования установки жанра книги не из списка жанров - def test_set_book_genre_ignore_genre_not_in_list(self): - collector = BooksCollector() + def test_set_book_genre_ignore_genre_not_in_list(self, collector): # Добавляем книгу collector.add_new_book('Гордость и предубеждение и зомби') # Добаляем жанр не из списка жанров @@ -71,8 +64,7 @@ def test_set_book_genre_ignore_genre_not_in_list(self): assert collector.get_book_genre('Гордость и предубеждение и зомби') == '' # Тест на проверку игнорирования установки жанра книги, которой нет в коллекции - def test_set_book_genre_ignore_book_not_in_collection(self): - collector = BooksCollector() + def test_set_book_genre_ignore_book_not_in_collection(self, collector): # Добавляем жанр книге, которой нет в коллекции collector.set_book_genre('Гордость и предубеждение и зомби', 'Ужасы') # Проверяем, что жанр книги не установлен @@ -80,62 +72,60 @@ def test_set_book_genre_ignore_book_not_in_collection(self): # Тест на проверку получения жанра книги с фикстурой def test_get_book_genre_book_exist(self, collector_with_books): - collector = collector_with_books - assert collector.get_book_genre("Оно") == "Ужасы" + # Используем фикстуру с книгами и жанрами + assert collector_with_books.get_book_genre("Оно") == "Ужасы" # Тест на проверку получения жанра книги, которой нет в коллекции, с фикстурой def test_get_book_genre_book_not_exist(self, collector_with_books): - collector = collector_with_books - assert collector.get_book_genre("Неизвестная книга") is None + # Используем фикстуру с книгами и жанрами + assert collector_with_books.get_book_genre("Неизвестная книга") is None # Тест на проверку получения списка книг с определнным жанром черрез параметризацию @pytest.mark.parametrize("book, genre", BOOK_WITH_GENRE) def test_get_books_with_specific_genre(self, book, genre, collector_with_books): - collector = collector_with_books - # Добавляем книгу - collector.add_new_book(book) - # Устанавливаем жанр книги - collector.set_book_genre(book, genre) # Проверяем, что книга возвращается в списке книг с определенным жанром - assert book in collector.get_books_with_specific_genre(genre) + assert book in collector_with_books.get_books_with_specific_genre(genre) # Тест на проверку получения словаря books_genre def test_get_books_genre_book_exist (self, collector_with_books): - collector = collector_with_books # Преобразуем список книг с жанрами в словарь dic_books = dict(BOOK_WITH_GENRE) # Проверяем, что метод возвращает правильный словарь книг с жанрами - assert collector.get_books_genre() == dic_books + assert collector_with_books.get_books_genre() == dic_books # Тест на проверку получения списка книг, подходящих для детей def test_get_books_for_children_only_children_genres(self, collector_with_books): - collector = collector_with_books # Получаем список книг для детей - book_for_children = set(collector.get_books_for_children()) + book_for_children = set(collector_with_books.get_books_for_children()) + # Берем названия книг через переменные, чтобы тест был стабильным + expected_books = { + name for name, genre in BOOK_WITH_GENRE + if genre not in ['Ужасы', 'Детективы'] + } # Проверяем, что в списке книг для детей только книги без возрастного рейтинга - assert book_for_children == {"Цветы для Элджернона", "Приключения Винни", "Горе от ума"} + assert book_for_children == expected_books # Тест на проверку получения списка книг, подходящих для детей, когда все книги имеют возрастной рейтинг - @pytest.mark.parametrize("adult_genre", ['Ужасы', 'Детективы']) - def test_get_books_for_children_no_children_genres(self, adult_genre): - collector = BooksCollector() - # Добавляем книгу с возрастныи рейтингом + def test_get_books_for_children_no_children_genres(self, collector): + # Добавляем книгу с жанром из возрастного рейтинга collector.add_new_book('Взрослая книга') - collector.set_book_genre('Взрослая книга', adult_genre) + collector.set_book_genre('Взрослая книга', 'Ужасы') # можно выбрать любой из genre_age_rating # Проверяем, что список книг для детей пустой assert collector.get_books_for_children() == [] #Тест на проверку добавление книги в избранное - def test_add_book_in_favorites_one_book(self, collector_with_books): - collector = collector_with_books + def test_add_book_in_favorites_one_book(self, collector): + # Добавляем новую книгу + collector.add_new_book("Приключения Винни") # Добавляем книгу в избранное collector.add_book_in_favorites("Приключения Винни") # Проверяем, что книга добавлена в избраное assert "Приключения Винни" in collector.get_list_of_favorites_books() #Тест на проверку игнорирования дубликатов при добавлении книги в избранное - def test_add_book_in_favorites_ignore_duplicates(self, collector_with_books): - collector = collector_with_books + def test_add_book_in_favorites_ignore_duplicates(self, collector): + # Добавляем новую книгу + collector.add_new_book("Приключения Винни") # Добавляем книгу в избранное collector.add_book_in_favorites("Приключения Винни") collector.add_book_in_favorites("Приключения Винни") @@ -143,8 +133,9 @@ def test_add_book_in_favorites_ignore_duplicates(self, collector_with_books): assert len(collector.get_list_of_favorites_books()) == 1 #Тест на проверку удаления книги из избранного - def tes_delete_book_from_favorites_one_book(self, collector_with_books): - collector = collector_with_books + def test_delete_book_from_favorites_one_book(self, collector): + # Добавляем новую книгу + collector.add_new_book("Приключения Винни") # Добавляем книгу в избранное collector.add_book_in_favorites("Приключения Винни") # Удаляем книгу из избранного @@ -153,8 +144,10 @@ def tes_delete_book_from_favorites_one_book(self, collector_with_books): assert "Приключения Винни" not in collector.get_list_of_favorites_books() #Тест на проверку удаления только одной книги из избранного при наличии нескольких книг - def test_delete_book_from_favorites_one_of_many(self, collector_with_books): - collector = collector_with_books + def test_delete_book_from_favorites_one_of_many(self, collector): + # Добавляем новую книгу + collector.add_new_book("Приключения Винни") + collector.add_new_book("Горе от ума") # Добавляем книги в избранное collector.add_book_in_favorites("Приключения Винни") collector.add_book_in_favorites("Горе от ума") @@ -164,8 +157,9 @@ def test_delete_book_from_favorites_one_of_many(self, collector_with_books): assert collector.get_list_of_favorites_books() == ["Горе от ума"] # Тест на проверку не удаления книги из избранного, если ее там нет - def test_delete_book_from_favorites_book_not_in_favorites(self, collector_with_books): - collector = collector_with_books + def test_delete_book_from_favorites_book_not_in_favorites(self, collector): + # Добавляем новую книгу + collector.add_new_book("Приключения Винни") # Добавляем книгу в избранное collector.add_book_in_favorites("Приключения Винни") # Пытаемся удалить книгу, которой нет в избранном @@ -174,8 +168,10 @@ def test_delete_book_from_favorites_book_not_in_favorites(self, collector_with_b assert collector.get_list_of_favorites_books() == ["Приключения Винни"] # Тест на проверку получения списка избранных книг - def test_get_list_of_favorites_books_return_favorites(self, collector_with_books): - collector = collector_with_books + def test_get_list_of_favorites_books_return_favorites(self, collector): + # Добавляем новую книгу + collector.add_new_book("Приключения Винни") + collector.add_new_book("Горе от ума") # Добавляем книги в избранное collector.add_book_in_favorites("Приключения Винни") collector.add_book_in_favorites("Горе от ума") @@ -183,8 +179,7 @@ def test_get_list_of_favorites_books_return_favorites(self, collector_with_books assert collector.get_list_of_favorites_books() == ["Приключения Винни", "Горе от ума"] # Тест на проверку получения списка избранных книг, когда избранное пусто - def test_get_list_of_favorites_books_empty_favorites(self, collector_with_books): - collector = collector_with_books + def test_get_list_of_favorites_books_empty_favorites(self, collector): # Проверяем, что метод возвращает пустой список избранных книг assert collector.get_list_of_favorites_books() == [] From b210a7a2121c2e2ef11093665711cfc540d9d593 Mon Sep 17 00:00:00 2001 From: Kirill Martyushov Date: Mon, 22 Dec 2025 14:01:04 +0300 Subject: [PATCH 6/8] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B7=D0=B0=D0=BC=D0=B5=D1=87=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20=D0=BF=D0=BE=20=D1=84=D0=B8=D0=BA=D1=81?= =?UTF-8?q?=D1=82=D1=83=D1=80=D0=B5,=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B8?= =?UTF-8?q?=D1=81=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D1=81=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD=D0=BD=D0=BE?= =?UTF-8?q?=D0=B3=D0=BE=20=D1=8D=D0=BA=D0=B7=D0=B5=D0=BC=D0=BF=D0=BB=D1=8F?= =?UTF-8?q?=D1=80=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- conftest.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/conftest.py b/conftest.py index ccf63da..acb0c1f 100644 --- a/conftest.py +++ b/conftest.py @@ -10,8 +10,7 @@ def collector(): # Фикстура для создания экземпляра BooksCollector с предзаполненными книгами и жанрами @pytest.fixture -def collector_with_books(): - collector = BooksCollector() +def collector_with_books(collector): for name, genre in BOOK_WITH_GENRE: collector.add_new_book(name) collector.set_book_genre(name, genre) From bcac2a8730b72271294fc6ecdf4856527d232230 Mon Sep 17 00:00:00 2001 From: Kirill Martyushov Date: Mon, 22 Dec 2025 14:06:42 +0300 Subject: [PATCH 7/8] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B7=D0=B0=D0=BC=D0=B5=D1=87=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F,=20=D1=83=D0=B1=D1=80=D0=B0=D0=BD=D0=BE=20?= =?UTF-8?q?=D1=83=D1=81=D0=BB=D0=BE=D0=B2=D0=B8=D0=B5=20=D0=B8=D0=B7=20?= =?UTF-8?q?=D1=82=D0=B5=D1=81=D1=82=D0=B0,=20=D0=B4=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=20=D1=81=D0=BB=D0=BE=D0=B2=D0=B0=D1=80?= =?UTF-8?q?=D1=8C=20=D1=82=D0=BE=D0=BB=D1=8C=D0=BA=D0=BE=20=D1=81=20=D0=B4?= =?UTF-8?q?=D0=B5=D1=82=D1=81=D0=BA=D0=B8=D0=BC=D0=B8=20=D0=BA=D0=BD=D0=B8?= =?UTF-8?q?=D0=B3=D0=B0=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- books_data.py | 9 ++++++++- test.py | 10 +++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/books_data.py b/books_data.py index c916e02..712423a 100644 --- a/books_data.py +++ b/books_data.py @@ -4,4 +4,11 @@ ["Убийство в Восточном экспрессе", "Детективы"], ["Приключения Винни", "Мультфильмы"], ["Горе от ума", "Комедии"] - ] \ No newline at end of file + ] + + +BOOK_FOR_CHILDREN = [ + "Цветы для Элджернона", + "Приключения Винни", + "Горе от ума" +] \ No newline at end of file diff --git a/test.py b/test.py index 09bd414..28cba07 100644 --- a/test.py +++ b/test.py @@ -2,6 +2,7 @@ from conftest import collector from main import BooksCollector from books_data import BOOK_WITH_GENRE +from books_data import BOOK_FOR_CHILDREN # класс TestBooksCollector объединяет набор тестов, которыми мы покрываем наше приложение BooksCollector # обязательно указывать префикс Test @@ -9,7 +10,7 @@ class TestBooksCollector: # пример теста: # обязательно указывать префикс test_ - # дальше идет название метода, который тестируем add_new_book_ + # дальше идет название метода, который тестируем add_new_book_п # затем, что тестируем add_two_books - добавление двух книг def test_add_new_book_add_two_books(self, collector): # добавляем две книги @@ -97,13 +98,8 @@ def test_get_books_genre_book_exist (self, collector_with_books): def test_get_books_for_children_only_children_genres(self, collector_with_books): # Получаем список книг для детей book_for_children = set(collector_with_books.get_books_for_children()) - # Берем названия книг через переменные, чтобы тест был стабильным - expected_books = { - name for name, genre in BOOK_WITH_GENRE - if genre not in ['Ужасы', 'Детективы'] - } # Проверяем, что в списке книг для детей только книги без возрастного рейтинга - assert book_for_children == expected_books + assert book_for_children == set(BOOK_FOR_CHILDREN) # Тест на проверку получения списка книг, подходящих для детей, когда все книги имеют возрастной рейтинг def test_get_books_for_children_no_children_genres(self, collector): From 6845e69251c343dd02261b0cc5250b208ed67135 Mon Sep 17 00:00:00 2001 From: Kirill Martyushov Date: Mon, 22 Dec 2025 14:25:50 +0300 Subject: [PATCH 8/8] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B7=D0=B0=D0=BC=D0=B5=D1=87=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F,=20=D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D1=8C?= =?UTF-8?q?=D0=B7=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=B4=D0=B0=D0=BD?= =?UTF-8?q?=D0=BD=D1=8B=D1=85=20=D0=B8=D0=B7=20=D1=84=D0=B8=D0=BA=D1=81?= =?UTF-8?q?=D1=82=D1=83=D1=80=D0=B5=20=D0=B2=20=D1=82=D0=B5=D1=81=D1=82?= =?UTF-8?q?=D0=B5,=20=D0=B2=D0=BC=D0=B5=D1=81=D1=82=D0=BE=20=D0=B4=D1=83?= =?UTF-8?q?=D0=B1=D0=BB=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test.py b/test.py index 28cba07..c6b23c5 100644 --- a/test.py +++ b/test.py @@ -73,8 +73,10 @@ def test_set_book_genre_ignore_book_not_in_collection(self, collector): # Тест на проверку получения жанра книги с фикстурой def test_get_book_genre_book_exist(self, collector_with_books): - # Используем фикстуру с книгами и жанрами - assert collector_with_books.get_book_genre("Оно") == "Ужасы" + # Берем первую книгу и жанр из тестовых данных + book, genre = BOOK_WITH_GENRE[0] + # Проверяем, что жанр книги установлен корректно + assert collector_with_books.get_book_genre(book) == genre # Тест на проверку получения жанра книги, которой нет в коллекции, с фикстурой def test_get_book_genre_book_not_exist(self, collector_with_books):