mirror of
https://github.com/koloideal/Argenta.git
synced 2026-06-10 10:05:28 +03:00
benchs
This commit is contained in:
@@ -80,35 +80,15 @@ class BehaviorHandlersSettersMixin:
|
|||||||
self._exit_command_handler: NonStandardBehaviorHandler[Response] = exit_command_handler
|
self._exit_command_handler: NonStandardBehaviorHandler[Response] = exit_command_handler
|
||||||
|
|
||||||
def set_description_message_pattern(self, _: DescriptionMessageGenerator, /) -> None:
|
def set_description_message_pattern(self, _: DescriptionMessageGenerator, /) -> None:
|
||||||
"""
|
|
||||||
Public. Sets the output pattern of the available commands
|
|
||||||
:param _: output pattern of the available commands
|
|
||||||
:return: None
|
|
||||||
"""
|
|
||||||
self._description_message_generator = _
|
self._description_message_generator = _
|
||||||
|
|
||||||
def set_incorrect_input_syntax_handler(self, _: NonStandardBehaviorHandler[str], /) -> None:
|
def set_incorrect_input_syntax_handler(self, _: NonStandardBehaviorHandler[str], /) -> None:
|
||||||
"""
|
|
||||||
Public. Sets the handler for incorrect flags when entering a command
|
|
||||||
:param _: handler for incorrect flags when entering a command
|
|
||||||
:return: None
|
|
||||||
"""
|
|
||||||
self._incorrect_input_syntax_handler = _
|
self._incorrect_input_syntax_handler = _
|
||||||
|
|
||||||
def set_repeated_input_flags_handler(self, _: NonStandardBehaviorHandler[str], /) -> None:
|
def set_repeated_input_flags_handler(self, _: NonStandardBehaviorHandler[str], /) -> None:
|
||||||
"""
|
|
||||||
Public. Sets the handler for repeated flags when entering a command
|
|
||||||
:param _: handler for repeated flags when entering a command
|
|
||||||
:return: None
|
|
||||||
"""
|
|
||||||
self._repeated_input_flags_handler = _
|
self._repeated_input_flags_handler = _
|
||||||
|
|
||||||
def set_unknown_command_handler(self, _: NonStandardBehaviorHandler[InputCommand], /) -> None:
|
def set_unknown_command_handler(self, _: NonStandardBehaviorHandler[InputCommand], /) -> None:
|
||||||
"""
|
|
||||||
Public. Sets the handler for unknown commands when entering a command
|
|
||||||
:param _: handler for unknown commands when entering a command
|
|
||||||
:return: None
|
|
||||||
"""
|
|
||||||
self._unknown_command_handler = _
|
self._unknown_command_handler = _
|
||||||
|
|
||||||
def set_empty_command_handler(self, _: EmptyCommandHandler, /) -> None:
|
def set_empty_command_handler(self, _: EmptyCommandHandler, /) -> None:
|
||||||
|
|||||||
@@ -0,0 +1,229 @@
|
|||||||
|
import pytest
|
||||||
|
from unittest.mock import Mock
|
||||||
|
|
||||||
|
from argenta.app.behavior_handlers.models import BehaviorHandlersFabric, BehaviorHandlersSettersMixin
|
||||||
|
from argenta.app.presentation.renderers import PlainRenderer
|
||||||
|
from argenta.command.models import InputCommand
|
||||||
|
from argenta.response import Response, ResponseStatus
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def mock_printer() -> Mock:
|
||||||
|
return Mock()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def mock_most_similar_getter() -> Mock:
|
||||||
|
return Mock(return_value="similar_cmd")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def behavior_fabric(mock_printer: Mock, mock_most_similar_getter: Mock) -> BehaviorHandlersFabric:
|
||||||
|
renderer = PlainRenderer()
|
||||||
|
return BehaviorHandlersFabric(mock_printer, renderer, mock_most_similar_getter)
|
||||||
|
|
||||||
|
|
||||||
|
class TestBehaviorHandlersFabric:
|
||||||
|
def test_initialization(self, mock_printer: Mock, mock_most_similar_getter: Mock):
|
||||||
|
renderer = PlainRenderer()
|
||||||
|
fabric = BehaviorHandlersFabric(mock_printer, renderer, mock_most_similar_getter)
|
||||||
|
|
||||||
|
assert fabric._printer == mock_printer
|
||||||
|
assert fabric._renderer == renderer
|
||||||
|
assert fabric._most_similar_command_getter == mock_most_similar_getter
|
||||||
|
|
||||||
|
def test_generate_incorrect_input_syntax_handler(self, behavior_fabric: BehaviorHandlersFabric, mock_printer: Mock):
|
||||||
|
handler = behavior_fabric.generate_incorrect_input_syntax_handler()
|
||||||
|
|
||||||
|
handler("bad --flag")
|
||||||
|
|
||||||
|
mock_printer.assert_called_once()
|
||||||
|
call_arg = mock_printer.call_args[0][0]
|
||||||
|
assert "Incorrect flag syntax" in call_arg
|
||||||
|
assert "bad --flag" in call_arg
|
||||||
|
|
||||||
|
def test_generate_repeated_input_flags_handler(self, behavior_fabric: BehaviorHandlersFabric, mock_printer: Mock):
|
||||||
|
handler = behavior_fabric.generate_repeated_input_flags_handler()
|
||||||
|
|
||||||
|
handler("cmd --flag --flag")
|
||||||
|
|
||||||
|
mock_printer.assert_called_once()
|
||||||
|
call_arg = mock_printer.call_args[0][0]
|
||||||
|
assert "Repeated input flags" in call_arg
|
||||||
|
assert "cmd --flag --flag" in call_arg
|
||||||
|
|
||||||
|
def test_generate_empty_input_command_handler(self, behavior_fabric: BehaviorHandlersFabric, mock_printer: Mock):
|
||||||
|
handler = behavior_fabric.generate_empty_input_command_handler()
|
||||||
|
|
||||||
|
handler()
|
||||||
|
|
||||||
|
mock_printer.assert_called_once()
|
||||||
|
call_arg = mock_printer.call_args[0][0]
|
||||||
|
assert "Empty input command" in call_arg
|
||||||
|
|
||||||
|
def test_generate_unknown_command_handler(self, behavior_fabric: BehaviorHandlersFabric, mock_printer: Mock, mock_most_similar_getter: Mock):
|
||||||
|
handler = behavior_fabric.generate_unknown_command_handler()
|
||||||
|
|
||||||
|
input_command = InputCommand("unknown")
|
||||||
|
handler(input_command)
|
||||||
|
|
||||||
|
mock_most_similar_getter.assert_called_once_with("unknown")
|
||||||
|
mock_printer.assert_called_once()
|
||||||
|
call_arg = mock_printer.call_args[0][0]
|
||||||
|
assert "Unknown command" in call_arg
|
||||||
|
assert "unknown" in call_arg
|
||||||
|
assert "similar_cmd" in call_arg
|
||||||
|
|
||||||
|
def test_generate_unknown_command_handler_no_similar(self, mock_printer: Mock):
|
||||||
|
renderer = PlainRenderer()
|
||||||
|
most_similar_getter = Mock(return_value=None)
|
||||||
|
fabric = BehaviorHandlersFabric(mock_printer, renderer, most_similar_getter)
|
||||||
|
|
||||||
|
handler = fabric.generate_unknown_command_handler()
|
||||||
|
input_command = InputCommand("unknown")
|
||||||
|
handler(input_command)
|
||||||
|
|
||||||
|
most_similar_getter.assert_called_once_with("unknown")
|
||||||
|
mock_printer.assert_called_once()
|
||||||
|
call_arg = mock_printer.call_args[0][0]
|
||||||
|
assert "Unknown command" in call_arg
|
||||||
|
assert "unknown" in call_arg
|
||||||
|
assert "most similar" not in call_arg
|
||||||
|
|
||||||
|
def test_generate_exit_command_handler(self, behavior_fabric: BehaviorHandlersFabric, mock_printer: Mock):
|
||||||
|
handler = behavior_fabric.generate_exit_command_handler("Goodbye!")
|
||||||
|
|
||||||
|
response = Response(ResponseStatus.ALL_FLAGS_VALID)
|
||||||
|
handler(response)
|
||||||
|
|
||||||
|
mock_printer.assert_called_once_with("Goodbye!")
|
||||||
|
|
||||||
|
def test_generate_description_message_generator(self, behavior_fabric: BehaviorHandlersFabric):
|
||||||
|
generator = behavior_fabric.generate_description_message_generator()
|
||||||
|
|
||||||
|
result = generator("test", "Test command")
|
||||||
|
|
||||||
|
assert "test" in result
|
||||||
|
assert "Test command" in result
|
||||||
|
|
||||||
|
|
||||||
|
class TestBehaviorHandlersSettersMixin:
|
||||||
|
def test_initialization(self):
|
||||||
|
desc_gen = lambda cmd, desc: f"{cmd}: {desc}"
|
||||||
|
incorrect_handler = lambda raw: None
|
||||||
|
repeated_handler = lambda raw: None
|
||||||
|
empty_handler = lambda: None
|
||||||
|
unknown_handler = lambda cmd: None
|
||||||
|
exit_handler = lambda resp: None
|
||||||
|
|
||||||
|
mixin = BehaviorHandlersSettersMixin(
|
||||||
|
desc_gen,
|
||||||
|
incorrect_handler,
|
||||||
|
repeated_handler,
|
||||||
|
empty_handler,
|
||||||
|
unknown_handler,
|
||||||
|
exit_handler
|
||||||
|
)
|
||||||
|
|
||||||
|
assert mixin._description_message_generator == desc_gen
|
||||||
|
assert mixin._incorrect_input_syntax_handler == incorrect_handler
|
||||||
|
assert mixin._repeated_input_flags_handler == repeated_handler
|
||||||
|
assert mixin._empty_input_command_handler == empty_handler
|
||||||
|
assert mixin._unknown_command_handler == unknown_handler
|
||||||
|
assert mixin._exit_command_handler == exit_handler
|
||||||
|
|
||||||
|
def test_set_description_message_pattern(self):
|
||||||
|
initial_gen = lambda cmd, desc: f"{cmd}: {desc}"
|
||||||
|
mixin = BehaviorHandlersSettersMixin(
|
||||||
|
initial_gen,
|
||||||
|
lambda raw: None,
|
||||||
|
lambda raw: None,
|
||||||
|
lambda: None,
|
||||||
|
lambda cmd: None,
|
||||||
|
lambda resp: None
|
||||||
|
)
|
||||||
|
|
||||||
|
new_gen = lambda cmd, desc: f"{cmd} -> {desc}"
|
||||||
|
mixin.set_description_message_pattern(new_gen)
|
||||||
|
|
||||||
|
assert mixin._description_message_generator == new_gen
|
||||||
|
|
||||||
|
def test_set_incorrect_input_syntax_handler(self):
|
||||||
|
initial_handler = lambda raw: None
|
||||||
|
mixin = BehaviorHandlersSettersMixin(
|
||||||
|
lambda cmd, desc: f"{cmd}: {desc}",
|
||||||
|
initial_handler,
|
||||||
|
lambda raw: None,
|
||||||
|
lambda: None,
|
||||||
|
lambda cmd: None,
|
||||||
|
lambda resp: None
|
||||||
|
)
|
||||||
|
|
||||||
|
new_handler = lambda raw: print(f"Error: {raw}")
|
||||||
|
mixin.set_incorrect_input_syntax_handler(new_handler)
|
||||||
|
|
||||||
|
assert mixin._incorrect_input_syntax_handler == new_handler
|
||||||
|
|
||||||
|
def test_set_repeated_input_flags_handler(self):
|
||||||
|
initial_handler = lambda raw: None
|
||||||
|
mixin = BehaviorHandlersSettersMixin(
|
||||||
|
lambda cmd, desc: f"{cmd}: {desc}",
|
||||||
|
lambda raw: None,
|
||||||
|
initial_handler,
|
||||||
|
lambda: None,
|
||||||
|
lambda cmd: None,
|
||||||
|
lambda resp: None
|
||||||
|
)
|
||||||
|
|
||||||
|
new_handler = lambda raw: print(f"Repeated: {raw}")
|
||||||
|
mixin.set_repeated_input_flags_handler(new_handler)
|
||||||
|
|
||||||
|
assert mixin._repeated_input_flags_handler == new_handler
|
||||||
|
|
||||||
|
def test_set_unknown_command_handler(self):
|
||||||
|
initial_handler = lambda cmd: None
|
||||||
|
mixin = BehaviorHandlersSettersMixin(
|
||||||
|
lambda cmd, desc: f"{cmd}: {desc}",
|
||||||
|
lambda raw: None,
|
||||||
|
lambda raw: None,
|
||||||
|
lambda: None,
|
||||||
|
initial_handler,
|
||||||
|
lambda resp: None
|
||||||
|
)
|
||||||
|
|
||||||
|
new_handler = lambda cmd: print(f"Unknown: {cmd.trigger}")
|
||||||
|
mixin.set_unknown_command_handler(new_handler)
|
||||||
|
|
||||||
|
assert mixin._unknown_command_handler == new_handler
|
||||||
|
|
||||||
|
def test_set_empty_command_handler(self):
|
||||||
|
initial_handler = lambda: None
|
||||||
|
mixin = BehaviorHandlersSettersMixin(
|
||||||
|
lambda cmd, desc: f"{cmd}: {desc}",
|
||||||
|
lambda raw: None,
|
||||||
|
lambda raw: None,
|
||||||
|
initial_handler,
|
||||||
|
lambda cmd: None,
|
||||||
|
lambda resp: None
|
||||||
|
)
|
||||||
|
|
||||||
|
new_handler = lambda: print("Empty command")
|
||||||
|
mixin.set_empty_command_handler(new_handler)
|
||||||
|
|
||||||
|
assert mixin._empty_input_command_handler == new_handler
|
||||||
|
|
||||||
|
def test_set_exit_command_handler(self):
|
||||||
|
initial_handler = lambda resp: None
|
||||||
|
mixin = BehaviorHandlersSettersMixin(
|
||||||
|
lambda cmd, desc: f"{cmd}: {desc}",
|
||||||
|
lambda raw: None,
|
||||||
|
lambda raw: None,
|
||||||
|
lambda: None,
|
||||||
|
lambda cmd: None,
|
||||||
|
initial_handler
|
||||||
|
)
|
||||||
|
|
||||||
|
new_handler = lambda resp: print("Exiting...")
|
||||||
|
mixin.set_exit_command_handler(new_handler)
|
||||||
|
|
||||||
|
assert mixin._exit_command_handler == new_handler
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
from pytest_mock import MockerFixture
|
import pytest
|
||||||
|
from unittest.mock import Mock
|
||||||
|
|
||||||
from argenta.app.presentation.viewers import Viewer
|
from argenta.app.presentation.viewers import Viewer
|
||||||
from argenta.app.presentation.renderers import PlainRenderer
|
from argenta.app.presentation.renderers import PlainRenderer
|
||||||
@@ -9,45 +10,51 @@ from argenta.response import Response
|
|||||||
from argenta.router import Router
|
from argenta.router import Router
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def mock_printer() -> Mock:
|
||||||
|
return Mock()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def mock_output_generator() -> Mock:
|
||||||
|
return Mock()
|
||||||
|
|
||||||
|
|
||||||
class TestViewer:
|
class TestViewer:
|
||||||
def test_viewer_initialization(self, mocker: MockerFixture):
|
def test_viewer_initialization(self, mock_printer: Mock):
|
||||||
printer = mocker.Mock()
|
|
||||||
renderer = PlainRenderer()
|
renderer = PlainRenderer()
|
||||||
dividing_line = StaticDividingLine()
|
dividing_line = StaticDividingLine()
|
||||||
|
|
||||||
viewer = Viewer(printer, renderer, dividing_line, False)
|
viewer = Viewer(mock_printer, renderer, dividing_line, False)
|
||||||
|
|
||||||
assert viewer._printer == printer
|
assert viewer._printer == mock_printer
|
||||||
assert viewer._renderer == renderer
|
assert viewer._renderer == renderer
|
||||||
assert viewer._dividing_line == dividing_line
|
assert viewer._dividing_line == dividing_line
|
||||||
assert viewer._override_system_messages is False
|
assert viewer._override_system_messages is False
|
||||||
|
|
||||||
def test_view_initial_message(self, mocker: MockerFixture):
|
def test_view_initial_message(self, mock_printer: Mock):
|
||||||
printer = mocker.Mock()
|
|
||||||
renderer = PlainRenderer()
|
renderer = PlainRenderer()
|
||||||
viewer = Viewer(printer, renderer, None, False)
|
viewer = Viewer(mock_printer, renderer, None, False)
|
||||||
|
|
||||||
viewer.view_initial_message("Welcome")
|
viewer.view_initial_message("Welcome")
|
||||||
|
|
||||||
printer.assert_called_once_with("Welcome")
|
mock_printer.assert_called_once_with("Welcome")
|
||||||
|
|
||||||
def test_view_messages_on_startup(self, mocker: MockerFixture):
|
def test_view_messages_on_startup(self, mock_printer: Mock):
|
||||||
printer = mocker.Mock()
|
|
||||||
renderer = PlainRenderer()
|
renderer = PlainRenderer()
|
||||||
viewer = Viewer(printer, renderer, None, False)
|
viewer = Viewer(mock_printer, renderer, None, False)
|
||||||
|
|
||||||
messages = ["Message 1", "Message 2"]
|
messages = ["Message 1", "Message 2"]
|
||||||
viewer.view_messages_on_startup(messages)
|
viewer.view_messages_on_startup(messages)
|
||||||
|
|
||||||
printer.assert_called_once()
|
mock_printer.assert_called_once()
|
||||||
call_arg = printer.call_args[0][0]
|
call_arg = mock_printer.call_args[0][0]
|
||||||
assert "Message 1" in call_arg
|
assert "Message 1" in call_arg
|
||||||
assert "Message 2" in call_arg
|
assert "Message 2" in call_arg
|
||||||
|
|
||||||
def test_view_command_groups_description(self, mocker: MockerFixture):
|
def test_view_command_groups_description(self, mock_printer: Mock):
|
||||||
printer = mocker.Mock()
|
|
||||||
renderer = PlainRenderer()
|
renderer = PlainRenderer()
|
||||||
viewer = Viewer(printer, renderer, None, False)
|
viewer = Viewer(mock_printer, renderer, None, False)
|
||||||
|
|
||||||
router = Router(title="Test Router")
|
router = Router(title="Test Router")
|
||||||
|
|
||||||
@@ -63,37 +70,32 @@ class TestViewer:
|
|||||||
|
|
||||||
viewer.view_command_groups_description(desc_gen, registered_routers)
|
viewer.view_command_groups_description(desc_gen, registered_routers)
|
||||||
|
|
||||||
printer.assert_called_once()
|
mock_printer.assert_called_once()
|
||||||
call_arg = printer.call_args[0][0]
|
call_arg = mock_printer.call_args[0][0]
|
||||||
assert "Test Router" in call_arg
|
assert "Test Router" in call_arg
|
||||||
assert "test: Test command" in call_arg
|
assert "test: Test command" in call_arg
|
||||||
|
|
||||||
def test_view_framed_text_with_no_dividing_line(self, mocker: MockerFixture):
|
def test_view_framed_text_with_no_dividing_line(self, mock_printer: Mock, mock_output_generator: Mock):
|
||||||
printer = mocker.Mock()
|
|
||||||
renderer = PlainRenderer()
|
renderer = PlainRenderer()
|
||||||
viewer = Viewer(printer, renderer, None, False)
|
viewer = Viewer(mock_printer, renderer, None, False)
|
||||||
|
|
||||||
output_generator = mocker.Mock()
|
viewer.view_framed_text_from_generator(mock_output_generator)
|
||||||
viewer.view_framed_text_from_generator(output_generator)
|
|
||||||
|
|
||||||
output_generator.assert_called_once()
|
mock_output_generator.assert_called_once()
|
||||||
|
|
||||||
def test_view_framed_text_with_static_dividing_line(self, mocker: MockerFixture):
|
def test_view_framed_text_with_static_dividing_line(self, mock_printer: Mock, mock_output_generator: Mock):
|
||||||
printer = mocker.Mock()
|
|
||||||
renderer = PlainRenderer()
|
renderer = PlainRenderer()
|
||||||
dividing_line = StaticDividingLine("=")
|
dividing_line = StaticDividingLine("=")
|
||||||
viewer = Viewer(printer, renderer, dividing_line, False)
|
viewer = Viewer(mock_printer, renderer, dividing_line, False)
|
||||||
|
|
||||||
output_generator = mocker.Mock()
|
viewer.view_framed_text_from_generator(mock_output_generator)
|
||||||
viewer.view_framed_text_from_generator(output_generator)
|
|
||||||
|
|
||||||
output_generator.assert_called_once()
|
mock_output_generator.assert_called_once()
|
||||||
assert printer.call_count >= 2
|
assert mock_printer.call_count >= 2
|
||||||
|
|
||||||
def test_capture_stdout(self, mocker: MockerFixture):
|
def test_capture_stdout(self, mock_printer: Mock):
|
||||||
printer = mocker.Mock()
|
|
||||||
renderer = PlainRenderer()
|
renderer = PlainRenderer()
|
||||||
viewer = Viewer(printer, renderer, None, False)
|
viewer = Viewer(mock_printer, renderer, None, False)
|
||||||
|
|
||||||
def test_func():
|
def test_func():
|
||||||
print("test output")
|
print("test output")
|
||||||
@@ -101,10 +103,9 @@ class TestViewer:
|
|||||||
result = viewer._capture_stdout(test_func)
|
result = viewer._capture_stdout(test_func)
|
||||||
assert "test output" in result
|
assert "test output" in result
|
||||||
|
|
||||||
def test_capture_stdout_reuses_buffer(self, mocker: MockerFixture):
|
def test_capture_stdout_reuses_buffer(self, mock_printer: Mock):
|
||||||
printer = mocker.Mock()
|
|
||||||
renderer = PlainRenderer()
|
renderer = PlainRenderer()
|
||||||
viewer = Viewer(printer, renderer, None, False)
|
viewer = Viewer(mock_printer, renderer, None, False)
|
||||||
|
|
||||||
def test_func1():
|
def test_func1():
|
||||||
print("output 1")
|
print("output 1")
|
||||||
@@ -119,27 +120,24 @@ class TestViewer:
|
|||||||
assert "output 1" not in result2
|
assert "output 1" not in result2
|
||||||
assert "output 2" in result2
|
assert "output 2" in result2
|
||||||
|
|
||||||
def test_view_framed_text_with_dynamic_dividing_line(self, mocker: MockerFixture):
|
def test_view_framed_text_with_dynamic_dividing_line(self, mock_printer: Mock):
|
||||||
printer = mocker.Mock()
|
|
||||||
renderer = PlainRenderer()
|
renderer = PlainRenderer()
|
||||||
dividing_line = DynamicDividingLine("=")
|
dividing_line = DynamicDividingLine("=")
|
||||||
viewer = Viewer(printer, renderer, dividing_line, False)
|
viewer = Viewer(mock_printer, renderer, dividing_line, False)
|
||||||
|
|
||||||
def output_generator():
|
def output_generator():
|
||||||
print("test output")
|
print("test output")
|
||||||
|
|
||||||
viewer.view_framed_text_from_generator(output_generator)
|
viewer.view_framed_text_from_generator(output_generator)
|
||||||
|
|
||||||
assert printer.call_count >= 2
|
assert mock_printer.call_count >= 2
|
||||||
|
|
||||||
def test_view_framed_text_with_router_stdout_redirect(self, mocker: MockerFixture):
|
def test_view_framed_text_with_router_stdout_redirect(self, mock_printer: Mock, mock_output_generator: Mock):
|
||||||
printer = mocker.Mock()
|
|
||||||
renderer = PlainRenderer()
|
renderer = PlainRenderer()
|
||||||
dividing_line = DynamicDividingLine("=")
|
dividing_line = DynamicDividingLine("=")
|
||||||
viewer = Viewer(printer, renderer, dividing_line, False)
|
viewer = Viewer(mock_printer, renderer, dividing_line, False)
|
||||||
|
|
||||||
output_generator = mocker.Mock()
|
viewer.view_framed_text_from_generator(mock_output_generator, is_stdout_redirected_by_router=True)
|
||||||
viewer.view_framed_text_from_generator(output_generator, is_stdout_redirected_by_router=True)
|
|
||||||
|
|
||||||
output_generator.assert_called_once()
|
mock_output_generator.assert_called_once()
|
||||||
assert printer.call_count >= 2
|
assert mock_printer.call_count >= 2
|
||||||
|
|||||||
Reference in New Issue
Block a user