From be90d871175c3ae9c53444dc0e69ce10544343e1 Mon Sep 17 00:00:00 2001 From: Konstantin Zhulev Date: Mon, 23 Mar 2026 20:33:18 +0300 Subject: [PATCH 1/2] Feat: add pytest for TestBooksCollector --- README.md | 13 ++- __pycache__/main.cpython-313.pyc | Bin 0 -> 3580 bytes .../tests.cpython-313-pytest-9.0.2.pyc | Bin 0 -> 15342 bytes tests.py | 83 +++++++++++++----- 4 files changed, 75 insertions(+), 21 deletions(-) create mode 100644 __pycache__/main.cpython-313.pyc create mode 100644 __pycache__/tests.cpython-313-pytest-9.0.2.pyc diff --git a/README.md b/README.md index 1cc701d..b7de704 100644 --- a/README.md +++ b/README.md @@ -1 +1,12 @@ -# qa_python \ No newline at end of file +## Описание тестов + +- `test_add_new_book_add_one_book` — проверка успешного добавления одной книги. +- `test_add_new_book_invalid_name_length_not_added` — проверка, что книги с некорректной длиной названия (0 или 41+ символов) не добавляются. +- `test_set_book_genre_existing_genre` — проверка установки жанра из списка разрешённых. +- `test_set_book_genre_not_in_list_not_set` — проверка, что жанр не устанавливается, если его нет в списке `genre`. +- `test_get_books_with_specific_genre_is_correct` — проверка фильтрации книг по выбранному жанру. +- `test_get_books_genre_returns_dict` — проверка корректного возврата всего словаря книг. +- `test_get_books_for_children_excludes_age_rating_genres` — проверка, что книги с жанрами из `genre_age_rating` не попадают в детский список. +- `test_add_book_in_favorites_added_successfully` — проверка успешного добавления книги в список избранного. +- `test_add_book_in_favorites_book_not_in_collector_not_added` — проверка запрета на добавление в избранное книг, отсутствующих в коллекции. +- `test_delete_book_from_favorites_removed_successfully` — проверка удаления книги из списка избранного. diff --git a/__pycache__/main.cpython-313.pyc b/__pycache__/main.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4cf9afcb061c41d0d58dfe8b2d81966e93dd89c9 GIT binary patch literal 3580 zcmbVP-A@}w5Z^odh_Q|D1kRU@!C*V#Ac3HeHX;ei2bKDv(3T4lY9n1Q_TgAHHrX?Y z5~)#}RuxeqrICt~R+Wm>K7^;zHc8Vo{rV5?O2O8>_9<_vQPkJY-1!S*klF?2_I76X zc7F5QnPsh|#Z90w^!HSIGa-NBOSw5qowZ%inJ2qQH<3tyNX#MD)=-jUMMu1Bk58ub zvi1ga=E+$?8HrF^6XJ73%?T zFlGYEz_9?FVR0LrX z(Lv!15Yv%VbEYG$W)@kB;W3>VWm?tHy>OWFIO0_j2|1%)k}*7HunxsqB@#qC2?CJh z+wy#;!FT5Qh`~n|M)SOA@Zvq?eq<@}y|~hU{L#79{^Nz%-nr4dx83lz-#zn(xBHoc z44hzeUZlvbcr9kw$G^3AK+Ka#p%KbQK&NyPG8rDPjS!4tv$Wt7XzhV@vKFmHW=v!) zgs2CM04)TE22kLDhC2zD5%Otj&O)ce-B2Ay>(vOVwjTtbTNfXQW7cS4`;2C**wKA^}}-mO<-_Rw&R z1{_%CMcq{jZLKGj1N0lrnJdejiYpEwI`p_R5h z1^@oMf5`9;EuC5Q5C6@P*s*6#M1W}b*u1S2BKQXOt%HoGX*1rIab#>9Tfo##^L9?+ ztM1svp<`2bEqxcx$0JDH!c@34|Oj=ZmOdc4=HS5|D z0KuXcR7&zkTTO7d=_=WFRPnC0H)ET^UTcP%(8fRj`k_wU6(|Hd^T9qN*q09u z8o|NU;KA#!&5ag#f4+UtXdhhR2ba`eul#sr<%L%YLU&#e4MDsYT@?m^TJ1wft!^Oc z7Af%xd~C}av2W7^0+CVLtprk=qF_C2jS@(;Mq@3;A3Leq6_#RAv~b^;S+`^H#3;ZO zMXug=qIIA)w88?S4S@hmYpMv;-7iNz8-Yw)5d3$1w|#jbW(cu`#EQ@d#Z~A9;f-#A z+*`2ZmdM%IfK`2KbRz1pDVG}r#cZPLboQdU5tl$hO{+Q8hGvRpr)$6w>%iIE^dNjg zi-52Yx-)WnWZBbI@Cvuau8-xtU52-7A-dw-i-2@*Oa%WiOIcB_&r(4=HR+U=le1G* z7c93lv$xKXEo`yCYj}vQ>~-tv^{cuoWNn$cV0296@tTVlH@N1yWqCTAm`!8fE6W#V zm2^qN%kor;YPobOqh_+QOa+)sgD9YW5!#IcuZI*)2cZX0Ac*uu6p&$vxm}jE99+KR zvXaZu)VW!>pUd(hu{VP^8;Ysj5{RINDe+@cbUL}0n4*v6dWvqA>npk$uD9rF;>2Pr z!-b13j_WQ84sKu33ntG&+hMPWi;ao!9~CZo0!1qd>t5H5`BDU>N2f N_At{?Bp|E_{{lqk^KAeC literal 0 HcmV?d00001 diff --git a/__pycache__/tests.cpython-313-pytest-9.0.2.pyc b/__pycache__/tests.cpython-313-pytest-9.0.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a098a7b20092837f22ee90ed29377a001386d2b1 GIT binary patch literal 15342 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 M!FvJzhmZ4r0podbB>(^b literal 0 HcmV?d00001 diff --git a/tests.py b/tests.py index 383385e..55abb94 100644 --- a/tests.py +++ b/tests.py @@ -1,24 +1,67 @@ +import pytest from main import BooksCollector -# класс TestBooksCollector объединяет набор тестов, которыми мы покрываем наше приложение BooksCollector -# обязательно указывать префикс Test class TestBooksCollector: - - # пример теста: - # обязательно указывать префикс test_ - # дальше идет название метода, который тестируем add_new_book_ - # затем, что тестируем add_two_books - добавление двух книг - def test_add_new_book_add_two_books(self): - # создаем экземпляр (объект) класса BooksCollector + + def test_add_new_book_add_one_book(self): collector = BooksCollector() - - # добавляем две книги - collector.add_new_book('Гордость и предубеждение и зомби') - collector.add_new_book('Что делать, если ваш кот хочет вас убить') - - # проверяем, что добавилось именно две - # словарь books_rating, который нам возвращает метод get_books_rating, имеет длину 2 - assert len(collector.get_books_rating()) == 2 - - # напиши свои тесты ниже - # чтобы тесты были независимыми в каждом из них создавай отдельный экземпляр класса BooksCollector() \ No newline at end of file + collector.add_new_book('Гордость и предубеждение') + assert 'Гордость и предубеждение' in collector.get_books_genre() + + @pytest.mark.parametrize('name', ['', 'Название книги, которое длиннее сорока одного символа']) + def test_add_new_book_invalid_name_length_not_added(self, name): + collector = BooksCollector() + collector.add_new_book(name) + assert name not in collector.get_books_genre() + + def test_set_book_genre_existing_genre(self): + collector = BooksCollector() + collector.add_new_book('Дюна') + collector.set_book_genre('Дюна', 'Фантастика') + assert collector.get_book_genre('Дюна') == 'Фантастика' + + def test_set_book_genre_not_in_list_not_set(self): + collector = BooksCollector() + collector.add_new_book('Дюна') + collector.set_book_genre('Дюна', 'Киберпанк') + assert collector.get_book_genre('Дюна') == '' + + def test_get_books_with_specific_genre_is_correct(self): + collector = BooksCollector() + collector.add_new_book('Дракула') + collector.set_book_genre('Дракула', 'Ужасы') + assert 'Дракула' in collector.get_books_with_specific_genre('Ужасы') + + def test_get_books_genre_returns_dict(self): + collector = BooksCollector() + collector.add_new_book('Оно') + assert isinstance(collector.get_books_genre(), dict) + assert 'Оно' in collector.get_books_genre() + + def test_get_books_for_children_excludes_age_rating_genres(self): + collector = BooksCollector() + collector.add_new_book('Шрек') + collector.set_book_genre('Шрек', 'Мультфильмы') + collector.add_new_book('Сияние') + collector.set_book_genre('Сияние', 'Ужасы') + + children_books = collector.get_books_for_children() + assert 'Шрек' in children_books and 'Сияние' not in children_books + + def test_add_book_in_favorites_added_successfully(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_book_not_in_collector_not_added(self): + collector = BooksCollector() + collector.add_book_in_favorites('Неизвестная книга') + assert len(collector.get_list_of_favorites_books()) == 0 + + def test_delete_book_from_favorites_removed_successfully(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() From 16129dbc133142e9a078fdf439ec73b69077b507 Mon Sep 17 00:00:00 2001 From: Konstantin Zhulev Date: Tue, 24 Mar 2026 18:14:04 +0300 Subject: [PATCH 2/2] Feat: add gitignore --- .gitignore | 5 +++++ __pycache__/main.cpython-313.pyc | Bin 3580 -> 0 bytes __pycache__/main.cpython-38.pyc | Bin 2030 -> 0 bytes __pycache__/test.cpython-38-pytest-7.1.2.pyc | Bin 8183 -> 0 bytes __pycache__/tests.cpython-313-pytest-9.0.2.pyc | Bin 15342 -> 0 bytes 5 files changed, 5 insertions(+) create mode 100644 .gitignore delete mode 100644 __pycache__/main.cpython-313.pyc delete mode 100644 __pycache__/main.cpython-38.pyc delete mode 100644 __pycache__/test.cpython-38-pytest-7.1.2.pyc delete mode 100644 __pycache__/tests.cpython-313-pytest-9.0.2.pyc diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..89de410 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +__pycache__/ +*.py[cod] +.pytest_cache/ +venv/ +.venv/ \ No newline at end of file diff --git a/__pycache__/main.cpython-313.pyc b/__pycache__/main.cpython-313.pyc deleted file mode 100644 index 4cf9afcb061c41d0d58dfe8b2d81966e93dd89c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3580 zcmbVP-A@}w5Z^odh_Q|D1kRU@!C*V#Ac3HeHX;ei2bKDv(3T4lY9n1Q_TgAHHrX?Y z5~)#}RuxeqrICt~R+Wm>K7^;zHc8Vo{rV5?O2O8>_9<_vQPkJY-1!S*klF?2_I76X zc7F5QnPsh|#Z90w^!HSIGa-NBOSw5qowZ%inJ2qQH<3tyNX#MD)=-jUMMu1Bk58ub zvi1ga=E+$?8HrF^6XJ73%?T zFlGYEz_9?FVR0LrX z(Lv!15Yv%VbEYG$W)@kB;W3>VWm?tHy>OWFIO0_j2|1%)k}*7HunxsqB@#qC2?CJh z+wy#;!FT5Qh`~n|M)SOA@Zvq?eq<@}y|~hU{L#79{^Nz%-nr4dx83lz-#zn(xBHoc z44hzeUZlvbcr9kw$G^3AK+Ka#p%KbQK&NyPG8rDPjS!4tv$Wt7XzhV@vKFmHW=v!) zgs2CM04)TE22kLDhC2zD5%Otj&O)ce-B2Ay>(vOVwjTtbTNfXQW7cS4`;2C**wKA^}}-mO<-_Rw&R z1{_%CMcq{jZLKGj1N0lrnJdejiYpEwI`p_R5h z1^@oMf5`9;EuC5Q5C6@P*s*6#M1W}b*u1S2BKQXOt%HoGX*1rIab#>9Tfo##^L9?+ ztM1svp<`2bEqxcx$0JDH!c@34|Oj=ZmOdc4=HS5|D z0KuXcR7&zkTTO7d=_=WFRPnC0H)ET^UTcP%(8fRj`k_wU6(|Hd^T9qN*q09u z8o|NU;KA#!&5ag#f4+UtXdhhR2ba`eul#sr<%L%YLU&#e4MDsYT@?m^TJ1wft!^Oc z7Af%xd~C}av2W7^0+CVLtprk=qF_C2jS@(;Mq@3;A3Leq6_#RAv~b^;S+`^H#3;ZO zMXug=qIIA)w88?S4S@hmYpMv;-7iNz8-Yw)5d3$1w|#jbW(cu`#EQ@d#Z~A9;f-#A z+*`2ZmdM%IfK`2KbRz1pDVG}r#cZPLboQdU5tl$hO{+Q8hGvRpr)$6w>%iIE^dNjg zi-52Yx-)WnWZBbI@Cvuau8-xtU52-7A-dw-i-2@*Oa%WiOIcB_&r(4=HR+U=le1G* z7c93lv$xKXEo`yCYj}vQ>~-tv^{cuoWNn$cV0296@tTVlH@N1yWqCTAm`!8fE6W#V zm2^qN%kor;YPobOqh_+QOa+)sgD9YW5!#IcuZI*)2cZX0Ac*uu6p&$vxm}jE99+KR zvXaZu)VW!>pUd(hu{VP^8;Ysj5{RINDe+@cbUL}0n4*v6dWvqA>npk$uD9rF;>2Pr z!-b13j_WQ84sKu33ntG&+hMPWi;ao!9~CZo0!1qd>t5H5`BDU>N2f N_At{?Bp|E_{{lqk^KAeC 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-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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 M!FvJzhmZ4r0podbB>(^b