Skip to content

Commit 5caf308

Browse files
committed
Adding a CLI timeout flag and unit tests
1 parent 937fc4c commit 5caf308

3 files changed

Lines changed: 131 additions & 0 deletions

File tree

tests/test_run_tests.py

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,103 @@ def test_run_tests_config_data_processing(
689689
assert "dut_config" in result.output
690690
assert "network" in result.output
691691

692+
def test_run_tests_prompt_timeout_merges_into_execution_config(
693+
self,
694+
cli_runner: CliRunner,
695+
mock_async_apis: Mock,
696+
sample_test_collections: api_models.TestCollections,
697+
sample_test_run_execution: api_models.TestRunExecutionWithChildren,
698+
sample_default_config_dict: dict,
699+
) -> None:
700+
"""--prompt-timeout should merge th_config.prompt_timeout_seconds into the
701+
execution config submitted for the run, without requiring --config."""
702+
# Arrange
703+
project_api = mock_async_apis.projects_api.default_config_api_v1_projects_default_config_get
704+
test_collection_api = mock_async_apis.test_collections_api.read_test_collections_api_v1_test_collections__get
705+
test_run_executions_api = mock_async_apis.test_run_executions_api
706+
cli_api = test_run_executions_api.create_cli_test_run_execution_api_v1_test_run_executions_cli_post
707+
id_start = test_run_executions_api.start_test_run_execution_api_v1_test_run_executions_id_start_post
708+
709+
project_api.return_value = sample_default_config_dict
710+
test_collection_api.return_value = sample_test_collections
711+
cli_api.return_value = sample_test_run_execution
712+
id_start.return_value = sample_test_run_execution
713+
with patch("th_cli.commands.run_tests.AsyncApis", return_value=mock_async_apis):
714+
with patch(
715+
"th_cli.commands.run_tests.test_logging.configure_logger_for_run", return_value="./test_logs/test.log"
716+
):
717+
with patch("th_cli.commands.run_tests.TestRunSocket") as mock_socket_class:
718+
with patch(
719+
"th_cli.commands.run_tests.convert_nested_to_dict", return_value=sample_default_config_dict
720+
):
721+
mock_socket = Mock()
722+
mock_socket.connect_websocket = AsyncMock()
723+
mock_socket_class.return_value = mock_socket
724+
725+
# Act
726+
result = cli_runner.invoke(
727+
run_tests,
728+
["--tests-list", "TC-ACE-1.1", "--prompt-timeout", "300"],
729+
)
730+
731+
# Assert
732+
assert result.exit_code == 0
733+
assert "Prompt Timeout Used (Execution Only)" in result.output
734+
submitted_body = cli_api.call_args[0][0]
735+
assert submitted_body.execution_config["th_config"]["prompt_timeout_seconds"] == 300
736+
737+
def test_run_tests_prompt_timeout_wins_over_config_file(
738+
self,
739+
cli_runner: CliRunner,
740+
mock_async_apis: Mock,
741+
sample_test_collections: api_models.TestCollections,
742+
sample_test_run_execution: api_models.TestRunExecutionWithChildren,
743+
sample_default_config_dict: dict,
744+
mock_json_config_file: Path,
745+
) -> None:
746+
"""--prompt-timeout takes precedence over any prompt_timeout_seconds already
747+
present in a --config file, since it's applied after the config merge."""
748+
# Arrange
749+
project_api = mock_async_apis.projects_api.default_config_api_v1_projects_default_config_get
750+
test_collection_api = mock_async_apis.test_collections_api.read_test_collections_api_v1_test_collections__get
751+
test_run_executions_api = mock_async_apis.test_run_executions_api
752+
cli_api = test_run_executions_api.create_cli_test_run_execution_api_v1_test_run_executions_cli_post
753+
id_start = test_run_executions_api.start_test_run_execution_api_v1_test_run_executions_id_start_post
754+
755+
project_api.return_value = sample_default_config_dict
756+
test_collection_api.return_value = sample_test_collections
757+
cli_api.return_value = sample_test_run_execution
758+
id_start.return_value = sample_test_run_execution
759+
with patch("th_cli.commands.run_tests.AsyncApis", return_value=mock_async_apis):
760+
with patch(
761+
"th_cli.commands.run_tests.test_logging.configure_logger_for_run", return_value="./test_logs/test.log"
762+
):
763+
with patch("th_cli.commands.run_tests.TestRunSocket") as mock_socket_class:
764+
with patch(
765+
"th_cli.commands.run_tests.convert_nested_to_dict", return_value=sample_default_config_dict
766+
):
767+
mock_socket = Mock()
768+
mock_socket.connect_websocket = AsyncMock()
769+
mock_socket_class.return_value = mock_socket
770+
771+
# Act
772+
result = cli_runner.invoke(
773+
run_tests,
774+
[
775+
"--tests-list",
776+
"TC-ACE-1.1",
777+
"--config",
778+
str(mock_json_config_file),
779+
"--prompt-timeout",
780+
"45",
781+
],
782+
)
783+
784+
# Assert
785+
assert result.exit_code == 0
786+
submitted_body = cli_api.call_args[0][0]
787+
assert submitted_body.execution_config["th_config"]["prompt_timeout_seconds"] == 45
788+
692789
@pytest.mark.parametrize(
693790
"invalid_test_id",
694791
[

tests/test_utils.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,23 @@ def test_merge_configs_nested(self) -> None:
573573
assert result["network"]["thread"]["channel"] == 15 # Preserved
574574
assert result["dut_config"]["pairing_mode"] == "onnetwork" # Preserved
575575

576+
def test_merge_configs_th_config_override(self) -> None:
577+
"""Test merging a partial th_config override, as used by --prompt-timeout."""
578+
# Arrange
579+
base = {
580+
"network": {"wifi": {"ssid": "default", "password": "default"}},
581+
"th_config": {"prompt_timeout_seconds": 60, "enable_realtime_python_test_logs": None},
582+
}
583+
override = {"th_config": {"prompt_timeout_seconds": 300}}
584+
585+
# Act
586+
result = merge_configs(base, override)
587+
588+
# Assert
589+
assert result["th_config"]["prompt_timeout_seconds"] == 300
590+
assert result["th_config"]["enable_realtime_python_test_logs"] is None # Preserved
591+
assert result["network"]["wifi"]["ssid"] == "default" # Preserved
592+
576593
def test_merge_configs_deep_nesting(self) -> None:
577594
"""Test deeply nested configuration merging."""
578595
# Arrange

th_cli/commands/run_tests.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,14 @@
127127
is_flag=True,
128128
help=colorize_help("Disable real-time log streaming via web browser (enabled by default)."),
129129
)
130+
@click.option(
131+
"--prompt-timeout",
132+
type=int,
133+
help=colorize_help(
134+
"Override the user-prompt response timeout in seconds for this run only "
135+
"(th_config.prompt_timeout_seconds)."
136+
),
137+
)
130138
@async_cmd
131139
@click.pass_context
132140
async def run_tests(
@@ -139,6 +147,7 @@ async def run_tests(
139147
project_id: int | None = None,
140148
no_color: bool = False,
141149
no_streaming: bool = False,
150+
prompt_timeout: int | None = None,
142151
) -> None:
143152
"""Execute a CLI test run from selected test cases.
144153
@@ -151,6 +160,7 @@ async def run_tests(
151160
tc_params_file: Optional path to TC parameters mapping JSON file
152161
project_id: Optional project ID for the test run
153162
no_color: Flag to disable colored output
163+
prompt_timeout: Optional override for the user-prompt response timeout (seconds)
154164
155165
Raises:
156166
CLIError: If there are validation or execution errors
@@ -271,6 +281,13 @@ async def run_tests(
271281
test_run_config["test_parameters"] = {}
272282
test_run_config["test_parameters"].update(extra_test_params)
273283

284+
# Override the user-prompt timeout if provided (execution-only, not persisted)
285+
if prompt_timeout is not None:
286+
click.echo(colorize_key_value("Prompt Timeout Used (Execution Only)", f"{prompt_timeout}s"))
287+
test_run_config = merge_configs(
288+
test_run_config, {"th_config": {"prompt_timeout_seconds": prompt_timeout}}
289+
)
290+
274291
# Retrieve available test collections to build test selection
275292
test_collections = await test_collections_api.read_test_collections_api_v1_test_collections__get()
276293
selected_tests_dict = build_test_selection(test_collections, validated_test_ids)

0 commit comments

Comments
 (0)