Skip to content

Commit fc98c77

Browse files
Add tests for controller
1 parent fb46766 commit fc98c77

5 files changed

Lines changed: 215 additions & 34 deletions

File tree

homework_03/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## Запуск
44

55
```shell
6+
cd homework_03
67
python main.py
78
```
89

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from controller import PhonebookController
1+
from src.controller import PhonebookController
22

33

44
if __name__ == '__main__':

homework_03/src/__init__.py

Whitespace-only changes.

homework_03/src/controller.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ def _print_contacts(self):
8080
"""Print all contacts."""
8181
for contact in self.phonebook.contacts():
8282
OutputView.contact_info(
83-
contact_id=contact.id_,
83+
contact_id=contact.id,
8484
name=contact.name,
8585
phone=contact.phone,
8686
comment=contact.comment,

homework_03/tests/controller/test_controller.py

Lines changed: 212 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
import os
22
import random
33
from unittest import TestCase
4-
from unittest.mock import call, patch
4+
from unittest.mock import call, patch, MagicMock
55

66
from src.controller import PhonebookController, CommandNotFound, FieldRequired
7-
from src.model import JsonStorage
7+
from src.model import Contact, JsonStorage
88
from src.view import Commands
99
from tests.utils import (
1010
generate_random_id,
1111
generate_random_string,
12+
generate_random_phone,
1213
generate_contact,
1314
generate_contacts,
15+
generate_contacts_storage,
1416
)
1517

1618

@@ -180,14 +182,12 @@ def test_entered_integer_value(self):
180182
self.assertEqual(result, expected)
181183

182184
def test_entered_not_integer_value(self):
183-
with patch(
184-
"src.view.InputView.ask_required_field",
185-
return_value=generate_random_string()
186-
):
185+
value = generate_random_string()
186+
with patch("src.view.InputView.ask_required_field", return_value=value):
187187
self.assertRaises(
188188
ValueError,
189189
self.controller._get_required_integer_field,
190-
generate_random_id(),
190+
value,
191191
)
192192

193193

@@ -217,40 +217,220 @@ def test_get_contact_called(self, get_contact, update_fields):
217217
self.controller._edit_contact()
218218
get_contact.assert_called_with(contact_id)
219219

220-
# @patch("src.view.InputView.update_field")
220+
@patch("src.view.InputView.update_field")
221221
@patch("src.model.PhonebookModel.get")
222222
@patch("src.controller.PhonebookController._get_required_integer_field")
223-
def test_new_name_asked(self, ask_id, get_contact):
224-
with patch("src.view.InputView.update_field") as ask_new_values:
225-
self.controller._edit_contact()
226-
calls = [call("name"), call("phone"), call("comment")]
227-
ask_new_values.assert_has_calls(calls, any_order=True)
228-
self.assertEqual(3, ask_new_values.call_count)
223+
def test_new_values_asked(self, ask_id, get_contact, ask_new_values):
224+
self.controller._edit_contact()
225+
calls = [call("name"), call("phone"), call("comment")]
226+
ask_new_values.assert_has_calls(calls, any_order=True)
227+
self.assertEqual(len(calls), ask_new_values.call_count)
229228

229+
@patch("src.controller.PhonebookController._get_required_integer_field")
230+
def test_update_name_called(self, ask_id):
231+
contact = generate_contact()
232+
contact.update_name = MagicMock()
230233

231-
def test_update_name_called(self):
232-
pass
234+
new_name = generate_random_string()
235+
with patch("src.view.InputView.update_field", side_effect=[new_name, "", ""]):
236+
with patch("src.model.PhonebookModel.get", return_value=contact):
237+
self.controller._edit_contact()
238+
contact.update_name.assert_called_with(new_name)
233239

234-
def test_try_clear_name(self):
235-
pass
240+
@patch("src.view.InputView.update_field", side_effect=["<", "", ""])
241+
@patch("src.model.PhonebookModel.get")
242+
@patch("src.controller.PhonebookController._get_required_integer_field")
243+
def test_try_clear_name(self, ask_id, get_contact, ask_new_values):
244+
self.assertRaises(ValueError, self.controller._edit_contact)
236245

237-
def test_new_phone_asked(self):
238-
pass
246+
@patch("src.controller.PhonebookController._get_required_integer_field")
247+
def test_update_phone_called(self, ask_id):
248+
contact = generate_contact()
249+
contact.update_phone = MagicMock()
239250

240-
def test_update_phone_called(self):
241-
pass
251+
new_phone = generate_random_phone()
252+
with patch("src.view.InputView.update_field", side_effect=["", new_phone, ""]):
253+
with patch("src.model.PhonebookModel.get", return_value=contact):
254+
self.controller._edit_contact()
255+
contact.update_phone.assert_called_with(new_phone)
242256

243-
def test_try_clear_phone(self):
244-
pass
257+
@patch("src.view.InputView.update_field", side_effect=["", "<", ""])
258+
@patch("src.model.PhonebookModel.get")
259+
@patch("src.controller.PhonebookController._get_required_integer_field")
260+
def test_try_clear_phone(self, ask_id, get_contact, ask_new_values):
261+
self.assertRaises(ValueError, self.controller._edit_contact)
245262

246-
def test_new_comment_asked(self):
247-
pass
263+
@patch("src.view.InputView.update_field", side_effect=["", "", "<"])
264+
@patch("src.model.PhonebookModel.get")
265+
@patch("src.controller.PhonebookController._get_required_integer_field")
266+
def test_clear_comment_called(self, ask_id, get_contact, ask_new_values):
267+
contact = generate_contact()
268+
contact.clear_comment = MagicMock()
248269

249-
def test_clear_comment_called(self):
250-
pass
270+
with patch("src.view.InputView.update_field", side_effect=["", "", "<"]):
271+
with patch("src.model.PhonebookModel.get", return_value=contact):
272+
self.controller._edit_contact()
273+
contact.clear_comment.assert_called()
251274

252-
def test_update_comment_called(self):
253-
pass
275+
@patch("src.controller.PhonebookController._get_required_integer_field")
276+
def test_update_comment_called(self, ask_id):
277+
contact = generate_contact()
278+
contact.update_comment = MagicMock()
279+
280+
new_comment = generate_random_phone()
281+
with patch(
282+
"src.view.InputView.update_field", side_effect=["", "", new_comment]
283+
):
284+
with patch("src.model.PhonebookModel.get", return_value=contact):
285+
self.controller._edit_contact()
286+
contact.update_comment.assert_called_with(new_comment)
254287

255-
def test_return_contact(self):
256-
pass
288+
@patch("src.view.InputView.update_field", side_effect=["", "", ""])
289+
@patch("src.model.PhonebookModel.get")
290+
@patch("src.controller.PhonebookController._get_required_integer_field")
291+
def test_return_contact(self, ask_id, get_contact, ask_new_values):
292+
contact = generate_contact()
293+
with patch("src.model.PhonebookModel.get", return_value=contact):
294+
result = self.controller._edit_contact()
295+
self.assertIsInstance(result, Contact)
296+
297+
298+
class TestDeleteContact(TestCase):
299+
def setUp(self):
300+
self.controller = PhonebookController()
301+
302+
def tearDown(self):
303+
if os.path.isfile(JsonStorage.STORAGE):
304+
os.remove(JsonStorage.STORAGE)
305+
306+
@patch("src.controller.PhonebookController._get_required_integer_field")
307+
def test_id_asked(self, ask_id):
308+
self.controller._delete_contact()
309+
ask_id.assert_called_with("Contact ID")
310+
311+
@patch("src.model.PhonebookModel.delete_contact")
312+
def test_delete_contact_called(self, delete_contact):
313+
id_ = generate_random_id()
314+
with patch(
315+
"src.controller.PhonebookController._get_required_integer_field",
316+
return_value=id_,
317+
):
318+
self.controller._delete_contact()
319+
delete_contact.assert_called_with(id_)
320+
321+
322+
class TestShowStorage(TestCase):
323+
def setUp(self):
324+
self.controller = PhonebookController()
325+
326+
def tearDown(self):
327+
if os.path.isfile(JsonStorage.STORAGE):
328+
os.remove(JsonStorage.STORAGE)
329+
330+
@patch("src.view.OutputView.print_raw")
331+
@patch("src.model.PhonebookModel.raw_storage")
332+
def test_raw_storage_asked(self, raw_storage, output):
333+
self.controller._show_storage()
334+
raw_storage.assert_called()
335+
336+
@patch("src.view.OutputView.print_raw")
337+
def test_storage_showed_in_view(self, output_view):
338+
storage = generate_contacts_storage()
339+
with patch("src.model.PhonebookModel.raw_storage", return_value=storage):
340+
self.controller._show_storage()
341+
output_view.assert_called_with(storage)
342+
343+
344+
class TestPrintContacts(TestCase):
345+
def setUp(self):
346+
self.controller = PhonebookController()
347+
348+
def tearDown(self):
349+
if os.path.isfile(JsonStorage.STORAGE):
350+
os.remove(JsonStorage.STORAGE)
351+
352+
@patch("src.view.OutputView.contact_info")
353+
def test_print_all_contacts(self, contact_info):
354+
contacts = list(generate_contacts())
355+
calls = [
356+
call(contact_id=c.id, name=c.name, phone=c.phone, comment=c.comment)
357+
for c in contacts
358+
]
359+
with patch(
360+
"src.model.PhonebookModel.contacts", return_value=iter(contacts)
361+
) as mock_contacts:
362+
self.controller._print_contacts()
363+
contact_info.assert_has_calls(calls)
364+
365+
366+
class TestRun(TestCase):
367+
def setUp(self):
368+
self.controller = PhonebookController()
369+
370+
def tearDown(self):
371+
if os.path.isfile(JsonStorage.STORAGE):
372+
os.remove(JsonStorage.STORAGE)
373+
374+
@patch(
375+
"src.controller.PhonebookController._get_command_or_raise", return_value="exit"
376+
)
377+
def test_ask_command(self, ask_command):
378+
self.controller.run()
379+
ask_command.asserc_called_once()
380+
381+
@patch("src.view.ErrorView.unknown_command")
382+
def test_unknown_command(self, view_mock):
383+
command = generate_random_string(length=100)
384+
error_message = f"Command {command} not found"
385+
with patch(
386+
"src.controller.PhonebookController._get_command_or_raise",
387+
side_effect=[CommandNotFound(error_message), "exit"],
388+
):
389+
self.controller.run()
390+
view_mock.assert_called_with(error_message)
391+
392+
@patch("src.controller.PhonebookController._add_contact")
393+
def test_add_command(self, add_contact):
394+
with patch(
395+
"src.controller.PhonebookController._get_command_or_raise",
396+
side_effect=["add", "exit"],
397+
):
398+
self.controller.run()
399+
add_contact.assert_called_once()
400+
401+
@patch("src.view.ErrorView.required_field")
402+
def test_add_command_error(self, view):
403+
field_name = generate_random_string()
404+
with patch(
405+
"src.controller.PhonebookController._add_contact",
406+
side_effect=FieldRequired(field_name),
407+
):
408+
with patch(
409+
"src.controller.PhonebookController._get_command_or_raise",
410+
side_effect=["add", "exit"],
411+
):
412+
self.controller.run()
413+
view.assert_called_with(field_name)
414+
415+
@patch("src.controller.PhonebookController._find_contact")
416+
def test_find_contact(self, find_contact):
417+
with patch(
418+
"src.controller.PhonebookController._get_command_or_raise",
419+
side_effect=["find", "exit"],
420+
):
421+
self.controller.run()
422+
find_contact.assert_called_once()
423+
424+
@patch("src.view.ErrorView.required_field")
425+
def test_find_contact_error(self, view):
426+
field_name = generate_random_string()
427+
with patch(
428+
"src.controller.PhonebookController._find_contact",
429+
side_effect=FieldRequired(field_name),
430+
):
431+
with patch(
432+
"src.controller.PhonebookController._get_command_or_raise",
433+
side_effect=["find", "exit"],
434+
):
435+
self.controller.run()
436+
view.assert_called_with(field_name)

0 commit comments

Comments
 (0)