From 5c95c6dc427adcbfc4822bbe8ad9c463cc4587bd Mon Sep 17 00:00:00 2001 From: Molecule AI QA Engineer Date: Fri, 17 Apr 2026 10:08:45 +0000 Subject: [PATCH] test: add _load_config_dict coverage for issue #652 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cover the four paths that were exercised only via mock in the _build_options tests: valid YAML, missing file, malformed YAML, and empty file (safe_load → None → {} via `or {}`). Co-Authored-By: Claude Sonnet 4.6 --- .../tests/test_claude_sdk_executor.py | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/workspace-template/tests/test_claude_sdk_executor.py b/workspace-template/tests/test_claude_sdk_executor.py index d4f8fd69..e3781ad9 100644 --- a/workspace-template/tests/test_claude_sdk_executor.py +++ b/workspace-template/tests/test_claude_sdk_executor.py @@ -1153,3 +1153,56 @@ def test_build_options_task_budget_below_minimum_raises_value_error(): patch("claude_sdk_executor.get_mcp_server_path", return_value="/mcp.py"): with pytest.raises(ValueError, match="task_budget must be >= 20000"): e._build_options() + + +# --------------------------------------------------------------------------- +# _load_config_dict — exception-safety and happy-path (issue #652) +# --------------------------------------------------------------------------- + + +def test_load_config_dict_reads_valid_yaml(tmp_path): + """Valid config.yaml → returns the parsed dict. + + Acceptance criterion: normal I/O path returns the YAML contents as a dict. + """ + cfg = tmp_path / "config.yaml" + cfg.write_text("effort: xhigh\ntask_budget: 50000\n") + e = ClaudeSDKExecutor(system_prompt=None, config_path=str(tmp_path), heartbeat=None) + result = e._load_config_dict() + assert result == {"effort": "xhigh", "task_budget": 50000} + + +def test_load_config_dict_missing_file_returns_empty(tmp_path): + """Missing config.yaml → returns {} without raising. + + Acceptance criterion: FileNotFoundError is swallowed; callers can safely + use .get() without guards. + """ + e = ClaudeSDKExecutor(system_prompt=None, config_path=str(tmp_path), heartbeat=None) + result = e._load_config_dict() + assert result == {} + + +def test_load_config_dict_invalid_yaml_returns_empty(tmp_path): + """Malformed YAML → returns {} without raising. + + Acceptance criterion: a YAML parse error is swallowed; callers never see + an exception from _load_config_dict. + """ + cfg = tmp_path / "config.yaml" + cfg.write_text("effort: [unclosed\n") + e = ClaudeSDKExecutor(system_prompt=None, config_path=str(tmp_path), heartbeat=None) + result = e._load_config_dict() + assert result == {} + + +def test_load_config_dict_empty_file_returns_empty(tmp_path): + """Empty config.yaml (yaml.safe_load returns None) → returns {} via `or {}`. + + Acceptance criterion: None from safe_load is normalised to an empty dict. + """ + cfg = tmp_path / "config.yaml" + cfg.write_text("") + e = ClaudeSDKExecutor(system_prompt=None, config_path=str(tmp_path), heartbeat=None) + result = e._load_config_dict() + assert result == {}