From 3614d05f3d4c2ffc5a9d8362c5f0ba404cf7ca7d Mon Sep 17 00:00:00 2001 From: Olga Anisimova Date: Wed, 25 Feb 2026 20:07:00 +0700 Subject: [PATCH 1/2] spriont_4 --- .idea/.gitignore | 5 + .../inspectionProfiles/profiles_settings.xml | 6 ++ .idea/vcs.xml | 6 ++ __pycache__/main.cpython-314.pyc | Bin 0 -> 3698 bytes .../tests.cpython-314-pytest-9.0.2.pyc | Bin 0 -> 18173 bytes tests.py | 89 +++++++++++++++++- 6 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/vcs.xml create mode 100644 __pycache__/main.cpython-314.pyc create mode 100644 __pycache__/tests.cpython-314-pytest-9.0.2.pyc diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..b58b603 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,5 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/__pycache__/main.cpython-314.pyc b/__pycache__/main.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..08aaa6ecc805e8e54a417358e592cc1f2a888a2a GIT binary patch literal 3698 zcmb7GU2Gdg5Z<%zQYUtN*CuJ&*h!q&adQoI2(_vK%siZuF98XT1kHS4bBbAPVUw3YYXa8iOdFD3QJC>J0ql z+>iBH=%irYE5zUwVtCGShIcn9!2E7v@QMedpm;&HC_Km=iU885w18|?c7SYCd?5Ww zE69M-2C`l88^IZ3h)MwVZMTEZ6bi5FCkwfpmNp7BUELdxfM@g);#+?XI#jQ}dciQ${vF zzrxwPuI1)*^fqqyr^jbs(lx3xIeQ_cF1~4;FXU$zQrUcB@lD&Os@Z(jP*uBoGq{PW z0wK}kAg+*dsCSuP^X)0`4K4HU2kox6;HRxTaKIcrX+|cO`J%6P9V|(D16las;h#n3 zE9hK-NKC_TW1HSUzNVSsl5WiQxr6gh5)vk7$t!LDSLCc$|tj z5=dn-YF@jjV#w@J1Dy3rB#-_q2!K@VD2e@+*k2N(mKeP?SrX+xMEQ2=`{-)sJGq!R ze)n7{aokKCFAwcoo-75zRv`Sz=?8(qzrAGi1ZRmdMe?QV@xwkt{57`68L64qM?jZ} zB0gs#)AjL!acoS#)73jeo1}{x0o2_86>duQFu156OaVGXita^$13I27UWF^DYX*bL zC3kNFV4Ky5uzmmpK;{=q9Z{6$* z%?YtR8KZ>u!sM!}c%$ha5Sz#l1iozN-DWkW869zILWl>VZ2H_F*L%W)IScadY+iya zLIP_R=<4OkyugAfZ5iyRQQv%x>5U5qo4GCN{z~MzK0+?S*=X|2iNh}wG7skplT+=4 z%y_0T?KQL+Z}npLlT#5wT1g*RR&nKP6tV?Kb_=@Ql3HBU@)<~{j8RA?doNxyUA>q! z&a3*Omd?&)(+-swq!mk+V&hh9ycj!XNs$lvaz}5mBVO)2Q0h!toypbH z#m@1+1v2#X!xkbz*oPegZ&WVW2Ky}RPL*yRt}2wA10@84I0eD+U#xlLl##wIJ!bj= zoR7%Y(bM$xKYq9kPTph2z{xFAZnGO!$ER_ZPth|^PUD&l?FfM2a;%#WuxV*9fKNiNV3$L|xdK(w=d-yCg(_Xk zc6jg_=XTdHueY~{wuHXk40qM1KtKd~`%Pa@In-YYjaZ?PQfSNyjTJ)&ubo<+EQ_6` z@R$`ID~e;Q+HaSBx>P*$d|4VSNwOu$w_`B(q0&Cncx=4fG|4kEb$qODC2!XA1Q1jFg$i5nAZ z{(*8p`e5qXR4FiE1qN=#ih+Fy%i!b5;eTc>7VE~$6~bGT%j$+&n5((K+|up+4UTMM zi`8GpOU*Lc2bZs1HhsP9$P}KB@a&WDWsFZecp0~;>Ovv2l*4{NRWB^1a;`>H)wwLy zja)Xb#bD7#BlbpxL6X*FdSG<$9dUiYxi zPE}3kQo5eWrj4|g%c-i&+3j_MFbx4c&N4cMia?maF&zpy`S(5Wt-|xdvs@+U5r!*m z9$}=?#tHi?z7|2Q?Baw-#U}`Z70D|+Q3-&_KcMYA1exYdq(oY_tBYmXY0JnP8?qBxTZn`tBoF{D z0LyY3TXxe4XY83KX&yXH+N$HuRDS6&Zqz8g)ia&xOJ5cwManzv%2K$u9LzQqJwFIAtJRYq?`;=|UE=6m*L(xK`LA!rN)dIVfRQNxs zIGGAq@uS7!x68+h`FwV|QZ(x34A^~?TW65TVAkg_qo!1Xr^A)D?Me}AxI?Lgv>?(j z%~OeJA*4|)j8xSkNMl+QX}hK(?a*RKJGFMCU0MgyxYk)oq?O7htqZG)TU(yWmMfkW z@m0`b68PVyDC(^=(#y(}Xd9(gT%|xda1w3aOH)Q2**>L#M4(QB@3%D2>^-{_F;Cl6 zlsBc@c+XPkba3{mba?!6MVURj#}POlIQN92^eR&-?{SiS&b(y5g19q<2>iSyK9<2<+)v+nKrqSJhw}kits#NIbZ9{U7r41xTO2;*Z&U# zTALQq!W&xa-JZF8*P0fei&*0wo_@Y-bo*g#VJ#xHV066402 z%7(e@V5DDsMtG{DTD#Vfjt&OuYSpQ2{8N!e-p=dX_gzX_WEpmy2(Inq~Zuhw2qn%9%&KcVKD`SaSJm_Nh&Kce-T`M!DG zyvAC8VSZq~hnDMAJpPLLcePi|50XsgU2~qs=uev0YOk2@(ok=sYA$KMgYjQY*8UW4 z-$&!CcEc-4HpO-7WVMwp4OwmZY=LsaR&1JM6_xi>GDgWkD}?5u7ZaIsIcrpsU)hV| zNUF@LM<(A2d=h;4;Z)$o3)FBhRc`-|lSw|zWQS7ay;L*Cn~-su_VX%aoT}kedEi{O zqMsr3)X!xLMz;OCdsFS-#Vh%+J>oEiOm!NByjEvsW=1b$FR~6+!qe3tEV0@Tmo8O+ ze|pBSHtW-wd|o%QC1bjHp_DPQRwtVEGu2$ak}H(0NWKV(vUR6kK3}ZnXPBsdE?+#8 z$?Jv8g{&3R%bBxT8o`PmVSAD*7LFT6(XhJpvqj@VrlMzGDCIMSOa(2em=!8#^Jk41 zt)+t|vv+btE{w{B19D+PE{xl&wPzU~t}E>?(+u||oy$rddvNM$d}L*oPR(X?Y{U6t zVT$&mJW#r1_1U{3?VwKES-DuW_um>>OB(}C`gC9ot(ZhU@?EElG zYKhSm)p;#JGBGHMBJ+A#WEW@*Q4$#p^@9mff)Fn)v&roi8oqnL&GV^HKR+xwdomdL z7Vcb`7W9b%eJG4tOL$=Ysa1=Wg8t;07U0R~)sH+!(rpu%Z}w3RVM*PYQbEy%eZDoTwQo+C<~d4e8*Hni8W5-!O@}=M6q)MgdoGQ-NStXb>=M7q*70VY3=WG-MvX9u1gxu&SaS7cI0Nhb|V6v*QzUKVx z{Rhg36pEE(t^nFNNZbHGPuew%GDbNsAmi`?2xp*<6H*G2Tn2Wqy+lEV(dVYiW<<#6t)M(UgTt)-7go0?Sc)uV{+kOnFz*#Tw^y4;)AJ` zVo`TDzBNp(>qBcUUqy0R`8NksZ*IMNE+%mFjY~^v>Si*vk{qig$4qt1L?$t|qB^fd zb!_gED2a?zx8N^@zL6zoC;L&2R$8=#=lA_`&z@8x1l zBb+QXGAshVhQ)r5DlAaZof#O~!3>MeI>Ul6R3PV<+OV)Obt7y2;tUJIRKZ&({S6C& zsVx{GuCdVE2yu;ta2-}hHC2n1A9~YW917c&4 z)kllOj7I}E&uRbX{$Qkrl2egfKL0f~R+miYk z#uj?6Q@gnbjRCh%qg=7sN1@~hRdDv{blVy)&~!^+&AmWhmlWQOdV#(;03>y{834MV zMt+#v59DIkJ&Jp?b%}mZj-lQ*y$=Dn1hAjOeF&o1;C+aGxR2PNmkd5H&k=cy(vHW7 z^j3I`=4+SXA%b`3ugR?g|IfABWt$}a7OMICsF){j5GQgM|f?7(}uc(P9(<-yhCrC>!a%1}Nm*0yul>ZBf zOdk(`J~rJq7xw7z#39L=n!M7pq>kK7+_{q2Q%meI)k9`t&(+vsVg%XwY%OtUMRi_F z)HWiDB16i(BeI|#;-zIal4!9rsJsd--<9SiChZ*?mGfCyS}KWZWFWT=rL=!(D5VtE zg0tClgwe`H4iN}0+}|RtL|JelEzt^r_w9#c;d9_?bo?mI;8^r?d=<^)U0NaVzWw(h z=wXBRA^PDypo?#SR+dp{($nNt^WT6Ui8V4E;K(#%c5I14pG9ic_J*~#!lMm{4S=>d+@bx zP;0c2Qomj=T1oj=NMvjt1vcN=Ki9PmHa{p~^SF!6B^3eyQMbm< z6C^uz3+gy8EtB*f(PC#%Ns#PH^AeMG#>PDJXM~WPfz({f}Eh`b0Vmq~CPvsEqUy3JIiS3t|aO7Z***ry)G#Cw+b1qfS@4gL7VE z!`}-cc7Wf{8dmUMm*@vH4G#wEJRLFSm5$Y;-t3zvMOf6m!*o0U1Yp30#TwphZAYI` zv7?)xiKc_np32DXzxF7fQ;Yr9>}dyMk`B+F{KdbyOH&YjIouQ60ujG;d6U_~;eQnoN-#d&lXZmxW>B!wap z5?@YYKHGNj^??l;eY7AJw6q_ z1li`@dl>Jod-v8@BjR1R8!>Ie zj?{J>F^{Gfcbu9_e59u5UNY76mA+bHXhlsUJAWF~EmSW?L&>RZH^>+tx$G_@ip)qtKFQ|M9()P877Z|DEhaLD#9@?SFIDZoL07FloF>p=p!xBo21L60H4M z($2s^N}s&>Q`nC0)?SC?_rS`?neWwJtCERj zzKN4&cfK3%)Y}*>JhXG?)E%C^T>bw@!N6bXOUA!UXg}^fP5T%8>lBh-oEjJTGrux`* zjQ`k*>bw@!$4p{RD&COtLSUJCh|)q`NmL^P%3e!er1CK%)NFh>s?}owJ|?6aH)A-+|EqHj#Kwa)U(lp0A6#?*Fbddh_7*tx!1%@gt_mK~iz#)-}}I8H?Z1Jpq zHuHSZ$U)b)Vc$7&D}lAOjZTKL_bGg)JS8n2RW&X^*a!3OYm9k%p;*Yi0Cdk5 zD%Qk?@K5e~iY9&^iHwB@9V~Rwk4~N*uO*M0>IpM>d@*@~Wlq!*CstJFwWOXPq;o6m zyi~W~FM*-x(5cfALcFxhCbL^Gx|#HjEt=LrztzuFr;e2!U^KZK5C6MhM#MUR-BV zq^ayi5tPmXu}d16Y-7)b9c=+Yt}}=ntWmt+ zs)x4)U zD0f|7+@9jM^x(|3VOqaEmBX~|TK!pW<6&AC@7=Ne@xJ9SZ5rW~eks&jifA3PzfLFE z(Kk2Ta*6r8+*$pfitWtZf5)k!_gyu#^1C2l;paGimPEcmNe?CT zETpzb?w9XSEggz-e}Q3p)G6R#Oi@CfbT`Os5S1D_C4WT85G5m&>_<|jC2>a$|7CL0 zIn&j{%oo?0?(U$~-^gO|lRifiebe9Z{>IBo>Y(tu+of$gSGEn*whb(98=7nXNS&N} z*;FU5?5mL*eG=LEJ|rK0wKhD7vi({nDLZ?^&C1PJ_KDI0jV4N-%o2_N;aBZij5UvN zvO5p*n2I-}gt4TON7T2ts7~HY^t>^6BeBm^hpys08WI)&hZmn-i|UY>!1^eEL&`6a zpk3`r(ZWoqxA2!uHe0IBexjr6R=ciWD9%*#S>!u)eYTp((=X&vO6dC8oKddibA@c7 zsO!eP^hA&nU_3<0W0d?pB^gTS6EupHlqq?El0QabZPWE~1wW&o)-#ogkvmhxBZJ{L z>-uyau0i^?O=t0YejR^trAw+rH#`r@Vdfh&LNp#FWU7^E?*INiG@#Ya_VCzhZzz0V zH69KRu5OBiA6nfK2~VtUiH1)FR=29*6M@z3;qaq@)lH%Be#o|3SG$L3buO9mi!W} x`#wr`BeB$n?A?CEcnw9mzcPJ^KW+;I0>4s}? Date: Sat, 28 Feb 2026 10:19:03 +0700 Subject: [PATCH 2/2] new_commit --- README.md | 12 ++- tests.py | 280 ++++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 218 insertions(+), 74 deletions(-) diff --git a/README.md b/README.md index 1cc701d..981d55e 100644 --- a/README.md +++ b/README.md @@ -1 +1,11 @@ -# qa_python \ No newline at end of file +# qa_python +# реализованы +# add_new_book — добавляет новую книгу в словарь без указания жанра. Название книги может содержать максимум 40 символов. Одну и ту же книгу можно добавить только один раз. +# set_book_genre — устанавливает жанр книги, если книга есть в books_genreи её жанр входит в списокgenre. +# get_book_genre— выводит жанр книги по её имени. +# get_books_with_specific_genre— выводит список книг с определённым жанром. +# get_books_genre— выводит текущий словарь books_genre. +# get_books_for_children — возвращает книги, которые подходят детям. У жанра книги не должно быть возрастного рейтинга. +# add_book_in_favorites — добавляет книгу в избранное. Книга должна находиться в словаре books_genre. Повторно добавить книгу в избранное нельзя. +# delete_book_from_favorites — удаляет книгу из избранного, если она там есть. +# get_list_of_favorites_books — получает список избранных книг. \ No newline at end of file diff --git a/tests.py b/tests.py index 83659af..4e622a6 100644 --- a/tests.py +++ b/tests.py @@ -1,3 +1,4 @@ +import pytest from main import BooksCollector # класс TestBooksCollector объединяет набор тестов, которыми мы покрываем наше приложение BooksCollector @@ -16,94 +17,227 @@ def test_add_new_book_add_two_books(self): collector.add_new_book('Гордость и предубеждение и зомби') collector.add_new_book('Что делать, если ваш кот хочет вас убить') - # проверяем, что добавилось именно две - # словарь books_rating, который нам возвращает метод get_books_rating, имеет длину 2 + # проверяем, что добавилось именно две книги + # словарь books_genre, который нам возвращает метод get_books_genre, имеет длину 2 assert len(collector.get_books_genre()) == 2 - # напиши свои тесты ниже - # Тест: добавление книги с названием длиннее 40 символов (не должно добавиться) - def test_add_new_book_too_long_name(self): - collector = BooksCollector() # новый экземпляр - long_name = 'а' * 41 # строка из 41 символа - collector.add_new_book(long_name) - assert long_name not in collector.books_genre + # добавление книг с разной длиной названия + @pytest.mark.parametrize('name, expected_in_books', [ + ('Нормальная книга', True), # корректное название + ('', False), # пустое название + ('а' * 41, False), # 41 символ (больше 40) + ('а' * 40, True), # 40 символов (граничное значение) + ('а' * 1, True), # 1 символ (граничное значение) + ('Книга с очень длинным названием которое почти сорок', False) # больше 40 + ]) + def test_add_new_book_different_lengths(self, name, expected_in_books): + collector = BooksCollector() + collector.add_new_book(name) + assert (name in collector.books_genre) == expected_in_books - # Тест: попытка добавить одну и ту же книгу дважды + # (отдельный тест, так как параметризация здесь неудобна) def test_add_new_book_duplicate(self): - collector = BooksCollector() # новый экземпляр - book_name = 'Война и мир' + collector = BooksCollector() + book_name = 'Дублирующая книга' + + # добавляем первый раз + collector.add_new_book(book_name) + assert book_name in collector.books_genre + assert len(collector.books_genre) == 1 + + # добавляем второй раз (дубликат) collector.add_new_book(book_name) - collector.add_new_book(book_name) # повторная попытка - assert len(collector.books_genre) == 1 # должна быть только одна запись - - # Тест: установка жанра для книги (успешный случай) - def test_set_book_genre_success(self): - collector = BooksCollector() # новый экземпляр - book_name = 'Гарри Поттер' - genre = 'Фантастика' + assert book_name in collector.books_genre + assert len(collector.books_genre) == 1 # количество не должно увеличиться + + # установка валидных жанров + @pytest.mark.parametrize('genre', ['Фантастика', 'Ужасы', 'Детективы', 'Мультфильмы', 'Комедии']) + def test_set_book_genre_valid_genres(self, genre): + collector = BooksCollector() + book_name = 'Тестовая книга' collector.add_new_book(book_name) collector.set_book_genre(book_name, genre) assert collector.get_book_genre(book_name) == genre - # Тест: установка несуществующего жанра (должен остаться пустой жанр) - def test_set_book_genre_invalid_genre(self): - collector = BooksCollector() # новый экземпляр - book_name = 'Незнайка на Луне' - invalid_genre = 'Романтика' # такого жанра нет в self.genre + # установка невалидных жанров + @pytest.mark.parametrize('invalid_genre', ['Роман', 'Поэзия', 'Драма', 'Триллер', '']) + def test_set_book_genre_invalid_genres(self, invalid_genre): + collector = BooksCollector() + book_name = 'Тестовая книга' collector.add_new_book(book_name) collector.set_book_genre(book_name, invalid_genre) - assert collector.get_book_genre(book_name) == '' # жанр не изменился + assert collector.get_book_genre(book_name) == '' # жанр должен остаться пустым - # Тест: получение списка книг с определённым жанром - def test_get_books_with_specific_genre(self): - collector = BooksCollector() # новый экземпляр + # получение жанра для разных книг + @pytest.mark.parametrize('book_name, genre, expected_genre', [ + ('Фантастическая книга', 'Фантастика', 'Фантастика'), + ('Страшная книга', 'Ужасы', 'Ужасы'), + ('Детективная книга', 'Детективы', 'Детективы'), + ('Мультик', 'Мультфильмы', 'Мультфильмы'), + ('Смешная книга', 'Комедии', 'Комедии'), + ('Книга без жанра', '', ''), + ]) + def test_get_book_genre_different_books(self, book_name, genre, expected_genre): + collector = BooksCollector() + + # добавляем книгу + collector.add_new_book(book_name) + + # устанавливаем жанр, если он указан + if genre: + collector.set_book_genre(book_name, genre) + + # проверяем, что метод возвращает правильный жанр + assert collector.get_book_genre(book_name) == expected_genre + # получение списка книг с определённым жанром + @pytest.mark.parametrize('genre, expected_books', [ + ('Фантастика', ['Фантастика 1', 'Фантастика 2']), + ('Детективы', ['Детектив 1']), + ('Ужасы', []), + ('Мультфильмы', ['Мультфильм 1']), + ('Комедии', ['Комедия 1', 'Комедия 2']), + ]) + def test_get_books_with_specific_genre(self, genre, expected_books): + collector = BooksCollector() + + # добавляем книги с разными жанрами + books_data = [ + ('Фантастика 1', 'Фантастика'), + ('Фантастика 2', 'Фантастика'), + ('Детектив 1', 'Детективы'), + ('Мультфильм 1', 'Мультфильмы'), + ('Комедия 1', 'Комедии'), + ('Комедия 2', 'Комедии'), + ] + for book_name, book_genre in books_data: + collector.add_new_book(book_name) + collector.set_book_genre(book_name, book_genre) + # получаем список книг с указанным жанром + books = collector.get_books_with_specific_genre(genre) + # проверяем, что получили ожидаемый список + assert books == expected_books + # проверка книг для детей + @pytest.mark.parametrize('book_name, genre, should_be_for_children', [ + ('Мультфильм для детей', 'Мультфильмы', True), + ('Смешная комедия', 'Комедии', True), + ('Космическая фантастика', 'Фантастика', True), + ('Страшный ужастик', 'Ужасы', False), + ('Загадочный детектив', 'Детективы', False), + ('Книга без жанра', '', False), + ]) + def test_get_books_for_children(self, book_name, genre, should_be_for_children): + collector = BooksCollector() + + # добавляем книгу + collector.add_new_book(book_name) + + # устанавливаем жанр, если он указан + if genre: + collector.set_book_genre(book_name, genre) + + # получаем список книг для детей + children_books = collector.get_books_for_children() + + # проверяем, есть ли книга в списке для детей + if should_be_for_children: + assert book_name in children_books + else: + assert book_name not in children_books + + # добавление книг в избранное + @pytest.mark.parametrize('book_name, book_exists, should_be_added', [ + ('Существующая книга', True, True), + ('Несуществующая книга', False, False), + ('', False, False), + ]) + def test_add_book_in_favorites(self, book_name, book_exists, should_be_added): + collector = BooksCollector() + + # если книга должна существовать, добавляем её в books_genre + if book_exists: + collector.add_new_book(book_name) + + # добавляем книгу в избранное + collector.add_book_in_favorites(book_name) + + # проверяем результат + if should_be_added: + assert book_name in collector.get_list_of_favorites_books() + else: + assert book_name not in collector.get_list_of_favorites_books() + + # удаление книг из избранного + @pytest.mark.parametrize('book_to_delete, expected_favorites', [ + ('Книга 1', ['Книга 2', 'Книга 3']), + ('Книга 2', ['Книга 1', 'Книга 3']), + ('Книга 3', ['Книга 1', 'Книга 2']), + ('Несуществующая книга', ['Книга 1', 'Книга 2', 'Книга 3']), + ]) + def test_delete_book_from_favorites(self, book_to_delete, expected_favorites): + collector = BooksCollector() + + # добавляем три книги в books_genre collector.add_new_book('Книга 1') collector.add_new_book('Книга 2') - collector.set_book_genre('Книга 1', 'Детективы') - collector.set_book_genre('Книга 2', 'Детективы') - detective_books = collector.get_books_with_specific_genre('Детективы') - assert 'Книга 1' in detective_books and 'Книга 2' in detective_books - - # Тест: получение книг для детей (без возрастного рейтинга) - def test_get_books_for_children(self): - collector = BooksCollector() # новый экземпляр - collector.add_new_book('Детская сказка') - collector.add_new_book('Страшный рассказ') - collector.set_book_genre('Детская сказка', 'Мультфильмы') # без рейтинга - collector.set_book_genre('Страшный рассказ', 'Ужасы') # с рейтингом - children_books = collector.get_books_for_children() - assert 'Детская сказка' in children_books - assert 'Страшный рассказ' not in children_books + collector.add_new_book('Книга 3') + + # добавляем все книги в избранное + collector.add_book_in_favorites('Книга 1') + collector.add_book_in_favorites('Книга 2') + collector.add_book_in_favorites('Книга 3') + + # удаляем указанную книгу + collector.delete_book_from_favorites(book_to_delete) + + # проверяем, что в избранном остались только ожидаемые книги + assert collector.get_list_of_favorites_books() == expected_favorites - # Тест: добавление книги в избранное - def test_add_book_in_favorites(self): - collector = BooksCollector() # новый экземпляр - book_name = 'Мастер и Маргарита' + # добавление одной и той же книги в избранное дважды + 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) - assert book_name in collector.get_list_of_favorites_books() - - # Тест: попытка добавить в избранное несуществующую книгу - def test_add_book_in_favorites_nonexistent(self): - collector = BooksCollector() # новый экземпляр - book_name = 'Неизвестная книга' - collector.add_book_in_favorites(book_name) # книги нет в books_genre - assert book_name not in collector.get_list_of_favorites_books() - - # Тест: удаление книги из избранного - def test_delete_book_from_favorites(self): - collector = BooksCollector() # новый экземпляр - book_name = '1984' - collector.add_new_book(book_name) collector.add_book_in_favorites(book_name) - collector.delete_book_from_favorites(book_name) - assert book_name not in collector.get_list_of_favorites_books() - - # Тест: получение полного словаря books_genre - def test_get_books_genre_dict(self): - collector = BooksCollector() # новый экземпляр - collector.add_new_book('Книга А') - collector.add_new_book('Книга Б') - genre_dict = collector.get_books_genre() - assert 'Книга А' in genre_dict and 'Книга Б' in genre_dict - assert genre_dict['Книга А'] == '' \ No newline at end of file + assert len(collector.get_list_of_favorites_books()) == 1 + assert collector.get_list_of_favorites_books() == [book_name] + + # получение словаря books_genre + def test_get_books_genre(self): + collector = BooksCollector() + collector.add_new_book('Книга 1') + collector.add_new_book('Книга 2') + collector.set_book_genre('Книга 1', 'Фантастика') + books_genre = collector.get_books_genre() + assert len(books_genre) == 2 + assert books_genre['Книга 1'] == 'Фантастика' + assert books_genre['Книга 2'] == '' + + # получение пустого списка избранного + def test_get_list_of_favorites_books_empty(self): + collector = BooksCollector() + assert collector.get_list_of_favorites_books() == [] + + # удаление книги, которой нет в избранном + def test_delete_book_from_favorites_nonexistent(self): + collector = BooksCollector() + collector.add_new_book('Книга 1') + collector.add_book_in_favorites('Книга 1') + collector.delete_book_from_favorites('Несуществующая книга') + assert collector.get_list_of_favorites_books() == ['Книга 1'] + + # установка жанра для несуществующей книги + def test_set_book_genre_for_nonexistent_book(self): + collector = BooksCollector() + collector.set_book_genre('Несуществующая книга', 'Фантастика') + assert collector.get_book_genre('Несуществующая книга') is None + + # изменение жанра у существующей книги + def test_set_book_genre_change_genre(self): + collector = BooksCollector() + book_name = 'Книга для смены жанра' + collector.add_new_book(book_name) + collector.set_book_genre(book_name, 'Ужасы') + assert collector.get_book_genre(book_name) == 'Ужасы' + collector.set_book_genre(book_name, 'Комедии') + assert collector.get_book_genre(book_name) == 'Комедии' \ No newline at end of file